forked from PrismJS/prism
-
Notifications
You must be signed in to change notification settings - Fork 0
/
faq.html
235 lines (197 loc) · 8.74 KB
/
faq.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="favicon.png" />
<title>FAQ ▲ Prism</title>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="themes/prism.css" data-noprefix />
<style>
#toc {
display: block;
position: static;
max-width: 900px;
font-size: 100%;
color: black;
}
</style>
<script src="scripts/prefixfree.min.js"></script>
<script>var _gaq = [['_setAccount', 'UA-33746269-1'], ['_trackPageview']];</script>
<script src="https://www.google-analytics.com/ga.js" async></script>
</head>
<body>
<header>
<div class="intro" data-src="templates/header-main.html" data-type="text/html"></div>
<h2>FAQ</h2>
<p>Frequently Asked Questions, with a few Questions I want people to Frequently Ask.</p>
</header>
<section>
<h1>This page doesn’t work in Opera!</h1>
<p><strong>Prism works fine in Opera.</strong> However, this page might sometimes appear to not be working in Opera, due to the theme switcher triggering an Opera bug.
This will be fixed soon.</p>
</section>
<section>
<h1>Isn’t it bad to do syntax highlighting with regular expressions?</h1>
<p>It is true that to correctly handle every possible case of syntax found in the wild, one would need to write a full-blown parser.
However, in most web applications and websites a small error margin is usually acceptable and a rare highlighting failure is not the end of the world.
A syntax highlighter based on regular expressions might only be accurate 99% of the time (the actual percentage is just a guess),
but in exchange for the small error margin, it offers some very important benefits:
<ul>
<li>Smaller filesize. Proper parsers are very big.</li>
<li>Extensibility. Authors can define new languages simply by knowing how to code regular expressions.
Writing a correct, unambiguous BNF grammar is a task at least an order of magnitude harder.</li>
<li>Graceful error recovery. Parsers fail on incorrect syntax, where regular expressions keep matching.</li>
</ul>
<p>For this reason, most syntax highlighters on the web and on desktop, are powered by regular expressions. This includes the internal syntax
highlighters used by popular native applications like Espresso and Sublime Text, at the time of writing.
Of course, not every regex-powered syntax highlighter is created equal. The number and type of failures can be vastly different, depending on
the exact algorithm used. <a href="known-failures.html">Prism’s known failures are documented on this page.</a>.</p>
</section>
<section>
<h1>Why is asynchronous highlighting disabled by default?</h1>
<p>Web Workers are good for preventing syntax highlighting of really large code blocks from blocking the main UI thread.
In most cases, you will want to highlight reasonably sized chunks of code, and this will not be needed.
Furthermore, using Web Workers is actually <strong>slower</strong> than synchronously highlighting, due to the overhead of creating and terminating
the Worker. It just appears faster in these cases because it doesn’t block the main thread.
In addition, since Web Workers operate on files instead of objects, plugins that hook on core parts of Prism (e.g. modify language definitions)
will not work unless included in the same file (using the builder in the <a href="download.html">Download</a> page will protect you from this pitfall).
Lastly, Web Workers cannot interact with the DOM and most other APIs (e.g. the console), so they are notoriously hard to debug.
</p>
</section>
<section>
<h1>Why is pre-existing HTML stripped off?</h1>
<p>Because it would complicate the code a lot, although it’s not a crucial feature for most people.
If it’s very important to you, you can use the <a href="plugins/keep-markup/">Keep Markup plugin</a>.</p>
</section>
<section>
<h1>If pre-existing HTML is stripped off, how can I highlight certain parts of the code?</h1>
<p>There is a number of ways around it. You can always break the block of code into multiple parts, and wrap the HTML around it (or just use a <code>.highlight</code> class).
You can see an example of this in action at the “<a href="index.html#basic-usage">Basic usage</a>” section of the homepage.</p>
<p>Another way around the limitation is to use the <a href="plugins/line-highlight/">Line Highlght plugin</a>, to highlight and link to specific lines and/or line ranges.
</section>
<section>
<h1>How do I know which tokens I can style for every language?</h1>
<p>Every token that is highlighted gets at least two classes: <code>token</code> and a class with the token type (e.g. <code>comment</code>) plus any number of aliases.
Aliases can be seen as additional token types and are used to give specialized tokens a more common class for easier styling.
You can find the different types of tokens either by looking at the keys of the object defining the language or by using the below interface.</p>
<p>Language: <select id="language-select"></select></p>
<pre class="language-none" style="height: 30em"><code id="print-tokens-output"></code></pre>
</section>
<section>
<h1>How can I use different highlighting for tokens with the same name in different languages?</h1>
<p>Just use a descendant selector, that includes the language class. The default <code>prism.css</code> does this, to have different colors for
JavaScript strings (which are very common) and CSS strings (which are relatively rare). Here’s that code, simplified to illustrate the technique:
<pre><code class="language-css">
.token.string {
color: #690;
}
.language-css .token.string,
.style .token.string {
color: #a67f59;
}</code></pre>
<p>Abbreviated language classes (e.g. <code>lang-css</code>) will be converted to their extended forms, so you don’t need to account for them.</p>
<p>The same technique can be used to differentiate XML tag namespaces from attribute namespaces:</p>
<pre><code class="language-css">.tag > .token.namespace {
color: #b37298;
}
.attr-name > .token.namespace {
color: #ab6;
}</code></pre>
</section>
<footer data-src="templates/footer.html" data-type="text/html"></footer>
<script src="scripts/utopia.js"></script>
<script src="prism.js"></script>
<script src="plugins/autoloader/prism-autoloader.min.js"></script>
<script>
Prism.plugins.autoloader.languages_path = 'components/';
</script>
<script src="components.js"></script>
<script>
(function () {
$$('section > h1').forEach(function (h1) {
$u.element.create('p', {
contents: {
tag: 'a',
properties: {
href: '#toc'
},
contents: '↑ Back to top'
},
inside: h1.parentNode
});
});
function printTokens(grammar) {
function toArray(x) {
return Array.isArray(x) ? x : (x == undefined ? [] : [x]);
}
var lines = [];
function log(line) {
if (lines.indexOf(line) === -1) {
lines.push(line);
}
}
var languageMap = new Map();
Object.keys(Prism.languages).filter(function (l) { return l in components.languages; }).forEach(function (l) {
languageMap.set(Prism.languages[l], 'Prism.languages["' + l + '"]');
});
var stack = new Map();
function inner(g, prefix) {
if (prefix && languageMap.has(g)) {
log(prefix + ' > ...' + languageMap.get(g));
return;
}
if (stack.has(g)) {
log(prefix + ' > ...' + stack.get(g));
return;
}
stack.set(g, '(' + (prefix || ':root:') + ')');
for (var name in g) {
var element = g[name];
if (name === 'rest') {
inner(element, (prefix ? prefix + ' > ' : '') + ':rest:');
} else {
for (var a = toArray(element), i = 0, token; token = a[i++];) {
var line = (prefix ? prefix + ' > ' : '') + name + toArray(token.alias).map(function (a) {
return '.' + a;
}).join('');
log(line);
if (token.inside) {
inner(token.inside, line);
}
}
}
}
stack.delete(g);
}
inner(grammar, '');
return lines.join('\n');
}
var loadedLanguages = {};
function showTokens() {
var language = $('#language-select').value;
if (Prism.languages[language]) {
$('#print-tokens-output').textContent = printTokens(Prism.languages[language]);
} else if (language in loadedLanguages) {
$('#print-tokens-output').textContent = '"' + language + '" doesn\'t have any tokens.';
} else {
// load grammar
Prism.plugins.autoloader.loadLanguages([language], function() {
loadedLanguages[language] = true;
showTokens();
}, function () {
$('#print-tokens-output').textContent = 'Unable to load "' + language + '"';
});
}
}
$('#language-select').onchange = showTokens;
$('#language-select').innerHTML = Object.keys(components.languages)
.filter(function (x) { return x !== 'meta'; })
.map(function (x) {
return '<option value="' + x + '">' + components.languages[x].title + '</option>';
}).join('');
showTokens();
}());
</script>
<script src="scripts/code.js"></script>
</body>
</html>