1
1
// jshint multistr:true
2
2
3
3
( function ( w , d ) {
4
- 'use strict' ;
5
-
6
- var TABLE_NAME = 'hljs-ln' ,
7
- LINE_NAME = 'hljs-ln-line' ,
8
- CODE_BLOCK_NAME = 'hljs-ln-code' ,
9
- NUMBERS_BLOCK_NAME = 'hljs-ln-numbers' ,
10
- NUMBER_LINE_NAME = 'hljs-ln-n' ,
11
- DATA_ATTR_NAME = 'data-line-number' ,
12
- BREAK_LINE_REGEXP = / \r \n | \r | \n / g;
13
-
14
- if ( w . hljs ) {
15
- w . hljs . initLineNumbersOnLoad = initLineNumbersOnLoad ;
16
- w . hljs . lineNumbersBlock = lineNumbersBlock ;
17
-
18
- addStyles ( ) ;
19
- } else {
20
- w . console . error ( 'highlight.js not detected!' ) ;
21
- }
22
-
23
- function addStyles ( ) {
24
- var css = d . createElement ( 'style' ) ;
25
- css . type = 'text/css' ;
26
- css . innerHTML = format (
27
- '.{0}{border-collapse:collapse}\
28
- .{0} td{padding:0}\
29
- .{1}:before{content:attr({2})}',
30
- [
31
- TABLE_NAME ,
32
- NUMBER_LINE_NAME ,
33
- DATA_ATTR_NAME
34
- ] ) ;
35
- d . getElementsByTagName ( 'head' ) [ 0 ] . appendChild ( css ) ;
36
- }
37
-
38
- function initLineNumbersOnLoad ( options ) {
39
- if ( d . readyState === 'complete' ) {
40
- documentReady ( options ) ;
41
- } else {
42
- w . addEventListener ( 'DOMContentLoaded' , function ( ) {
43
- documentReady ( options ) ;
44
- } ) ;
45
- }
46
- }
47
-
48
- function documentReady ( options ) {
49
- try {
50
- var blocks = d . querySelectorAll ( 'code.hljs' ) ;
51
-
52
- for ( var i in blocks ) {
53
- if ( blocks . hasOwnProperty ( i ) ) {
54
- lineNumbersBlock ( blocks [ i ] , options ) ;
55
- }
56
- }
57
- } catch ( e ) {
58
- w . console . error ( 'LineNumbers error: ' , e ) ;
59
- }
60
- }
61
-
62
- function lineNumbersBlock ( element , options ) {
63
- if ( typeof element !== 'object' ) return ;
64
-
65
- // define options or set default
66
- options = options || {
67
- singleLine : false
68
- } ;
69
-
70
- // convert options
71
- var firstLineIndex = ! ! options . singleLine ? 0 : 1 ;
72
-
73
- async ( function ( ) {
74
-
75
- duplicateMultilineNodes ( element ) ;
76
-
77
- element . innerHTML = addLineNumbersBlockFor ( element . innerHTML , firstLineIndex ) ;
78
- } ) ;
79
- }
80
-
81
- function addLineNumbersBlockFor ( inputHtml , firstLineIndex ) {
82
-
83
- var lines = getLines ( inputHtml ) ;
84
-
85
- if ( lines . length > firstLineIndex ) {
86
- var html = '' ;
87
-
88
- for ( var i = 0 , l = lines . length ; i < l ; i ++ ) {
89
- html += format (
90
- '<tr>\
91
- <td class="{0}">\
92
- <div class="{1} {2}" {3}="{5}"></div>\
93
- </td>\
94
- <td class="{4}">\
95
- <div class="{1}">{6}</div>\
96
- </td>\
97
- </tr>',
98
- [
99
- NUMBERS_BLOCK_NAME ,
100
- LINE_NAME ,
101
- NUMBER_LINE_NAME ,
102
- DATA_ATTR_NAME ,
103
- CODE_BLOCK_NAME ,
104
- i + 1 ,
105
- lines [ i ] . length > 0 ? lines [ i ] : ' '
106
- ] ) ;
107
- }
108
-
109
- return format ( '<table class="{0}">{1}</table>' , [ TABLE_NAME , html ] ) ;
110
- }
111
-
112
- return inputHtml ;
113
- }
114
-
115
- /**
116
- * Recursive method for fix multi-line elements implementation in highlight.js
117
- * Doing deep passage on child nodes.
118
- * @param {HTMLElement } element
119
- */
120
- function duplicateMultilineNodes ( element ) {
121
- var nodes = element . childNodes ;
122
- for ( var node in nodes ) {
123
- if ( nodes . hasOwnProperty ( node ) ) {
124
- var child = nodes [ node ] ;
125
- if ( getLinesCount ( child . textContent ) > 0 ) {
126
- if ( child . childNodes . length > 0 ) {
127
- duplicateMultilineNodes ( child ) ;
128
- } else {
129
- duplicateMultilineNode ( child ) ;
130
- }
131
- }
132
- }
133
- }
134
- }
135
-
136
- /**
137
- * Method for fix multi-line elements implementation in highlight.js
138
- * @param {HTMLElement } element
139
- */
140
- function duplicateMultilineNode ( element ) {
141
- var className = element . parentNode . className ;
142
-
143
- if ( ! / h l j s - / . test ( className ) ) return ;
144
-
145
- var lines = getLines ( element . textContent ) ;
146
-
147
- for ( var i = 0 , result = '' ; i < lines . length ; i ++ ) {
148
- result += format ( '<span class="{0}">{1}</span>\n' , [ className , lines [ i ] ] ) ;
149
- }
150
- element . parentNode . innerHTML = result . trim ( ) ;
151
- }
152
-
153
- function getLines ( text ) {
154
- if ( text . length === 0 ) return [ ] ;
155
- return text . split ( BREAK_LINE_REGEXP ) ;
156
- }
157
-
158
- function getLinesCount ( text ) {
159
- return ( text . trim ( ) . match ( BREAK_LINE_REGEXP ) || [ ] ) . length ;
160
- }
161
-
162
- function async ( func ) {
163
- w . setTimeout ( func , 0 ) ;
164
- }
165
-
166
- /**
167
- * {@link https://wcoder.github.io/notes/string-format-for-string-formating-in-javascript }
168
- * @param {string } format
169
- * @param {array } args
170
- */
171
- function format ( format , args ) {
172
- return format . replace ( / \{ ( \d + ) \} / g, function ( m , n ) {
173
- return args [ n ] ? args [ n ] : m ;
174
- } ) ;
175
- }
176
-
177
- } ( window , document ) ) ;
4
+ 'use strict' ;
5
+
6
+ var TABLE_NAME = 'hljs-ln' ,
7
+ LINE_NAME = 'hljs-ln-line' ,
8
+ CODE_BLOCK_NAME = 'hljs-ln-code' ,
9
+ NUMBERS_BLOCK_NAME = 'hljs-ln-numbers' ,
10
+ NUMBER_LINE_NAME = 'hljs-ln-n' ,
11
+ DATA_ATTR_NAME = 'data-line-number' ,
12
+ BREAK_LINE_REGEXP = / \r \n | \r | \n / g;
13
+
14
+ if ( w . hljs ) {
15
+ w . hljs . initLineNumbersOnLoad = initLineNumbersOnLoad ;
16
+ w . hljs . lineNumbersBlock = lineNumbersBlock ;
17
+
18
+ addStyles ( ) ;
19
+ } else {
20
+ w . console . error ( 'highlight.js not detected!' ) ;
21
+ }
22
+
23
+ function addStyles ( ) {
24
+ var css = d . createElement ( 'style' ) ;
25
+ css . type = 'text/css' ;
26
+ css . innerHTML = format (
27
+ '.{0}{border-collapse:collapse}\
28
+ .{0} td{padding:0}\
29
+ .{1}:before{content:attr({2})}',
30
+ [
31
+ TABLE_NAME ,
32
+ NUMBER_LINE_NAME ,
33
+ DATA_ATTR_NAME
34
+ ] ) ;
35
+ d . getElementsByTagName ( 'head' ) [ 0 ] . appendChild ( css ) ;
36
+ }
37
+
38
+ function initLineNumbersOnLoad ( options ) {
39
+ if ( d . readyState === 'complete' ) {
40
+ documentReady ( options ) ;
41
+ } else {
42
+ w . addEventListener ( 'DOMContentLoaded' , function ( ) {
43
+ documentReady ( options ) ;
44
+ } ) ;
45
+ }
46
+ }
47
+
48
+ function documentReady ( options ) {
49
+ try {
50
+ var blocks = d . querySelectorAll ( 'code.hljs' ) ;
51
+
52
+ for ( var i in blocks ) {
53
+ if ( blocks . hasOwnProperty ( i ) ) {
54
+ lineNumbersBlock ( blocks [ i ] , options ) ;
55
+ }
56
+ }
57
+ } catch ( e ) {
58
+ w . console . error ( 'LineNumbers error: ' , e ) ;
59
+ }
60
+ }
61
+
62
+ function lineNumbersBlock ( element , options ) {
63
+ if ( typeof element !== 'object' ) return ;
64
+
65
+ // define options or set default
66
+ options = options || {
67
+ singleLine : false
68
+ } ;
69
+
70
+ // convert options
71
+ var firstLineIndex = ! ! options . singleLine ? 0 : 1 ;
72
+
73
+ async ( function ( ) {
74
+
75
+ duplicateMultilineNodes ( element ) ;
76
+
77
+ element . innerHTML = addLineNumbersBlockFor ( element . innerHTML , firstLineIndex ) ;
78
+ } ) ;
79
+ }
80
+
81
+ function addLineNumbersBlockFor ( inputHtml , firstLineIndex ) {
82
+
83
+ var lines = getLines ( inputHtml ) ;
84
+
85
+ if ( lines . length > firstLineIndex ) {
86
+ var html = '' ;
87
+
88
+ for ( var i = 0 , l = lines . length ; i < l ; i ++ ) {
89
+ html += format (
90
+ '<tr>\
91
+ <td class="{0}">\
92
+ <div class="{1} {2}" {3}="{5}"></div>\
93
+ </td>\
94
+ <td class="{4}">\
95
+ <div class="{1}">{6}</div>\
96
+ </td>\
97
+ </tr>',
98
+ [
99
+ NUMBERS_BLOCK_NAME ,
100
+ LINE_NAME ,
101
+ NUMBER_LINE_NAME ,
102
+ DATA_ATTR_NAME ,
103
+ CODE_BLOCK_NAME ,
104
+ i + 1 ,
105
+ lines [ i ] . length > 0 ? lines [ i ] : ' '
106
+ ] ) ;
107
+ }
108
+
109
+ return format ( '<table class="{0}">{1}</table>' , [ TABLE_NAME , html ] ) ;
110
+ }
111
+
112
+ return inputHtml ;
113
+ }
114
+
115
+ /**
116
+ * Recursive method for fix multi-line elements implementation in highlight.js
117
+ * Doing deep passage on child nodes.
118
+ * @param {HTMLElement } element
119
+ */
120
+ function duplicateMultilineNodes ( element ) {
121
+ var nodes = element . childNodes ;
122
+ for ( var node in nodes ) {
123
+ if ( nodes . hasOwnProperty ( node ) ) {
124
+ var child = nodes [ node ] ;
125
+ if ( getLinesCount ( child . textContent ) > 0 ) {
126
+ if ( child . childNodes . length > 0 ) {
127
+ duplicateMultilineNodes ( child ) ;
128
+ } else {
129
+ duplicateMultilineNode ( child ) ;
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Method for fix multi-line elements implementation in highlight.js
138
+ * @param {HTMLElement } element
139
+ */
140
+ function duplicateMultilineNode ( element ) {
141
+ var className = element . parentNode . className ;
142
+
143
+ if ( ! / h l j s - / . test ( className ) ) return ;
144
+
145
+ var lines = getLines ( element . textContent ) ;
146
+
147
+ for ( var i = 0 , result = '' ; i < lines . length ; i ++ ) {
148
+ result += format ( '<span class="{0}">{1}</span>\n' , [ className , lines [ i ] ] ) ;
149
+ }
150
+ element . parentNode . innerHTML = result . trim ( ) ;
151
+ }
152
+
153
+ function getLines ( text ) {
154
+ if ( text . length === 0 ) return [ ] ;
155
+ return text . split ( BREAK_LINE_REGEXP ) ;
156
+ }
157
+
158
+ function getLinesCount ( text ) {
159
+ return ( text . trim ( ) . match ( BREAK_LINE_REGEXP ) || [ ] ) . length ;
160
+ }
161
+
162
+ function async ( func ) {
163
+ w . setTimeout ( func , 0 ) ;
164
+ }
165
+
166
+ /**
167
+ * {@link https://wcoder.github.io/notes/string-format-for-string-formating-in-javascript }
168
+ * @param {string } format
169
+ * @param {array } args
170
+ */
171
+ function format ( format , args ) {
172
+ return format . replace ( / \{ ( \d + ) \} / g, function ( m , n ) {
173
+ return args [ n ] ? args [ n ] : m ;
174
+ } ) ;
175
+ }
176
+
177
+ } ( window , document ) ) ;
0 commit comments