@mantine-vue/code-highlight 3.1.0 → 3.3.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.
- package/cjs/index.cjs +144 -39
- package/cjs/index.cjs.map +1 -1
- package/esm/index.mjs +143 -41
- package/esm/index.mjs.map +1 -1
- package/lib/CodeHighlight/CodeHighlight.types.d.ts +2 -0
- package/lib/CodeHighlight/InlineCodeHighlight.types.d.ts +2 -0
- package/lib/CodeHighlightProvider/CodeHighlightProvider.d.ts +7 -1
- package/lib/CodeHighlightProvider/CodeHighlightProvider.types.d.ts +4 -0
- package/lib/CodeHighlightProvider/adapters/shiki-adapter.d.ts +2 -1
- package/lib/index.d.mts +3 -1
- package/lib/index.d.ts +3 -1
- package/lib/normalize-code.d.ts +6 -0
- package/package.json +3 -3
package/cjs/index.cjs
CHANGED
|
@@ -19,15 +19,49 @@ var CodeHighlightAdapterProvider_default = /* @__PURE__ */ (0, vue.defineCompone
|
|
|
19
19
|
setup(__props) {
|
|
20
20
|
const props = __props;
|
|
21
21
|
const context = (0, vue.ref)(null);
|
|
22
|
+
const contextLoaded = (0, vue.ref)(false);
|
|
23
|
+
const loadedLanguages = (0, vue.ref)([]);
|
|
24
|
+
const requestedLanguages = /* @__PURE__ */ new Set();
|
|
25
|
+
let generation = 0;
|
|
22
26
|
const highlight = (0, vue.computed)(() => props.adapter.getHighlighter(context.value));
|
|
23
|
-
(0, vue.
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
(0, vue.watch)(() => props.adapter, async (adapter) => {
|
|
28
|
+
const currentGeneration = ++generation;
|
|
29
|
+
context.value = null;
|
|
30
|
+
contextLoaded.value = !adapter.loadContext;
|
|
31
|
+
loadedLanguages.value = [];
|
|
32
|
+
requestedLanguages.clear();
|
|
33
|
+
if (adapter.loadContext) {
|
|
34
|
+
const value = await adapter.loadContext();
|
|
35
|
+
if (currentGeneration === generation) {
|
|
36
|
+
context.value = value;
|
|
37
|
+
contextLoaded.value = true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}, { immediate: true });
|
|
41
|
+
function loadLanguage(language) {
|
|
42
|
+
if (!contextLoaded.value || !language || !props.adapter.loadLanguage || requestedLanguages.has(language)) return;
|
|
43
|
+
const currentGeneration = generation;
|
|
44
|
+
requestedLanguages.add(language);
|
|
45
|
+
let result;
|
|
46
|
+
try {
|
|
47
|
+
result = props.adapter.loadLanguage(context.value, language);
|
|
48
|
+
} catch {
|
|
49
|
+
requestedLanguages.delete(language);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
result?.then(() => {
|
|
53
|
+
if (currentGeneration === generation && !loadedLanguages.value.includes(language)) loadedLanguages.value = [...loadedLanguages.value, language];
|
|
54
|
+
}, () => currentGeneration === generation && requestedLanguages.delete(language));
|
|
55
|
+
}
|
|
26
56
|
provideCodeHighlightAdapterContext({
|
|
27
|
-
adapter
|
|
57
|
+
get adapter() {
|
|
58
|
+
return props.adapter;
|
|
59
|
+
},
|
|
28
60
|
get highlight() {
|
|
29
61
|
return highlight.value;
|
|
30
|
-
}
|
|
62
|
+
},
|
|
63
|
+
loadLanguage,
|
|
64
|
+
isLanguageLoaded: (language) => !language || !props.adapter.loadLanguage || loadedLanguages.value.includes(language)
|
|
31
65
|
});
|
|
32
66
|
return (_ctx, _cache) => {
|
|
33
67
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$1, [(0, vue.renderSlot)(_ctx.$slots, "default")]);
|
|
@@ -41,10 +75,24 @@ function provideCodeHighlightAdapterContext(value) {
|
|
|
41
75
|
(0, vue.provide)(CodeHighlightContext, value);
|
|
42
76
|
}
|
|
43
77
|
function useHighlight() {
|
|
44
|
-
|
|
78
|
+
const ctx = (0, vue.inject)(CodeHighlightContext, null);
|
|
79
|
+
const fallback = plainTextAdapter.getHighlighter(null);
|
|
80
|
+
return (input) => (ctx?.highlight || fallback)(input);
|
|
81
|
+
}
|
|
82
|
+
function useLoadLanguage() {
|
|
83
|
+
return (0, vue.inject)(CodeHighlightContext, null)?.loadLanguage || (() => {});
|
|
84
|
+
}
|
|
85
|
+
function useIsLanguageLoaded() {
|
|
86
|
+
return (0, vue.inject)(CodeHighlightContext, null)?.isLanguageLoaded || (() => true);
|
|
45
87
|
}
|
|
46
88
|
var CodeHighlightAdapterProvider = CodeHighlightAdapterProvider_default;
|
|
47
89
|
//#endregion
|
|
90
|
+
//#region src/normalize-code.ts
|
|
91
|
+
/** Removes blank leading lines and trailing whitespace before highlighting or copying code. */
|
|
92
|
+
function normalizeCode(code, { withFirstLineIndentation } = {}) {
|
|
93
|
+
return withFirstLineIndentation ? code.replace(/^(?:[^\S\r\n]*\r?\n)+|\s+$/g, "") : code.trim();
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
48
96
|
//#region src/CodeHighlight/CodeHighlight.context.ts
|
|
49
97
|
var [provideCodeHighlightContext, useCodeHighlightContext] = (0, _mantine_vue_core.createSafeContext)("CodeHighlightProvider was not found in the component tree");
|
|
50
98
|
//#endregion
|
|
@@ -163,7 +211,7 @@ var CopyCodeButton_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
163
211
|
variant: "none",
|
|
164
212
|
"tooltip-label": (0, vue.unref)(clipboard).copied.value ? props.copiedLabel : props.copyLabel,
|
|
165
213
|
"aria-label": (0, vue.unref)(clipboard).copied.value ? props.copiedLabel : `${props.copyLabel} code`,
|
|
166
|
-
onClick: _cache[0] || (_cache[0] = ($event) => (0, vue.unref)(clipboard).copy(props.code
|
|
214
|
+
onClick: _cache[0] || (_cache[0] = ($event) => (0, vue.unref)(clipboard).copy(props.code))
|
|
167
215
|
}, {
|
|
168
216
|
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(CopyIcon_default, { copied: (0, vue.unref)(clipboard).copied.value }, null, 8, ["copied"])]),
|
|
169
217
|
_: 1
|
|
@@ -309,7 +357,8 @@ var CodeHighlight_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
309
357
|
default: false
|
|
310
358
|
},
|
|
311
359
|
controls: {},
|
|
312
|
-
codeColorScheme: {}
|
|
360
|
+
codeColorScheme: {},
|
|
361
|
+
withFirstLineIndentation: { type: Boolean }
|
|
313
362
|
},
|
|
314
363
|
emits: ["update:expanded", "expanded-change"],
|
|
315
364
|
setup(__props, { emit: __emit }) {
|
|
@@ -342,21 +391,28 @@ var CodeHighlight_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
342
391
|
}
|
|
343
392
|
});
|
|
344
393
|
const highlight = useHighlight();
|
|
394
|
+
const loadLanguage = useLoadLanguage();
|
|
395
|
+
const isLanguageLoaded = useIsLanguageLoaded();
|
|
396
|
+
const normalizedCode = (0, vue.computed)(() => normalizeCode(props.code, { withFirstLineIndentation: props.withFirstLineIndentation }));
|
|
397
|
+
(0, vue.watchEffect)(() => loadLanguage(props.language));
|
|
345
398
|
function resolveColorScheme(value) {
|
|
346
399
|
if (value !== "auto") return value;
|
|
347
400
|
return typeof window !== "undefined" && window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
348
401
|
}
|
|
349
|
-
const highlighted = (0, vue.computed)(() =>
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
402
|
+
const highlighted = (0, vue.computed)(() => {
|
|
403
|
+
isLanguageLoaded(props.language);
|
|
404
|
+
return highlight({
|
|
405
|
+
code: normalizedCode.value,
|
|
406
|
+
language: props.language,
|
|
407
|
+
colorScheme: props.codeColorScheme ?? resolveColorScheme(mantine.colorScheme.value)
|
|
408
|
+
});
|
|
409
|
+
});
|
|
354
410
|
const renderedControls = (0, vue.computed)(() => {
|
|
355
411
|
const value = props.controls !== void 0 ? typeof props.controls === "function" ? props.controls() : props.controls : slots.controls?.();
|
|
356
412
|
return Array.isArray(value) ? value : value ? [value] : [];
|
|
357
413
|
});
|
|
358
414
|
const shouldDisplayControls = (0, vue.computed)(() => renderedControls.value.length > 0 || props.withExpandButton || props.withCopyButton);
|
|
359
|
-
const lineNumbers = (0, vue.computed)(() =>
|
|
415
|
+
const lineNumbers = (0, vue.computed)(() => normalizedCode.value.split("\n").map((_, index) => index + 1));
|
|
360
416
|
const renderControls = () => renderedControls.value;
|
|
361
417
|
provideCodeHighlightContext({
|
|
362
418
|
getStyles,
|
|
@@ -382,7 +438,7 @@ var CodeHighlight_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
382
438
|
className: [highlighted.value.codeElementProps?.class, (0, vue.unref)(attrs).class],
|
|
383
439
|
style: [highlighted.value.codeElementProps?.style, (0, vue.unref)(attrs).style]
|
|
384
440
|
})
|
|
385
|
-
}, { "data-with-border": (0, vue.unref)(props).withBorder || void 0 }), (0, vue.toDisplayString)(
|
|
441
|
+
}, { "data-with-border": (0, vue.unref)(props).withBorder || void 0 }), (0, vue.toDisplayString)(normalizedCode.value), 17, _hoisted_2)) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_mantine_vue_core.Box), (0, vue.mergeProps)({ key: 2 }, {
|
|
386
442
|
...(0, vue.unref)(attrs),
|
|
387
443
|
...(0, vue.unref)(getStyles)("codeHighlight")
|
|
388
444
|
}, {
|
|
@@ -407,7 +463,7 @@ var CodeHighlight_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
407
463
|
])) : (0, vue.createCommentVNode)("", true),
|
|
408
464
|
(0, vue.unref)(props).withCopyButton ? ((0, vue.openBlock)(), (0, vue.createBlock)(CopyCodeButton_default, {
|
|
409
465
|
key: 1,
|
|
410
|
-
code:
|
|
466
|
+
code: normalizedCode.value,
|
|
411
467
|
"copied-label": (0, vue.unref)(props).copiedLabel,
|
|
412
468
|
"copy-label": (0, vue.unref)(props).copyLabel
|
|
413
469
|
}, null, 8, [
|
|
@@ -438,7 +494,7 @@ var CodeHighlight_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
438
494
|
className: highlighted.value.codeElementProps?.class,
|
|
439
495
|
style: highlighted.value.codeElementProps?.style
|
|
440
496
|
})
|
|
441
|
-
})), (0, vue.toDisplayString)(
|
|
497
|
+
})), (0, vue.toDisplayString)(normalizedCode.value), 17))], 16, _hoisted_5)], 16)]),
|
|
442
498
|
_: 1
|
|
443
499
|
}, 16, ["data-collapsed"]),
|
|
444
500
|
(0, vue.createVNode)((0, vue.unref)(_mantine_vue_core.UnstyledButton), (0, vue.mergeProps)((0, vue.unref)(getStyles)("showCodeButton"), {
|
|
@@ -483,6 +539,7 @@ var InlineCodeHighlight = Object.assign(/* @__PURE__ */ (0, vue.defineComponent)
|
|
|
483
539
|
type: Boolean,
|
|
484
540
|
default: false
|
|
485
541
|
},
|
|
542
|
+
withFirstLineIndentation: { type: Boolean },
|
|
486
543
|
classNames: {},
|
|
487
544
|
styles: {},
|
|
488
545
|
vars: {},
|
|
@@ -593,7 +650,8 @@ var CodeHighlightTabs = Object.assign(/* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
593
650
|
default: false
|
|
594
651
|
},
|
|
595
652
|
controls: {},
|
|
596
|
-
codeColorScheme: {}
|
|
653
|
+
codeColorScheme: {},
|
|
654
|
+
withFirstLineIndentation: { type: Boolean }
|
|
597
655
|
},
|
|
598
656
|
emits: [
|
|
599
657
|
"update:activeTab",
|
|
@@ -695,6 +753,7 @@ var CodeHighlightTabs = Object.assign(/* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
695
753
|
controls: (0, vue.unref)(props).controls,
|
|
696
754
|
"code-color-scheme": (0, vue.unref)(props).codeColorScheme,
|
|
697
755
|
"with-line-numbers": (0, vue.unref)(props).withLineNumbers,
|
|
756
|
+
"with-first-line-indentation": (0, vue.unref)(props).withFirstLineIndentation,
|
|
698
757
|
"__with-offset": "",
|
|
699
758
|
"__static-selector": "CodeHighlightTabs",
|
|
700
759
|
onExpandedChange: (0, vue.unref)(setExpanded),
|
|
@@ -721,6 +780,7 @@ var CodeHighlightTabs = Object.assign(/* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
721
780
|
"controls",
|
|
722
781
|
"code-color-scheme",
|
|
723
782
|
"with-line-numbers",
|
|
783
|
+
"with-first-line-indentation",
|
|
724
784
|
"onExpandedChange",
|
|
725
785
|
"class-names",
|
|
726
786
|
"styles"
|
|
@@ -736,7 +796,7 @@ function createHighlightJsAdapter(hljs) {
|
|
|
736
796
|
return { getHighlighter: () => ({ code, language }) => {
|
|
737
797
|
const lang = hljs.getLanguage(language) ? language : "plaintext";
|
|
738
798
|
return {
|
|
739
|
-
highlightedCode: hljs.highlight(code
|
|
799
|
+
highlightedCode: hljs.highlight(code, { language: lang }).value,
|
|
740
800
|
isHighlighted: true,
|
|
741
801
|
codeElementProps: { class: `hljs ${lang}` }
|
|
742
802
|
};
|
|
@@ -1889,27 +1949,69 @@ function stripElement(openTag, data) {
|
|
|
1889
1949
|
function stripShikiCodeBlocks(data) {
|
|
1890
1950
|
return stripElement("code", stripElement("pre", data));
|
|
1891
1951
|
}
|
|
1892
|
-
var
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1952
|
+
var specialLanguages = [
|
|
1953
|
+
"text",
|
|
1954
|
+
"plaintext",
|
|
1955
|
+
"txt",
|
|
1956
|
+
"plain",
|
|
1957
|
+
"ansi"
|
|
1958
|
+
];
|
|
1959
|
+
function isLanguageAvailable(ctx, language) {
|
|
1960
|
+
return !language || specialLanguages.includes(language) || typeof ctx.getLoadedLanguages !== "function" || ctx.getLoadedLanguages().includes(language);
|
|
1961
|
+
}
|
|
1962
|
+
var createShikiAdapter = (loadShiki, { forceColorScheme, resolveLanguage } = {}) => {
|
|
1963
|
+
const warnedLanguages = /* @__PURE__ */ new Set();
|
|
1964
|
+
const warnUnavailable = (language, reason) => {
|
|
1965
|
+
if (warnedLanguages.has(language)) return;
|
|
1966
|
+
warnedLanguages.add(language);
|
|
1967
|
+
console.warn(`[@mantine-vue/code-highlight] Language \`${language}\` ${reason}, code is rendered as plain text.`);
|
|
1968
|
+
};
|
|
1969
|
+
return {
|
|
1970
|
+
loadContext: loadShiki,
|
|
1971
|
+
loadLanguage: resolveLanguage ? (ctx, language) => {
|
|
1972
|
+
if (isLanguageAvailable(ctx, language)) return void 0;
|
|
1973
|
+
const onLoadError = (error) => {
|
|
1974
|
+
warnUnavailable(language, "could not be loaded");
|
|
1975
|
+
throw error;
|
|
1909
1976
|
};
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1977
|
+
try {
|
|
1978
|
+
const grammar = resolveLanguage(language);
|
|
1979
|
+
if (!grammar) {
|
|
1980
|
+
warnUnavailable(language, "was not resolved by `resolveLanguage`");
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1983
|
+
return Promise.resolve(ctx.loadLanguage(grammar)).catch(onLoadError);
|
|
1984
|
+
} catch (error) {
|
|
1985
|
+
return Promise.reject(error).catch(onLoadError);
|
|
1986
|
+
}
|
|
1987
|
+
} : void 0,
|
|
1988
|
+
getHighlighter: (ctx) => {
|
|
1989
|
+
if (!ctx) return ({ code }) => ({
|
|
1990
|
+
highlightedCode: code,
|
|
1991
|
+
isHighlighted: false
|
|
1992
|
+
});
|
|
1993
|
+
return ({ code, language, colorScheme }) => {
|
|
1994
|
+
if (!isLanguageAvailable(ctx, language)) {
|
|
1995
|
+
if (!resolveLanguage && language) warnUnavailable(language, "is not loaded");
|
|
1996
|
+
return {
|
|
1997
|
+
highlightedCode: code,
|
|
1998
|
+
isHighlighted: false
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
let _colorScheme = colorScheme;
|
|
2002
|
+
if (colorScheme === "light") _colorScheme = light;
|
|
2003
|
+
else if (colorScheme === "dark") _colorScheme = dark;
|
|
2004
|
+
return {
|
|
2005
|
+
isHighlighted: true,
|
|
2006
|
+
highlightedCode: stripShikiCodeBlocks(ctx.codeToHtml(code, {
|
|
2007
|
+
lang: language,
|
|
2008
|
+
theme: forceColorScheme || _colorScheme
|
|
2009
|
+
}))
|
|
2010
|
+
};
|
|
2011
|
+
};
|
|
2012
|
+
}
|
|
2013
|
+
};
|
|
2014
|
+
};
|
|
1913
2015
|
//#endregion
|
|
1914
2016
|
exports.CodeHighlight = CodeHighlight;
|
|
1915
2017
|
exports.CodeHighlightAdapterProvider = CodeHighlightAdapterProvider;
|
|
@@ -1918,9 +2020,12 @@ exports.CodeHighlightTabs = CodeHighlightTabs;
|
|
|
1918
2020
|
exports.InlineCodeHighlight = InlineCodeHighlight;
|
|
1919
2021
|
exports.createHighlightJsAdapter = createHighlightJsAdapter;
|
|
1920
2022
|
exports.createShikiAdapter = createShikiAdapter;
|
|
2023
|
+
exports.normalizeCode = normalizeCode;
|
|
1921
2024
|
exports.plainTextAdapter = plainTextAdapter;
|
|
1922
2025
|
exports.stripShikiCodeBlocks = stripShikiCodeBlocks;
|
|
1923
2026
|
exports.useCodeHighlightContext = useCodeHighlightContext;
|
|
1924
2027
|
exports.useHighlight = useHighlight;
|
|
2028
|
+
exports.useIsLanguageLoaded = useIsLanguageLoaded;
|
|
2029
|
+
exports.useLoadLanguage = useLoadLanguage;
|
|
1925
2030
|
|
|
1926
2031
|
//# sourceMappingURL=index.cjs.map
|