nxt-highlightjs 22.0.0 → 22.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,251 +1,231 @@
1
- import * as i0 from '@angular/core';
2
- import { inject, ElementRef, input, numberAttribute, booleanAttribute, effect, Directive } from '@angular/core';
3
- import { NXT_HIGHLIGHT_OPTIONS, HighlightJS, HighlightBase } from 'nxt-highlightjs';
4
-
1
+ import * as i0 from "@angular/core";
2
+ import { Directive, ElementRef, booleanAttribute, effect, inject, input, numberAttribute } from "@angular/core";
3
+ import { HighlightBase, HighlightJS, NXT_HIGHLIGHT_OPTIONS } from "nxt-highlightjs";
5
4
  function activateLineNumbers(document) {
6
- const TABLE_NAME = 'hljs-ln';
7
- const LINE_NAME = 'hljs-ln-line';
8
- const CODE_BLOCK_NAME = 'hljs-ln-code';
9
- const NUMBERS_BLOCK_NAME = 'hljs-ln-numbers';
10
- const NUMBER_LINE_NAME = 'hljs-ln-n';
11
- const DATA_ATTR_NAME = 'data-line-number';
12
- const BREAK_LINE_REGEXP = /\r\n|\r|\n/g;
13
- addStyles();
14
- function isHljsLnCodeDescendant(domElt) {
15
- let curElt = domElt;
16
- while (curElt) {
17
- if (curElt.className && curElt.className.indexOf('hljs-ln-code') !== -1) {
18
- return true;
19
- }
20
- curElt = curElt.parentNode;
21
- }
22
- return false;
23
- }
24
- function getHljsLnTable(hljsLnDomElt) {
25
- let curElt = hljsLnDomElt;
26
- while (curElt && curElt.nodeName !== 'TABLE') {
27
- curElt = curElt.parentNode;
28
- }
29
- return curElt;
30
- }
31
- // Function to workaround a copy issue with Microsoft Edge.
32
- // Due to hljs-ln wrapping the lines of code inside a <table> element,
33
- // itself wrapped inside a <pre> element, window.getSelection().toString()
34
- // does not contain any line breaks. So we need to get them back using the
35
- // rendered code in the DOM as reference.
36
- function edgeGetSelectedCodeLines(selection) {
37
- // current selected text without line breaks
38
- const selectionText = selection.toString();
39
- // get the <td> element wrapping the first line of selected code
40
- let tdAnchor = selection.anchorNode;
41
- while (tdAnchor?.nodeName !== 'TD') {
42
- tdAnchor = tdAnchor?.parentNode || null;
43
- }
44
- // get the <td> element wrapping the last line of selected code
45
- let tdFocus = selection.focusNode;
46
- while (tdFocus?.nodeName !== 'TD') {
47
- tdFocus = tdFocus?.parentNode || null;
48
- }
49
- // extract line numbers
50
- let firstLineNumber = parseInt(tdAnchor?.dataset['lineNumber'] || '0', 10);
51
- let lastLineNumber = parseInt(tdFocus?.dataset['lineNumber'] || '0', 10);
52
- // multi-lines copied case
53
- if (firstLineNumber != lastLineNumber) {
54
- let firstLineText = tdAnchor.textContent;
55
- let lastLineText = tdFocus.textContent;
56
- // if the selection was made backward, swap values
57
- if (firstLineNumber > lastLineNumber) {
58
- const tmp = firstLineNumber;
59
- firstLineNumber = lastLineNumber;
60
- lastLineNumber = tmp;
61
- const tmp2 = firstLineText;
62
- firstLineText = lastLineText;
63
- lastLineText = tmp2;
64
- }
65
- // discard not copied characters in first line
66
- while (selectionText.indexOf(firstLineText || '') !== 0) {
67
- firstLineText = firstLineText.slice(1);
68
- }
69
- // discard not copied characters in last line
70
- while (selectionText.lastIndexOf(lastLineText || '') === -1) {
71
- lastLineText = lastLineText.slice(0, -1);
72
- }
73
- // reconstruct and return the real copied text
74
- let selectedText = firstLineText;
75
- const hljsLnTable = getHljsLnTable(tdAnchor);
76
- for (let i = firstLineNumber + 1; i < lastLineNumber; ++i) {
77
- const codeLineSel = format('.{0}[{1}="{2}"]', [CODE_BLOCK_NAME, DATA_ATTR_NAME, i]);
78
- const codeLineElt = hljsLnTable?.querySelector(codeLineSel);
79
- selectedText += '\n' + (codeLineElt?.textContent || '');
80
- }
81
- selectedText += '\n' + lastLineText;
82
- return selectedText;
83
- // single copied line case
84
- }
85
- else {
86
- return selectionText;
87
- }
88
- }
89
- // ensure consistent code copy/paste behavior across all browsers
90
- // (see https://github.com/wcoder/highlightjs-line-numbers.js/issues/51)
91
- document.addEventListener('copy', (e) => {
92
- // get current selection
93
- const selection = window.getSelection();
94
- // override behavior when one wants to copy line of codes
95
- if (isHljsLnCodeDescendant(selection?.anchorNode)) {
96
- let selectionText;
97
- // workaround an issue with Microsoft Edge as copied line breaks
98
- // are removed otherwise from the selection string
99
- if (window.navigator.userAgent.indexOf('Edge') !== -1 && selection) {
100
- selectionText = edgeGetSelectedCodeLines(selection);
101
- }
102
- else {
103
- // other browsers can directly use the selection string
104
- selectionText = selection?.toString();
105
- }
106
- if (selectionText) {
107
- e.clipboardData?.setData('text/plain', selectionText);
108
- e.preventDefault();
109
- }
110
- }
111
- });
112
- function addStyles() {
113
- const css = document.createElement('style');
114
- css.innerHTML = format('.{0}{border-collapse:collapse}' +
115
- '.{0} td{padding:0}' +
116
- '.{1}:before{content:attr({2})}', [
117
- TABLE_NAME,
118
- NUMBER_LINE_NAME,
119
- DATA_ATTR_NAME
120
- ]);
121
- document.getElementsByTagName('head')[0].appendChild(css);
122
- }
123
- function lineNumbersBlock(code, options) {
124
- return lineNumbersInternal(code, options);
125
- }
126
- function lineNumbersInternal(code, options) {
127
- const internalOptions = mapOptions(options);
128
- return addLineNumbersBlockFor(code, internalOptions);
129
- }
130
- function addLineNumbersBlockFor(inputHtml, options) {
131
- const lines = getLines(inputHtml);
132
- // if last line contains only carriage return remove it
133
- if (lines[lines.length - 1].trim() === '') {
134
- lines.pop();
135
- }
136
- if (lines.length > 1 || options?.singleLine) {
137
- let html = '';
138
- for (let i = 0, l = lines.length; i < l; i++) {
139
- html += format('<tr>' +
140
- '<td class="{0} {1}" {3}="{5}">' +
141
- '<div class="{2}" {3}="{5}"></div>' +
142
- '</td>' +
143
- '<td class="{0} {4}" {3}="{5}">' +
144
- '{6}' +
145
- '</td>' +
146
- '</tr>', [
147
- LINE_NAME,
148
- NUMBERS_BLOCK_NAME,
149
- NUMBER_LINE_NAME,
150
- DATA_ATTR_NAME,
151
- CODE_BLOCK_NAME,
152
- i + Number(!!(options?.startFrom)),
153
- lines[i].length > 0 ? lines[i] : ' '
154
- ]);
155
- }
156
- return format('<table class="{0}">{1}</table>', [TABLE_NAME, html]);
157
- }
158
- return inputHtml;
159
- }
160
- /**
161
- * @param element Code block.
162
- * @param options External API options.
163
- * @returns Internal API options.
164
- */
165
- function mapOptions(options) {
166
- options = options || {};
167
- return {
168
- singleLine: getSingleLineOption(options),
169
- startFrom: getStartFromOption(options)
170
- };
171
- }
172
- function getSingleLineOption(options) {
173
- const defaultValue = false;
174
- if (!!options?.singleLine) {
175
- return options.singleLine;
176
- }
177
- return defaultValue;
178
- }
179
- function getStartFromOption(options) {
180
- const defaultValue = 1;
181
- let startFrom = defaultValue;
182
- if (isFinite(options?.startFrom ?? NaN)) {
183
- startFrom = options.startFrom;
184
- }
185
- return startFrom;
186
- }
187
- function getLines(text) {
188
- if (text.length === 0)
189
- return [];
190
- return text.split(BREAK_LINE_REGEXP);
191
- }
192
- ///
193
- /// HELPERS
194
- ///
195
- /**
196
- * {@link https://wcoder.github.io/notes/string-format-for-string-formating-in-javascript}
197
- *
198
- * @param formatString
199
- * @param args
200
- */
201
- function format(formatString, args) {
202
- return formatString.replace(/\{(\d+)\}/g, (m, n) => args[n] !== null && args[n] !== undefined ? args[n] : m);
203
- }
204
- return lineNumbersBlock;
205
- }
206
-
207
- class HighlightLineNumbersDirective {
208
- constructor() {
209
- this.options = inject(NXT_HIGHLIGHT_OPTIONS)?.lineNumbersOptions;
210
- this.hljs = inject(HighlightJS);
211
- this.highlight = inject(HighlightBase);
212
- this.nativeElement = inject((ElementRef)).nativeElement;
213
- this.startFrom = input(this.options?.startFrom, { ...(ngDevMode ? { debugName: "startFrom" } : /* istanbul ignore next */ {}), transform: numberAttribute });
214
- this.singleLine = input(this.options?.singleLine, { ...(ngDevMode ? { debugName: "singleLine" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
215
- effect(() => {
216
- const hljs = this.hljs.hljs();
217
- const result = this.highlight.highlightResult();
218
- if (result?.value) {
219
- if (hljs.lineNumbersBlock) {
220
- const code = hljs.lineNumbersBlock(result.value, {
221
- startFrom: this.startFrom(),
222
- singleLine: this.singleLine()
223
- });
224
- this.nativeElement.innerHTML = code;
225
- }
226
- // If lines count is 1, the line numbers library will not add numbers
227
- if (this.nativeElement.firstElementChild?.tagName.toUpperCase() === 'TABLE') {
228
- this.nativeElement.classList.add('hljs-line-numbers');
229
- }
230
- else {
231
- this.nativeElement.classList.remove('hljs-line-numbers');
232
- }
233
- }
234
- });
235
- }
236
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: HighlightLineNumbersDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
237
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.6", type: HighlightLineNumbersDirective, isStandalone: true, selector: "[nxtHighlight][lineNumbers], [nxtHighlightAuto][lineNumbers]", inputs: { startFrom: { classPropertyName: "startFrom", publicName: "startFrom", isSignal: true, isRequired: false, transformFunction: null }, singleLine: { classPropertyName: "singleLine", publicName: "singleLine", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
5
+ const TABLE_NAME = "hljs-ln";
6
+ const LINE_NAME = "hljs-ln-line";
7
+ const CODE_BLOCK_NAME = "hljs-ln-code";
8
+ const NUMBERS_BLOCK_NAME = "hljs-ln-numbers";
9
+ const NUMBER_LINE_NAME = "hljs-ln-n";
10
+ const DATA_ATTR_NAME = "data-line-number";
11
+ const BREAK_LINE_REGEXP = /\r\n|\r|\n/g;
12
+ addStyles();
13
+ function isHljsLnCodeDescendant(domElt) {
14
+ let curElt = domElt;
15
+ while (curElt) {
16
+ if (curElt.className && curElt.className.indexOf("hljs-ln-code") !== -1) return true;
17
+ curElt = curElt.parentNode;
18
+ }
19
+ return false;
20
+ }
21
+ function getHljsLnTable(hljsLnDomElt) {
22
+ let curElt = hljsLnDomElt;
23
+ while (curElt && curElt.nodeName !== "TABLE") curElt = curElt.parentNode;
24
+ return curElt;
25
+ }
26
+ function edgeGetSelectedCodeLines(selection) {
27
+ const selectionText = selection.toString();
28
+ let tdAnchor = selection.anchorNode;
29
+ while (tdAnchor?.nodeName !== "TD") tdAnchor = tdAnchor?.parentNode || null;
30
+ let tdFocus = selection.focusNode;
31
+ while (tdFocus?.nodeName !== "TD") tdFocus = tdFocus?.parentNode || null;
32
+ let firstLineNumber = parseInt(tdAnchor?.dataset["lineNumber"] || "0", 10);
33
+ let lastLineNumber = parseInt(tdFocus?.dataset["lineNumber"] || "0", 10);
34
+ if (firstLineNumber != lastLineNumber) {
35
+ let firstLineText = tdAnchor.textContent;
36
+ let lastLineText = tdFocus.textContent;
37
+ if (firstLineNumber > lastLineNumber) {
38
+ const tmp = firstLineNumber;
39
+ firstLineNumber = lastLineNumber;
40
+ lastLineNumber = tmp;
41
+ const tmp2 = firstLineText;
42
+ firstLineText = lastLineText;
43
+ lastLineText = tmp2;
44
+ }
45
+ while (selectionText.indexOf(firstLineText || "") !== 0) firstLineText = firstLineText.slice(1);
46
+ while (selectionText.lastIndexOf(lastLineText || "") === -1) lastLineText = lastLineText.slice(0, -1);
47
+ let selectedText = firstLineText;
48
+ const hljsLnTable = getHljsLnTable(tdAnchor);
49
+ for (let i = firstLineNumber + 1; i < lastLineNumber; ++i) {
50
+ const codeLineSel = format(".{0}[{1}=\"{2}\"]", [
51
+ CODE_BLOCK_NAME,
52
+ DATA_ATTR_NAME,
53
+ i
54
+ ]);
55
+ const codeLineElt = hljsLnTable?.querySelector(codeLineSel);
56
+ selectedText += "\n" + (codeLineElt?.textContent || "");
57
+ }
58
+ selectedText += "\n" + lastLineText;
59
+ return selectedText;
60
+ } else return selectionText;
61
+ }
62
+ document.addEventListener("copy", (e) => {
63
+ const selection = window.getSelection();
64
+ if (isHljsLnCodeDescendant(selection?.anchorNode)) {
65
+ let selectionText;
66
+ if (window.navigator.userAgent.indexOf("Edge") !== -1 && selection) selectionText = edgeGetSelectedCodeLines(selection);
67
+ else selectionText = selection?.toString();
68
+ if (selectionText) {
69
+ e.clipboardData?.setData("text/plain", selectionText);
70
+ e.preventDefault();
71
+ }
72
+ }
73
+ });
74
+ function addStyles() {
75
+ const css = document.createElement("style");
76
+ css.innerHTML = format(".{0}{border-collapse:collapse}.{0} td{padding:0}.{1}:before{content:attr({2})}", [
77
+ TABLE_NAME,
78
+ NUMBER_LINE_NAME,
79
+ DATA_ATTR_NAME
80
+ ]);
81
+ document.getElementsByTagName("head")[0].appendChild(css);
82
+ }
83
+ function lineNumbersBlock(code, options) {
84
+ return lineNumbersInternal(code, options);
85
+ }
86
+ function lineNumbersInternal(code, options) {
87
+ return addLineNumbersBlockFor(code, mapOptions(options));
88
+ }
89
+ function addLineNumbersBlockFor(inputHtml, options) {
90
+ const lines = getLines(inputHtml);
91
+ if (lines[lines.length - 1].trim() === "") lines.pop();
92
+ if (lines.length > 1 || options?.singleLine) {
93
+ let html = "";
94
+ for (let i = 0, l = lines.length; i < l; i++) html += format("<tr><td class=\"{0} {1}\" {3}=\"{5}\"><div class=\"{2}\" {3}=\"{5}\"></div></td><td class=\"{0} {4}\" {3}=\"{5}\">{6}</td></tr>", [
95
+ LINE_NAME,
96
+ NUMBERS_BLOCK_NAME,
97
+ NUMBER_LINE_NAME,
98
+ DATA_ATTR_NAME,
99
+ CODE_BLOCK_NAME,
100
+ i + (options?.startFrom ?? 1),
101
+ lines[i].length > 0 ? lines[i] : " "
102
+ ]);
103
+ return format("<table class=\"{0}\">{1}</table>", [TABLE_NAME, html]);
104
+ }
105
+ return inputHtml;
106
+ }
107
+ function mapOptions(options) {
108
+ options = options || {};
109
+ return {
110
+ singleLine: getSingleLineOption(options),
111
+ startFrom: getStartFromOption(options)
112
+ };
113
+ }
114
+ function getSingleLineOption(options) {
115
+ const defaultValue = false;
116
+ if (!!options?.singleLine) return options.singleLine;
117
+ return defaultValue;
118
+ }
119
+ function getStartFromOption(options) {
120
+ let startFrom = 1;
121
+ if (isFinite(options?.startFrom ?? NaN)) startFrom = options.startFrom;
122
+ return startFrom;
123
+ }
124
+ function getLines(text) {
125
+ if (text.length === 0) return [];
126
+ return text.split(BREAK_LINE_REGEXP);
127
+ }
128
+ function format(formatString, args) {
129
+ return formatString.replace(/\{(\d+)\}/g, (m, n) => args[n] !== null && args[n] !== void 0 ? args[n] : m);
130
+ }
131
+ return lineNumbersBlock;
238
132
  }
239
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.6", ngImport: i0, type: HighlightLineNumbersDirective, decorators: [{
240
- type: Directive,
241
- args: [{
242
- selector: '[nxtHighlight][lineNumbers], [nxtHighlightAuto][lineNumbers]'
243
- }]
244
- }], ctorParameters: () => [], propDecorators: { startFrom: [{ type: i0.Input, args: [{ isSignal: true, alias: "startFrom", required: false }] }], singleLine: [{ type: i0.Input, args: [{ isSignal: true, alias: "singleLine", required: false }] }] } });
245
-
246
- /**
247
- * Generated bundle index. Do not edit.
248
- */
249
-
133
+ var HighlightLineNumbersDirective = class HighlightLineNumbersDirective {
134
+ constructor() {
135
+ this.options = inject(NXT_HIGHLIGHT_OPTIONS)?.lineNumbersOptions;
136
+ this.hljs = inject(HighlightJS);
137
+ this.highlight = inject(HighlightBase);
138
+ this.nativeElement = inject(ElementRef).nativeElement;
139
+ this.startFrom = input(this.options?.startFrom, {
140
+ ...ngDevMode ? { debugName: "startFrom" } : /* istanbul ignore next */ {},
141
+ transform: numberAttribute
142
+ });
143
+ this.singleLine = input(this.options?.singleLine, {
144
+ ...ngDevMode ? { debugName: "singleLine" } : /* istanbul ignore next */ {},
145
+ transform: booleanAttribute
146
+ });
147
+ effect(() => {
148
+ const hljs = this.hljs.hljs();
149
+ const result = this.highlight.highlightResult();
150
+ if (result?.value) {
151
+ if (hljs.lineNumbersBlock) {
152
+ const code = hljs.lineNumbersBlock(result.value, {
153
+ startFrom: this.startFrom(),
154
+ singleLine: this.singleLine()
155
+ });
156
+ this.nativeElement.innerHTML = code;
157
+ }
158
+ if (this.nativeElement.firstElementChild?.tagName.toUpperCase() === "TABLE") this.nativeElement.classList.add("hljs-line-numbers");
159
+ else this.nativeElement.classList.remove("hljs-line-numbers");
160
+ }
161
+ });
162
+ }
163
+ static {
164
+ this.ɵfac = i0.ɵɵngDeclareFactory({
165
+ minVersion: "12.0.0",
166
+ version: "22.2.5",
167
+ ngImport: i0,
168
+ type: HighlightLineNumbersDirective,
169
+ deps: [],
170
+ target: i0.ɵɵFactoryTarget.Directive
171
+ });
172
+ }
173
+ static {
174
+ this.ɵdir = i0.ɵɵngDeclareDirective({
175
+ minVersion: "17.1.0",
176
+ version: "22.2.5",
177
+ type: HighlightLineNumbersDirective,
178
+ isStandalone: true,
179
+ selector: "[nxtHighlight][lineNumbers], [nxtHighlightAuto][lineNumbers]",
180
+ inputs: {
181
+ startFrom: {
182
+ classPropertyName: "startFrom",
183
+ publicName: "startFrom",
184
+ isSignal: true,
185
+ isRequired: false,
186
+ transformFunction: null
187
+ },
188
+ singleLine: {
189
+ classPropertyName: "singleLine",
190
+ publicName: "singleLine",
191
+ isSignal: true,
192
+ isRequired: false,
193
+ transformFunction: null
194
+ }
195
+ },
196
+ ngImport: i0
197
+ });
198
+ }
199
+ };
200
+ i0.ɵɵngDeclareClassMetadata({
201
+ minVersion: "12.0.0",
202
+ version: "22.2.5",
203
+ ngImport: i0,
204
+ type: HighlightLineNumbersDirective,
205
+ decorators: [{
206
+ type: Directive,
207
+ args: [{ selector: "[nxtHighlight][lineNumbers], [nxtHighlightAuto][lineNumbers]" }]
208
+ }],
209
+ ctorParameters: () => [],
210
+ propDecorators: {
211
+ startFrom: [{
212
+ type: i0.Input,
213
+ args: [{
214
+ isSignal: true,
215
+ alias: "startFrom",
216
+ required: false
217
+ }]
218
+ }],
219
+ singleLine: [{
220
+ type: i0.Input,
221
+ args: [{
222
+ isSignal: true,
223
+ alias: "singleLine",
224
+ required: false
225
+ }]
226
+ }]
227
+ }
228
+ });
250
229
  export { HighlightLineNumbersDirective, activateLineNumbers };
251
- //# sourceMappingURL=nxt-highlightjs-line-numbers.mjs.map
230
+
231
+ //# sourceMappingURL=nxt-highlightjs-line-numbers.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"nxt-highlightjs-line-numbers.mjs","sources":["../../../packages/highlightjs/line-numbers/src/line-numbers-lib.ts","../../../packages/highlightjs/line-numbers/src/line-numbers.directive.ts","../../../packages/highlightjs/line-numbers/src/nxt-highlightjs-line-numbers.ts"],"sourcesContent":["import { LineNumbersOptions } from 'nxt-highlightjs'\r\n\r\nexport function activateLineNumbers(document: Document) {\r\n const TABLE_NAME = 'hljs-ln'\r\n const LINE_NAME = 'hljs-ln-line'\r\n const CODE_BLOCK_NAME = 'hljs-ln-code'\r\n const NUMBERS_BLOCK_NAME = 'hljs-ln-numbers'\r\n const NUMBER_LINE_NAME = 'hljs-ln-n'\r\n const DATA_ATTR_NAME = 'data-line-number'\r\n const BREAK_LINE_REGEXP = /\\r\\n|\\r|\\n/g\r\n\r\n addStyles()\r\n\r\n function isHljsLnCodeDescendant(domElt?: HTMLElement | null) {\r\n let curElt = domElt\r\n while (curElt) {\r\n if (curElt.className && curElt.className.indexOf('hljs-ln-code') !== -1) {\r\n return true\r\n }\r\n curElt = curElt.parentNode as HTMLElement\r\n }\r\n return false\r\n }\r\n\r\n function getHljsLnTable(hljsLnDomElt?: HTMLElement) {\r\n let curElt = hljsLnDomElt\r\n while (curElt && curElt.nodeName !== 'TABLE') {\r\n curElt = curElt.parentNode as HTMLElement\r\n }\r\n return curElt\r\n }\r\n\r\n // Function to workaround a copy issue with Microsoft Edge.\r\n // Due to hljs-ln wrapping the lines of code inside a <table> element,\r\n // itself wrapped inside a <pre> element, window.getSelection().toString()\r\n // does not contain any line breaks. So we need to get them back using the\r\n // rendered code in the DOM as reference.\r\n function edgeGetSelectedCodeLines(selection: Selection) {\r\n // current selected text without line breaks\r\n const selectionText = selection.toString()\r\n\r\n // get the <td> element wrapping the first line of selected code\r\n let tdAnchor = selection.anchorNode\r\n while (tdAnchor?.nodeName !== 'TD') {\r\n tdAnchor = tdAnchor?.parentNode || null\r\n }\r\n\r\n // get the <td> element wrapping the last line of selected code\r\n let tdFocus = selection.focusNode\r\n while (tdFocus?.nodeName !== 'TD') {\r\n tdFocus = tdFocus?.parentNode || null\r\n }\r\n\r\n // extract line numbers\r\n let firstLineNumber = parseInt((tdAnchor as HTMLElement | null)?.dataset['lineNumber'] || '0', 10)\r\n let lastLineNumber = parseInt((tdFocus as HTMLElement | null)?.dataset['lineNumber'] || '0', 10)\r\n\r\n // multi-lines copied case\r\n if (firstLineNumber != lastLineNumber) {\r\n\r\n let firstLineText = tdAnchor.textContent\r\n let lastLineText = tdFocus.textContent\r\n\r\n // if the selection was made backward, swap values\r\n if (firstLineNumber > lastLineNumber) {\r\n const tmp = firstLineNumber\r\n firstLineNumber = lastLineNumber\r\n lastLineNumber = tmp\r\n const tmp2 = firstLineText\r\n firstLineText = lastLineText\r\n lastLineText = tmp2\r\n }\r\n\r\n // discard not copied characters in first line\r\n while (selectionText.indexOf(firstLineText || '') !== 0) {\r\n firstLineText = firstLineText!.slice(1)\r\n }\r\n\r\n // discard not copied characters in last line\r\n while (selectionText.lastIndexOf(lastLineText || '') === -1) {\r\n lastLineText = lastLineText!.slice(0, -1)\r\n }\r\n\r\n // reconstruct and return the real copied text\r\n let selectedText = firstLineText\r\n const hljsLnTable = getHljsLnTable(tdAnchor as HTMLElement)\r\n for (let i = firstLineNumber + 1; i < lastLineNumber; ++i) {\r\n const codeLineSel = format('.{0}[{1}=\"{2}\"]', [CODE_BLOCK_NAME, DATA_ATTR_NAME, i])\r\n const codeLineElt = hljsLnTable?.querySelector(codeLineSel)\r\n selectedText += '\\n' + (codeLineElt?.textContent || '')\r\n }\r\n selectedText += '\\n' + lastLineText\r\n return selectedText\r\n // single copied line case\r\n } else {\r\n return selectionText\r\n }\r\n }\r\n\r\n // ensure consistent code copy/paste behavior across all browsers\r\n // (see https://github.com/wcoder/highlightjs-line-numbers.js/issues/51)\r\n document.addEventListener('copy', (e) => {\r\n // get current selection\r\n const selection = window.getSelection()\r\n // override behavior when one wants to copy line of codes\r\n if (isHljsLnCodeDescendant(selection?.anchorNode as HTMLElement | null | undefined)) {\r\n let selectionText: string | null | undefined\r\n // workaround an issue with Microsoft Edge as copied line breaks\r\n // are removed otherwise from the selection string\r\n if (window.navigator.userAgent.indexOf('Edge') !== -1 && selection) {\r\n selectionText = edgeGetSelectedCodeLines(selection)\r\n } else {\r\n // other browsers can directly use the selection string\r\n selectionText = selection?.toString()\r\n }\r\n if (selectionText) {\r\n e.clipboardData?.setData('text/plain', selectionText)\r\n e.preventDefault()\r\n }\r\n }\r\n })\r\n\r\n function addStyles() {\r\n const css = document.createElement('style')\r\n css.innerHTML = format(\r\n '.{0}{border-collapse:collapse}' +\r\n '.{0} td{padding:0}' +\r\n '.{1}:before{content:attr({2})}',\r\n [\r\n TABLE_NAME,\r\n NUMBER_LINE_NAME,\r\n DATA_ATTR_NAME\r\n ])\r\n document.getElementsByTagName('head')[0].appendChild(css)\r\n }\r\n\r\n function lineNumbersBlock(code: string, options?: LineNumbersOptions) {\r\n return lineNumbersInternal(code, options)\r\n }\r\n\r\n function lineNumbersInternal(code: string, options?: LineNumbersOptions) {\r\n\r\n const internalOptions = mapOptions(options)\r\n\r\n return addLineNumbersBlockFor(code, internalOptions)\r\n }\r\n\r\n function addLineNumbersBlockFor(inputHtml: string, options?: LineNumbersOptions) {\r\n const lines = getLines(inputHtml)\r\n\r\n // if last line contains only carriage return remove it\r\n if (lines[lines.length - 1].trim() === '') {\r\n lines.pop()\r\n }\r\n\r\n if (lines.length > 1 || options?.singleLine) {\r\n let html = ''\r\n\r\n for (let i = 0, l = lines.length; i < l; i++) {\r\n html += format(\r\n '<tr>' +\r\n '<td class=\"{0} {1}\" {3}=\"{5}\">' +\r\n '<div class=\"{2}\" {3}=\"{5}\"></div>' +\r\n '</td>' +\r\n '<td class=\"{0} {4}\" {3}=\"{5}\">' +\r\n '{6}' +\r\n '</td>' +\r\n '</tr>',\r\n [\r\n LINE_NAME,\r\n NUMBERS_BLOCK_NAME,\r\n NUMBER_LINE_NAME,\r\n DATA_ATTR_NAME,\r\n CODE_BLOCK_NAME,\r\n i + Number(!!(options?.startFrom)),\r\n lines[i].length > 0 ? lines[i] : ' '\r\n ])\r\n }\r\n\r\n return format('<table class=\"{0}\">{1}</table>', [TABLE_NAME, html])\r\n }\r\n\r\n return inputHtml\r\n }\r\n\r\n /**\r\n * @param element Code block.\r\n * @param options External API options.\r\n * @returns Internal API options.\r\n */\r\n function mapOptions(options?: LineNumbersOptions) {\r\n options = options || {}\r\n return {\r\n singleLine: getSingleLineOption(options),\r\n startFrom: getStartFromOption(options)\r\n }\r\n }\r\n\r\n function getSingleLineOption(options?: LineNumbersOptions) {\r\n const defaultValue = false\r\n if (!!options?.singleLine) {\r\n return options.singleLine\r\n }\r\n return defaultValue\r\n }\r\n\r\n function getStartFromOption(options?: LineNumbersOptions) {\r\n const defaultValue = 1\r\n let startFrom = defaultValue\r\n\r\n if (isFinite(options?.startFrom ?? NaN)) {\r\n startFrom = options!.startFrom!\r\n }\r\n\r\n return startFrom\r\n }\r\n\r\n function getLines(text: string) {\r\n if (text.length === 0) return []\r\n return text.split(BREAK_LINE_REGEXP)\r\n }\r\n\r\n ///\r\n /// HELPERS\r\n ///\r\n\r\n /**\r\n * {@link https://wcoder.github.io/notes/string-format-for-string-formating-in-javascript}\r\n *\r\n * @param formatString\r\n * @param args\r\n */\r\n function format(formatString: string, args: any[]) {\r\n return formatString.replace(/\\{(\\d+)\\}/g, (m, n) => args[n] !== null && args[n] !== undefined ? args[n] : m)\r\n }\r\n\r\n return lineNumbersBlock\r\n}\r\n","import {\n Directive,\n ElementRef,\n booleanAttribute,\n effect,\n inject,\n input,\n numberAttribute\n} from '@angular/core'\nimport { HighlightBase, HighlightJS, NXT_HIGHLIGHT_OPTIONS } from 'nxt-highlightjs'\n\n@Directive({\n selector: '[nxtHighlight][lineNumbers], [nxtHighlightAuto][lineNumbers]'\n})\nexport class HighlightLineNumbersDirective {\n\n private readonly options = inject(NXT_HIGHLIGHT_OPTIONS)?.lineNumbersOptions\n private readonly hljs = inject(HighlightJS)\n private readonly highlight = inject(HighlightBase)\n private readonly nativeElement = inject(ElementRef<HTMLElement>).nativeElement\n\n readonly startFrom = input<number | undefined, unknown>(this.options?.startFrom, {\n transform: numberAttribute\n })\n\n readonly singleLine = input<boolean | undefined, unknown>(this.options?.singleLine, {\n transform: booleanAttribute\n })\n\n constructor() {\n effect(() => {\n const hljs = this.hljs.hljs()\n const result = this.highlight.highlightResult()\n if (result?.value) {\n if ((hljs as any).lineNumbersBlock) {\n const code = (hljs as any).lineNumbersBlock(result.value, {\n startFrom: this.startFrom(),\n singleLine: this.singleLine()\n })\n this.nativeElement.innerHTML = code\n }\n // If lines count is 1, the line numbers library will not add numbers\n if (this.nativeElement.firstElementChild?.tagName.toUpperCase() === 'TABLE') {\n this.nativeElement.classList.add('hljs-line-numbers')\n } else {\n this.nativeElement.classList.remove('hljs-line-numbers')\n }\n }\n })\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nxt-highlightjs-line-numbers.mjs","names":[],"sources":["../../../packages/highlightjs/line-numbers/src/line-numbers-lib.ts","../../../packages/highlightjs/line-numbers/src/line-numbers.directive.ts"],"sourcesContent":["import { LineNumbersOptions } from 'nxt-highlightjs'\n\nexport function activateLineNumbers(document: Document) {\n const TABLE_NAME = 'hljs-ln'\n const LINE_NAME = 'hljs-ln-line'\n const CODE_BLOCK_NAME = 'hljs-ln-code'\n const NUMBERS_BLOCK_NAME = 'hljs-ln-numbers'\n const NUMBER_LINE_NAME = 'hljs-ln-n'\n const DATA_ATTR_NAME = 'data-line-number'\n const BREAK_LINE_REGEXP = /\\r\\n|\\r|\\n/g\n\n addStyles()\n\n function isHljsLnCodeDescendant(domElt?: HTMLElement | null) {\n let curElt = domElt\n while (curElt) {\n if (curElt.className && curElt.className.indexOf('hljs-ln-code') !== -1) {\n return true\n }\n curElt = curElt.parentNode as HTMLElement\n }\n return false\n }\n\n function getHljsLnTable(hljsLnDomElt?: HTMLElement) {\n let curElt = hljsLnDomElt\n while (curElt && curElt.nodeName !== 'TABLE') {\n curElt = curElt.parentNode as HTMLElement\n }\n return curElt\n }\n\n // Function to workaround a copy issue with Microsoft Edge.\n // Due to hljs-ln wrapping the lines of code inside a <table> element,\n // itself wrapped inside a <pre> element, window.getSelection().toString()\n // does not contain any line breaks. So we need to get them back using the\n // rendered code in the DOM as reference.\n function edgeGetSelectedCodeLines(selection: Selection) {\n // current selected text without line breaks\n const selectionText = selection.toString()\n\n // get the <td> element wrapping the first line of selected code\n let tdAnchor = selection.anchorNode\n while (tdAnchor?.nodeName !== 'TD') {\n tdAnchor = tdAnchor?.parentNode || null\n }\n\n // get the <td> element wrapping the last line of selected code\n let tdFocus = selection.focusNode\n while (tdFocus?.nodeName !== 'TD') {\n tdFocus = tdFocus?.parentNode || null\n }\n\n // extract line numbers\n let firstLineNumber = parseInt((tdAnchor as HTMLElement | null)?.dataset['lineNumber'] || '0', 10)\n let lastLineNumber = parseInt((tdFocus as HTMLElement | null)?.dataset['lineNumber'] || '0', 10)\n\n // multi-lines copied case\n if (firstLineNumber != lastLineNumber) {\n\n let firstLineText = tdAnchor.textContent\n let lastLineText = tdFocus.textContent\n\n // if the selection was made backward, swap values\n if (firstLineNumber > lastLineNumber) {\n const tmp = firstLineNumber\n firstLineNumber = lastLineNumber\n lastLineNumber = tmp\n const tmp2 = firstLineText\n firstLineText = lastLineText\n lastLineText = tmp2\n }\n\n // discard not copied characters in first line\n while (selectionText.indexOf(firstLineText || '') !== 0) {\n firstLineText = firstLineText!.slice(1)\n }\n\n // discard not copied characters in last line\n while (selectionText.lastIndexOf(lastLineText || '') === -1) {\n lastLineText = lastLineText!.slice(0, -1)\n }\n\n // reconstruct and return the real copied text\n let selectedText = firstLineText\n const hljsLnTable = getHljsLnTable(tdAnchor as HTMLElement)\n for (let i = firstLineNumber + 1; i < lastLineNumber; ++i) {\n const codeLineSel = format('.{0}[{1}=\"{2}\"]', [CODE_BLOCK_NAME, DATA_ATTR_NAME, i])\n const codeLineElt = hljsLnTable?.querySelector(codeLineSel)\n selectedText += '\\n' + (codeLineElt?.textContent || '')\n }\n selectedText += '\\n' + lastLineText\n return selectedText\n // single copied line case\n } else {\n return selectionText\n }\n }\n\n // ensure consistent code copy/paste behavior across all browsers\n // (see https://github.com/wcoder/highlightjs-line-numbers.js/issues/51)\n document.addEventListener('copy', (e) => {\n // get current selection\n const selection = window.getSelection()\n // override behavior when one wants to copy line of codes\n if (isHljsLnCodeDescendant(selection?.anchorNode as HTMLElement | null | undefined)) {\n let selectionText: string | null | undefined\n // workaround an issue with Microsoft Edge as copied line breaks\n // are removed otherwise from the selection string\n if (window.navigator.userAgent.indexOf('Edge') !== -1 && selection) {\n selectionText = edgeGetSelectedCodeLines(selection)\n } else {\n // other browsers can directly use the selection string\n selectionText = selection?.toString()\n }\n if (selectionText) {\n e.clipboardData?.setData('text/plain', selectionText)\n e.preventDefault()\n }\n }\n })\n\n function addStyles() {\n const css = document.createElement('style')\n css.innerHTML = format(\n '.{0}{border-collapse:collapse}' +\n '.{0} td{padding:0}' +\n '.{1}:before{content:attr({2})}',\n [\n TABLE_NAME,\n NUMBER_LINE_NAME,\n DATA_ATTR_NAME\n ])\n document.getElementsByTagName('head')[0].appendChild(css)\n }\n\n function lineNumbersBlock(code: string, options?: LineNumbersOptions) {\n return lineNumbersInternal(code, options)\n }\n\n function lineNumbersInternal(code: string, options?: LineNumbersOptions) {\n\n const internalOptions = mapOptions(options)\n\n return addLineNumbersBlockFor(code, internalOptions)\n }\n\n function addLineNumbersBlockFor(inputHtml: string, options?: LineNumbersOptions) {\n const lines = getLines(inputHtml)\n\n // if last line contains only carriage return remove it\n if (lines[lines.length - 1].trim() === '') {\n lines.pop()\n }\n\n if (lines.length > 1 || options?.singleLine) {\n let html = ''\n\n for (let i = 0, l = lines.length; i < l; i++) {\n html += format(\n '<tr>' +\n '<td class=\"{0} {1}\" {3}=\"{5}\">' +\n '<div class=\"{2}\" {3}=\"{5}\"></div>' +\n '</td>' +\n '<td class=\"{0} {4}\" {3}=\"{5}\">' +\n '{6}' +\n '</td>' +\n '</tr>',\n [\n LINE_NAME,\n NUMBERS_BLOCK_NAME,\n NUMBER_LINE_NAME,\n DATA_ATTR_NAME,\n CODE_BLOCK_NAME,\n i + (options?.startFrom ?? 1),\n lines[i].length > 0 ? lines[i] : ' '\n ])\n }\n\n return format('<table class=\"{0}\">{1}</table>', [TABLE_NAME, html])\n }\n\n return inputHtml\n }\n\n /**\n * @param element Code block.\n * @param options External API options.\n * @returns Internal API options.\n */\n function mapOptions(options?: LineNumbersOptions) {\n options = options || {}\n return {\n singleLine: getSingleLineOption(options),\n startFrom: getStartFromOption(options)\n }\n }\n\n function getSingleLineOption(options?: LineNumbersOptions) {\n const defaultValue = false\n if (!!options?.singleLine) {\n return options.singleLine\n }\n return defaultValue\n }\n\n function getStartFromOption(options?: LineNumbersOptions) {\n const defaultValue = 1\n let startFrom = defaultValue\n\n if (isFinite(options?.startFrom ?? NaN)) {\n startFrom = options!.startFrom!\n }\n\n return startFrom\n }\n\n function getLines(text: string) {\n if (text.length === 0) return []\n return text.split(BREAK_LINE_REGEXP)\n }\n\n ///\n /// HELPERS\n ///\n\n /**\n * {@link https://wcoder.github.io/notes/string-format-for-string-formating-in-javascript}\n *\n * @param formatString\n * @param args\n */\n function format(formatString: string, args: any[]) {\n return formatString.replace(/\\{(\\d+)\\}/g, (m, n) => args[n] !== null && args[n] !== undefined ? args[n] : m)\n }\n\n return lineNumbersBlock\n}\n","import {\n Directive,\n ElementRef,\n booleanAttribute,\n effect,\n inject,\n input,\n numberAttribute\n} from '@angular/core'\nimport { HighlightBase, HighlightJS, NXT_HIGHLIGHT_OPTIONS } from 'nxt-highlightjs'\n\n@Directive({\n selector: '[nxtHighlight][lineNumbers], [nxtHighlightAuto][lineNumbers]'\n})\nexport class HighlightLineNumbersDirective {\n\n private readonly options = inject(NXT_HIGHLIGHT_OPTIONS)?.lineNumbersOptions\n private readonly hljs = inject(HighlightJS)\n private readonly highlight = inject(HighlightBase)\n private readonly nativeElement = inject(ElementRef<HTMLElement>).nativeElement\n\n readonly startFrom = input<number | undefined, unknown>(this.options?.startFrom, {\n transform: numberAttribute\n })\n\n readonly singleLine = input<boolean | undefined, unknown>(this.options?.singleLine, {\n transform: booleanAttribute\n })\n\n constructor() {\n effect(() => {\n const hljs = this.hljs.hljs()\n const result = this.highlight.highlightResult()\n if (result?.value) {\n if ((hljs as any).lineNumbersBlock) {\n const code = (hljs as any).lineNumbersBlock(result.value, {\n startFrom: this.startFrom(),\n singleLine: this.singleLine()\n })\n this.nativeElement.innerHTML = code\n }\n // If lines count is 1, the line numbers library will not add numbers\n if (this.nativeElement.firstElementChild?.tagName.toUpperCase() === 'TABLE') {\n this.nativeElement.classList.add('hljs-line-numbers')\n } else {\n this.nativeElement.classList.remove('hljs-line-numbers')\n }\n }\n })\n }\n}\n"],"mappings":"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"}