text.length) {
127 | // Something went terribly wrong, ABORT, ABORT!
128 | break tokenloop;
129 | }
130 |
131 | if (str instanceof Token) {
132 | continue;
133 | }
134 |
135 | pattern.lastIndex = 0;
136 |
137 | var match = pattern.exec(str);
138 |
139 | if (match) {
140 | if(lookbehind) {
141 | lookbehindLength = match[1].length;
142 | }
143 |
144 | var from = match.index - 1 + lookbehindLength,
145 | match = match[0].slice(lookbehindLength),
146 | len = match.length,
147 | to = from + len,
148 | before = str.slice(0, from + 1),
149 | after = str.slice(to + 1);
150 |
151 | var args = [i, 1];
152 |
153 | if (before) {
154 | args.push(before);
155 | }
156 |
157 | var wrapped = new Token(token, inside? _.tokenize(match, inside) : match);
158 |
159 | args.push(wrapped);
160 |
161 | if (after) {
162 | args.push(after);
163 | }
164 |
165 | Array.prototype.splice.apply(strarr, args);
166 | }
167 | }
168 | }
169 |
170 | return strarr;
171 | },
172 |
173 | hooks: {
174 | all: {},
175 |
176 | add: function (name, callback) {
177 | var hooks = _.hooks.all;
178 |
179 | hooks[name] = hooks[name] || [];
180 |
181 | hooks[name].push(callback);
182 | },
183 |
184 | run: function (name, env) {
185 | var callbacks = _.hooks.all[name];
186 |
187 | if (!callbacks || !callbacks.length) {
188 | return;
189 | }
190 |
191 | for (var i=0, callback; callback = callbacks[i++];) {
192 | callback(env);
193 | }
194 | }
195 | }
196 | };
197 |
198 | var Token = _.Token = function(type, content) {
199 | this.type = type;
200 | this.content = content;
201 | };
202 |
203 | Token.reactify = function(o) {
204 | if (typeof o == 'string') {
205 | return o;
206 | }
207 |
208 | if (Array.isArray(o)) {
209 | return o.map(function(element) {
210 | return Token.reactify(element);
211 | });
212 | }
213 |
214 | var attributes = {
215 | className: 'token ' + o.type
216 | }
217 | if (o.type == 'comment') {
218 | attributes.spellcheck = true;
219 | }
220 |
221 | return React.DOM.span(attributes, Token.reactify(o.content));
222 | };
223 |
224 | _.languages.markup = {
225 | 'comment': /<!--[\w\W]*?-->/g,
226 | 'prolog': /<\?.+?\?>/,
227 | 'doctype': /<!DOCTYPE.+?>/,
228 | 'cdata': /<!\[CDATA\[[\w\W]*?]]>/i,
229 | 'tag': {
230 | pattern: /<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/gi,
231 | inside: {
232 | 'tag': {
233 | pattern: /^<\/?[\w:-]+/i,
234 | inside: {
235 | 'punctuation': /^<\/?/,
236 | 'namespace': /^[\w-]+?:/
237 | }
238 | },
239 | 'attr-value': {
240 | pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,
241 | inside: {
242 | 'punctuation': /=|>|"/g
243 | }
244 | },
245 | 'punctuation': /\/?>/g,
246 | 'attr-name': {
247 | pattern: /[\w:-]+/g,
248 | inside: {
249 | 'namespace': /^[\w-]+?:/
250 | }
251 | }
252 |
253 | }
254 | },
255 | 'entity': /&#?[\da-z]{1,8};/gi
256 | };
257 |
258 | _.languages.css = {
259 | 'comment': /\/\*[\w\W]*?\*\//g,
260 | 'atrule': {
261 | pattern: /@[\w-]+?.*?(;|(?=\s*{))/gi,
262 | inside: {
263 | 'punctuation': /[;:]/g
264 | }
265 | },
266 | 'url': /url\((["']?).*?\1\)/gi,
267 | 'selector': /[^\{\}\s][^\{\};]*(?=\s*\{)/g,
268 | 'property': /(\b|\B)[\w-]+(?=\s*:)/ig,
269 | 'string': /("|')(\\?.)*?\1/g,
270 | 'important': /\B!important\b/gi,
271 | 'ignore': /&(lt|gt|amp);/gi,
272 | 'punctuation': /[\{\};:]/g
273 | };
274 |
275 | _.languages.insertBefore('markup', 'tag', {
276 | 'style': {
277 | pattern: /(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/ig,
278 | inside: {
279 | 'tag': {
280 | pattern: /(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/ig,
281 | inside: _.languages.markup.tag.inside
282 | },
283 | rest: _.languages.css
284 | }
285 | }
286 | });
287 |
288 | _.languages.clike = {
289 | 'comment': {
290 | pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,
291 | lookbehind: true
292 | },
293 | 'string': /("|')(\\?.)*?\1/g,
294 | 'class-name': {
295 | pattern: /((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig,
296 | lookbehind: true,
297 | inside: {
298 | punctuation: /(\.|\\)/
299 | }
300 | },
301 | 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,
302 | 'boolean': /\b(true|false)\b/g,
303 | 'function': {
304 | pattern: /[a-z0-9_]+\(/ig,
305 | inside: {
306 | punctuation: /\(/
307 | }
308 | },
309 | 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,
310 | 'operator': /[-+]{1,2}|!|<=?|>=?|={1,3}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,
311 | 'ignore': /&(lt|gt|amp);/gi,
312 | 'punctuation': /[{}[\];(),.:]/g
313 | };
314 |
315 | _.languages.javascript = _.languages.extend('clike', {
316 | 'keyword': /\b(class|extends|var|let|if|else|while|do|for|return|in|instanceof|function|get|set|new|with|typeof|try|throw|catch|finally|null|break|continue|this)\b/g,
317 | 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g
318 | });
319 |
320 | _.languages.insertBefore('javascript', 'keyword', {
321 | 'regex': {
322 | pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,
323 | lookbehind: true
324 | }
325 | });
326 |
327 | _.languages.insertBefore('markup', 'tag', {
328 | 'script': {
329 | pattern: /(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig,
330 | inside: {
331 | 'tag': {
332 | pattern: /(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig,
333 | inside: _.languages.markup.tag.inside
334 | },
335 | rest: _.languages.javascript
336 | }
337 | }
338 | });
339 |
340 | var Prism = React.createClass({
341 | statics: {
342 | _: _
343 | },
344 | getDefaultProps: function() {
345 | return {
346 | language: 'javascript'
347 | };
348 | },
349 | render: function() {
350 | var grammar = _.languages[this.props.language];
351 | return (
352 |
353 | {Token.reactify(_.tokenize(this.props.children, grammar))}
354 |
355 | );
356 | }
357 | })
358 |
359 | module.exports = Prism;
360 |
--------------------------------------------------------------------------------