@@ -24,7 +24,7 @@ var _self = (typeof window !== 'undefined')
2424var Prism = ( function ( _self ) {
2525
2626 // Private helper vars
27- var lang = / \b l a n g (?: u a g e ) ? - ( [ \w - ] + ) \b / i;
27+ var lang = / (?: ^ | \s ) l a n g (?: u a g e ) ? - ( [ \w - ] + ) (? = \s | $ ) / i;
2828 var uniqueId = 0 ;
2929
3030 // The grammar object for plaintext
@@ -54,6 +54,27 @@ var Prism = (function (_self) {
5454 * @public
5555 */
5656 manual : _self . Prism && _self . Prism . manual ,
57+ /**
58+ * By default, if Prism is in a web worker, it assumes that it is in a worker it created itself, so it uses
59+ * `addEventListener` to communicate with its parent instance. However, if you're using Prism manually in your
60+ * own worker, you don't want it to do this.
61+ *
62+ * By setting this value to `true`, Prism will not add its own listeners to the worker.
63+ *
64+ * You obviously have to change this value before Prism executes. To do this, you can add an
65+ * empty Prism object into the global scope before loading the Prism script like this:
66+ *
67+ * ```js
68+ * window.Prism = window.Prism || {};
69+ * Prism.disableWorkerMessageHandler = true;
70+ * // Load Prism's script
71+ * ```
72+ *
73+ * @default false
74+ * @type {boolean }
75+ * @memberof Prism
76+ * @public
77+ */
5778 disableWorkerMessageHandler : _self . Prism && _self . Prism . disableWorkerMessageHandler ,
5879
5980 /**
@@ -168,15 +189,33 @@ var Prism = (function (_self) {
168189 * @returns {string }
169190 */
170191 getLanguage : function ( element ) {
171- while ( element && ! lang . test ( element . className ) ) {
192+ while ( element ) {
193+ var m = lang . exec ( element . className ) ;
194+ if ( m ) {
195+ return m [ 1 ] . toLowerCase ( ) ;
196+ }
172197 element = element . parentElement ;
173198 }
174- if ( element ) {
175- return ( element . className . match ( lang ) || [ , 'none' ] ) [ 1 ] . toLowerCase ( ) ;
176- }
177199 return 'none' ;
178200 } ,
179201
202+ /**
203+ * Sets the Prism `language-xxxx` class of the given element.
204+ *
205+ * @param {Element } element
206+ * @param {string } language
207+ * @returns {void }
208+ */
209+ setLanguage : function ( element , language ) {
210+ // remove all `language-xxxx` classes
211+ // (this might leave behind a leading space)
212+ element . className = element . className . replace ( RegExp ( lang , 'gi' ) , '' ) ;
213+
214+ // add the new `language-xxxx` class
215+ // (using `classList` will automatically clean up spaces for us)
216+ element . classList . add ( 'language-' + language ) ;
217+ } ,
218+
180219 /**
181220 * Returns the script element that is currently executing.
182221 *
@@ -531,12 +570,12 @@ var Prism = (function (_self) {
531570 var grammar = _ . languages [ language ] ;
532571
533572 // Set language on the element, if not present
534- element . className = element . className . replace ( lang , '' ) . replace ( / \s + / g , ' ' ) + ' language-' + language ;
573+ _ . util . setLanguage ( element , language ) ;
535574
536575 // Set language on the parent, for styling
537576 var parent = element . parentElement ;
538577 if ( parent && parent . nodeName . toLowerCase ( ) === 'pre' ) {
539- parent . className = parent . className . replace ( lang , '' ) . replace ( / \s + / g , ' ' ) + ' language-' + language ;
578+ _ . util . setLanguage ( parent , language ) ;
540579 }
541580
542581 var code = element . textContent ;
@@ -931,7 +970,7 @@ var Prism = (function (_self) {
931970
932971 if ( greedy ) {
933972 match = matchPattern ( pattern , pos , text , lookbehind ) ;
934- if ( ! match ) {
973+ if ( ! match || match . index >= text . length ) {
935974 break ;
936975 }
937976
@@ -1507,14 +1546,14 @@ Prism.languages.clike = {
15071546 greedy : true
15081547 } ,
15091548 'class-name' : {
1510- pattern : / ( \b (?: c l a s s | i n t e r f a c e | e x t e n d s | i m p l e m e n t s | t r a i t | i n s t a n c e o f | n e w ) \s + | \b c a t c h \s + \( ) [ \w . \\ ] + / i,
1549+ pattern : / ( \b (?: c l a s s | e x t e n d s | i m p l e m e n t s | i n s t a n c e o f | i n t e r f a c e | n e w | t r a i t ) \s + | \b c a t c h \s + \( ) [ \w . \\ ] + / i,
15111550 lookbehind : true ,
15121551 inside : {
15131552 'punctuation' : / [ . \\ ] /
15141553 }
15151554 } ,
1516- 'keyword' : / \b (?: i f | e l s e | w h i l e | d o | f o r | r e t u r n | i n | i n s t a n c e o f | f u n c t i o n | n e w | t r y | t h r o w | c a t c h | f i n a l l y | n u l l | b r e a k | c o n t i n u e ) \b / ,
1517- 'boolean' : / \b (?: t r u e | f a l s e ) \b / ,
1555+ 'keyword' : / \b (?: b r e a k | c a t c h | c o n t i n u e | d o | e l s e | f i n a l l y | f o r | f u n c t i o n | i f | i n | i n s t a n c e o f | n e w | n u l l | r e t u r n | t h r o w | t r y | w h i l e ) \b / ,
1556+ 'boolean' : / \b (?: f a l s e | t r u e ) \b / ,
15181557 'function' : / \b \w + (? = \( ) / ,
15191558 'number' : / \b 0 x [ \d a - f ] + \b | (?: \b \d + (?: \. \d * ) ? | \B \. \d + ) (?: e [ + - ] ? \d + ) ? / i,
15201559 'operator' : / [ < > ] = ? | [ ! = ] = ? = ? | - - ? | \+ \+ ? | & & ? | \| \| ? | [ ? * / ~ ^ % ] / ,
@@ -1530,7 +1569,7 @@ Prism.languages.javascript = Prism.languages.extend('clike', {
15301569 'class-name' : [
15311570 Prism . languages . clike [ 'class-name' ] ,
15321571 {
1533- pattern : / ( ^ | [ ^ $ \w \xA0 - \uFFFF ] ) (? ! \s ) [ _ $ A - Z \xA0 - \uFFFF ] (?: (? ! \s ) [ $ \w \xA0 - \uFFFF ] ) * (? = \. (?: p r o t o t y p e | c o n s t r u c t o r ) ) / ,
1572+ pattern : / ( ^ | [ ^ $ \w \xA0 - \uFFFF ] ) (? ! \s ) [ _ $ A - Z \xA0 - \uFFFF ] (?: (? ! \s ) [ $ \w \xA0 - \uFFFF ] ) * (? = \. (?: c o n s t r u c t o r | p r o t o t y p e ) ) / ,
15341573 lookbehind : true
15351574 }
15361575 ] ,
@@ -1546,11 +1585,38 @@ Prism.languages.javascript = Prism.languages.extend('clike', {
15461585 ] ,
15471586 // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
15481587 'function' : / # ? (? ! \s ) [ _ $ a - z A - Z \xA0 - \uFFFF ] (?: (? ! \s ) [ $ \w \xA0 - \uFFFF ] ) * (? = \s * (?: \. \s * (?: a p p l y | b i n d | c a l l ) \s * ) ? \( ) / ,
1549- 'number' : / \b (?: (?: 0 [ x X ] (?: [ \d A - F a - f ] (?: _ [ \d A - F a - f ] ) ? ) + | 0 [ b B ] (?: [ 0 1 ] (?: _ [ 0 1 ] ) ? ) + | 0 [ o O ] (?: [ 0 - 7 ] (?: _ [ 0 - 7 ] ) ? ) + ) n ? | (?: \d (?: _ \d ) ? ) + n | N a N | I n f i n i t y ) \b | (?: \b (?: \d (?: _ \d ) ? ) + \. ? (?: \d (?: _ \d ) ? ) * | \B \. (?: \d (?: _ \d ) ? ) + ) (?: [ E e ] [ + - ] ? (?: \d (?: _ \d ) ? ) + ) ? / ,
1588+ 'number' : {
1589+ pattern : RegExp (
1590+ / ( ^ | [ ^ \w $ ] ) / . source +
1591+ '(?:' +
1592+ (
1593+ // constant
1594+ / N a N | I n f i n i t y / . source +
1595+ '|' +
1596+ // binary integer
1597+ / 0 [ b B ] [ 0 1 ] + (?: _ [ 0 1 ] + ) * n ? / . source +
1598+ '|' +
1599+ // octal integer
1600+ / 0 [ o O ] [ 0 - 7 ] + (?: _ [ 0 - 7 ] + ) * n ? / . source +
1601+ '|' +
1602+ // hexadecimal integer
1603+ / 0 [ x X ] [ \d A - F a - f ] + (?: _ [ \d A - F a - f ] + ) * n ? / . source +
1604+ '|' +
1605+ // decimal bigint
1606+ / \d + (?: _ \d + ) * n / . source +
1607+ '|' +
1608+ // decimal number (integer or float) but no bigint
1609+ / (?: \d + (?: _ \d + ) * (?: \. (?: \d + (?: _ \d + ) * ) ? ) ? | \. \d + (?: _ \d + ) * ) (?: [ E e ] [ + - ] ? \d + (?: _ \d + ) * ) ? / . source
1610+ ) +
1611+ ')' +
1612+ / (? ! [ \w $ ] ) / . source
1613+ ) ,
1614+ lookbehind : true
1615+ } ,
15501616 'operator' : / - - | \+ \+ | \* \* = ? | = > | & & = ? | \| \| = ? | [ ! = ] = = | < < = ? | > > > ? = ? | [ - + * / % & | ^ ! = < > ] = ? | \. { 3 } | \? \? = ? | \? \. ? | [ ~ : ] /
15511617} ) ;
15521618
1553- Prism . languages . javascript [ 'class-name' ] [ 0 ] . pattern = / ( \b (?: c l a s s | i n t e r f a c e | e x t e n d s | i m p l e m e n t s | i n s t a n c e o f | n e w ) \s + ) [ \w . \\ ] + / ;
1619+ Prism . languages . javascript [ 'class-name' ] [ 0 ] . pattern = / ( \b (?: c l a s s | e x t e n d s | i m p l e m e n t s | i n s t a n c e o f | i n t e r f a c e | n e w ) \s + ) [ \w . \\ ] + / ;
15541620
15551621Prism . languages . insertBefore ( 'javascript' , 'keyword' , {
15561622 'regex' : {
@@ -1626,9 +1692,23 @@ Prism.languages.insertBefore('javascript', 'string', {
16261692 } ,
16271693 'string' : / [ \s \S ] + /
16281694 }
1695+ } ,
1696+ 'string-property' : {
1697+ pattern : / ( (?: ^ | [ , { ] ) [ \t ] * ) ( [ " ' ] ) (?: \\ (?: \r \n | [ \s \S ] ) | (? ! \2) [ ^ \\ \r \n ] ) * \2(? = \s * : ) / m,
1698+ lookbehind : true ,
1699+ greedy : true ,
1700+ alias : 'property'
16291701 }
16301702} ) ;
16311703
1704+ Prism . languages . insertBefore ( 'javascript' , 'operator' , {
1705+ 'literal-property' : {
1706+ pattern : / ( (?: ^ | [ , { ] ) [ \t ] * ) (? ! \s ) [ _ $ a - z A - Z \xA0 - \uFFFF ] (?: (? ! \s ) [ $ \w \xA0 - \uFFFF ] ) * (? = \s * : ) / m,
1707+ lookbehind : true ,
1708+ alias : 'property'
1709+ } ,
1710+ } ) ;
1711+
16321712if ( Prism . languages . markup ) {
16331713 Prism . languages . markup . tag . addInlined ( 'script' , 'javascript' ) ;
16341714
@@ -1684,21 +1764,57 @@ Prism.languages.js = Prism.languages.javascript;
16841764 var SELECTOR = 'pre[data-src]:not([' + STATUS_ATTR + '="' + STATUS_LOADED + '"])'
16851765 + ':not([' + STATUS_ATTR + '="' + STATUS_LOADING + '"])' ;
16861766
1687- var lang = / \b l a n g (?: u a g e ) ? - ( [ \w - ] + ) \b / i;
1688-
16891767 /**
1690- * Sets the Prism `language-xxxx` or `lang-xxxx` class to the given language .
1768+ * Loads the given file .
16911769 *
1692- * @param {HTMLElement } element
1693- * @param {string } language
1694- * @returns { void }
1770+ * @param {string } src The URL or path of the source file to load.
1771+ * @param {(result: string) => void } success
1772+ * @param { (reason: string) => void } error
16951773 */
1696- function setLanguageClass ( element , language ) {
1697- var className = element . className ;
1698- className = className . replace ( lang , ' ' ) + ' language-' + language ;
1699- element . className = className . replace ( / \s + / g, ' ' ) . trim ( ) ;
1774+ function loadFile ( src , success , error ) {
1775+ var xhr = new XMLHttpRequest ( ) ;
1776+ xhr . open ( 'GET' , src , true ) ;
1777+ xhr . onreadystatechange = function ( ) {
1778+ if ( xhr . readyState == 4 ) {
1779+ if ( xhr . status < 400 && xhr . responseText ) {
1780+ success ( xhr . responseText ) ;
1781+ } else {
1782+ if ( xhr . status >= 400 ) {
1783+ error ( FAILURE_MESSAGE ( xhr . status , xhr . statusText ) ) ;
1784+ } else {
1785+ error ( FAILURE_EMPTY_MESSAGE ) ;
1786+ }
1787+ }
1788+ }
1789+ } ;
1790+ xhr . send ( null ) ;
17001791 }
17011792
1793+ /**
1794+ * Parses the given range.
1795+ *
1796+ * This returns a range with inclusive ends.
1797+ *
1798+ * @param {string | null | undefined } range
1799+ * @returns {[number, number | undefined] | undefined }
1800+ */
1801+ function parseRange ( range ) {
1802+ var m = / ^ \s * ( \d + ) \s * (?: ( , ) \s * (?: ( \d + ) \s * ) ? ) ? $ / . exec ( range || '' ) ;
1803+ if ( m ) {
1804+ var start = Number ( m [ 1 ] ) ;
1805+ var comma = m [ 2 ] ;
1806+ var end = m [ 3 ] ;
1807+
1808+ if ( ! comma ) {
1809+ return [ start , start ] ;
1810+ }
1811+ if ( ! end ) {
1812+ return [ start , undefined ] ;
1813+ }
1814+ return [ start , Number ( end ) ] ;
1815+ }
1816+ return undefined ;
1817+ }
17021818
17031819 Prism . hooks . add ( 'before-highlightall' , function ( env ) {
17041820 env . selector += ', ' + SELECTOR ;
@@ -1726,8 +1842,8 @@ Prism.languages.js = Prism.languages.javascript;
17261842 }
17271843
17281844 // set language classes
1729- setLanguageClass ( code , language ) ;
1730- setLanguageClass ( pre , language ) ;
1845+ Prism . util . setLanguage ( code , language ) ;
1846+ Prism . util . setLanguage ( pre , language ) ;
17311847
17321848 // preload the language
17331849 var autoloader = Prism . plugins . autoloader ;
@@ -1736,31 +1852,45 @@ Prism.languages.js = Prism.languages.javascript;
17361852 }
17371853
17381854 // load file
1739- var xhr = new XMLHttpRequest ( ) ;
1740- xhr . open ( 'GET' , src , true ) ;
1741- xhr . onreadystatechange = function ( ) {
1742- if ( xhr . readyState == 4 ) {
1743- if ( xhr . status < 400 && xhr . responseText ) {
1744- // mark as loaded
1745- pre . setAttribute ( STATUS_ATTR , STATUS_LOADED ) ;
1746-
1747- // highlight code
1748- code . textContent = xhr . responseText ;
1749- Prism . highlightElement ( code ) ;
1750-
1751- } else {
1752- // mark as failed
1753- pre . setAttribute ( STATUS_ATTR , STATUS_FAILED ) ;
1754-
1755- if ( xhr . status >= 400 ) {
1756- code . textContent = FAILURE_MESSAGE ( xhr . status , xhr . statusText ) ;
1757- } else {
1758- code . textContent = FAILURE_EMPTY_MESSAGE ;
1855+ loadFile (
1856+ src ,
1857+ function ( text ) {
1858+ // mark as loaded
1859+ pre . setAttribute ( STATUS_ATTR , STATUS_LOADED ) ;
1860+
1861+ // handle data-range
1862+ var range = parseRange ( pre . getAttribute ( 'data-range' ) ) ;
1863+ if ( range ) {
1864+ var lines = text . split ( / \r \n ? | \n / g) ;
1865+
1866+ // the range is one-based and inclusive on both ends
1867+ var start = range [ 0 ] ;
1868+ var end = range [ 1 ] == null ? lines . length : range [ 1 ] ;
1869+
1870+ if ( start < 0 ) { start += lines . length ; }
1871+ start = Math . max ( 0 , Math . min ( start - 1 , lines . length ) ) ;
1872+ if ( end < 0 ) { end += lines . length ; }
1873+ end = Math . max ( 0 , Math . min ( end , lines . length ) ) ;
1874+
1875+ text = lines . slice ( start , end ) . join ( '\n' ) ;
1876+
1877+ // add data-start for line numbers
1878+ if ( ! pre . hasAttribute ( 'data-start' ) ) {
1879+ pre . setAttribute ( 'data-start' , String ( start + 1 ) ) ;
17591880 }
17601881 }
1882+
1883+ // highlight code
1884+ code . textContent = text ;
1885+ Prism . highlightElement ( code ) ;
1886+ } ,
1887+ function ( error ) {
1888+ // mark as failed
1889+ pre . setAttribute ( STATUS_ATTR , STATUS_FAILED ) ;
1890+
1891+ code . textContent = error ;
17611892 }
1762- } ;
1763- xhr . send ( null ) ;
1893+ ) ;
17641894 }
17651895 } ) ;
17661896
0 commit comments