mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
ui: shiki: improve load speed
This commit is contained in:
2 files changed
+95
-57
No files matched your search
@@ -89,6 +89,7 @@ code
|
|||||||
border-radius: 0px !important
|
border-radius: 0px !important
|
||||||
background: none !important
|
background: none !important
|
||||||
box-shadow: 0 2px #0003
|
box-shadow: 0 2px #0003
|
||||||
|
text-decoration: none
|
||||||
padding: 0 .5em
|
padding: 0 .5em
|
||||||
color: #bbb
|
color: #bbb
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ import {
|
|||||||
transformerMetaHighlight, transformerNotationDiff, transformerNotationHighlight,
|
transformerMetaHighlight, transformerNotationDiff, transformerNotationHighlight,
|
||||||
transformerNotationWordHighlight, transformerRenderWhitespace,
|
transformerNotationWordHighlight, transformerRenderWhitespace,
|
||||||
} from '@shikijs/transformers';
|
} from '@shikijs/transformers';
|
||||||
|
import type { ElementContent } from 'hast';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import Notification from 'vj/components/notification/index';
|
import Notification from 'vj/components/notification/index';
|
||||||
import { getFeatures, load as loadModule } from 'vj/lazyload';
|
import { getFeatures, load as loadModule } from 'vj/lazyload';
|
||||||
import { i18n } from 'vj/utils';
|
import { i18n } from 'vj/utils';
|
||||||
import { addLanguage, bundledLanguages, createHighlighter } from './bundle';
|
import {
|
||||||
|
addLanguage, bundledLanguages, bundledLanguagesInfo, createHighlighter,
|
||||||
|
} from './bundle';
|
||||||
|
|
||||||
$(document).on('click', '[data-clipboard-text]', function (ev) {
|
$(document).on('click', '[data-clipboard-text]', function (ev) {
|
||||||
const content = $(this).attr('data-clipboard-text');
|
const content = $(this).attr('data-clipboard-text');
|
||||||
@@ -19,7 +22,7 @@ $(document).on('click', '[data-clipboard-text]', function (ev) {
|
|||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
const transformers = [
|
const baseTransformers = [
|
||||||
transformerNotationDiff(),
|
transformerNotationDiff(),
|
||||||
transformerNotationHighlight(),
|
transformerNotationHighlight(),
|
||||||
transformerNotationWordHighlight(),
|
transformerNotationWordHighlight(),
|
||||||
@@ -27,20 +30,101 @@ const transformers = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
if (UserContext.showInvisibleChar) {
|
if (UserContext.showInvisibleChar) {
|
||||||
transformers.push(transformerRenderWhitespace());
|
baseTransformers.push(transformerRenderWhitespace());
|
||||||
}
|
}
|
||||||
|
|
||||||
async function highlightBlocks($dom) {
|
async function highlightBlocks($dom) {
|
||||||
for (const code of $dom.find('pre code').get()) {
|
const nodes = $dom.find('pre code').get();
|
||||||
|
if (!nodes.length) return;
|
||||||
|
const shikiPlain = await createHighlighter({ langs: ['text'], themes: ['github-dark', 'light-plus'] });
|
||||||
|
const requestedLanguages = new Set<string>([]);
|
||||||
|
const tasks = [];
|
||||||
|
for (const code of nodes) {
|
||||||
const $code = $(code);
|
const $code = $(code);
|
||||||
const $pre = $code.parent();
|
const $pre = $code.parent();
|
||||||
if ($pre.hasClass('syntax-hl')) continue;
|
if ($pre.hasClass('syntax-hl')) continue;
|
||||||
const language = ($(code).attr('class') || '').trim();
|
const language = ($(code).attr('class') || '').trim();
|
||||||
// try to map the language name
|
// try to map the language name
|
||||||
const m = language.match(/language-([a-z0-9]+)(?=\.line-numbers)?(?=\|([\d,-]+))?/);
|
const m = language.match(/language-([a-zA-Z0-9]+)(?=\.line-numbers)?(?=\|([\d,-]+))?/);
|
||||||
if (!m) continue;
|
if (!m) continue;
|
||||||
if (!bundledLanguages[m[1]]) {
|
const name = m[1].toLowerCase();
|
||||||
const features = await getFeatures(`shiki-${m[1]}`);
|
const toolbarContents: ElementContent[] = [
|
||||||
|
{
|
||||||
|
tagName: 'a',
|
||||||
|
type: 'element',
|
||||||
|
properties: {
|
||||||
|
href: 'javascript:;',
|
||||||
|
class: 'copy-to-clipboard',
|
||||||
|
'data-clipboard-text': $code.text(),
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{ type: 'text', value: 'Copy' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
if (!name.startsWith('input') && !name.startsWith('output')) {
|
||||||
|
toolbarContents.unshift({
|
||||||
|
tagName: 'span',
|
||||||
|
type: 'element',
|
||||||
|
properties: {
|
||||||
|
style: 'padding: 0 10px 0 10px',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{ type: 'text', value: bundledLanguagesInfo[m[1]]?.name || m[1] },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const toolbar: ElementContent = {
|
||||||
|
tagName: 'div',
|
||||||
|
type: 'element',
|
||||||
|
properties: {
|
||||||
|
class: 'toolbar',
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
tagName: 'div',
|
||||||
|
type: 'element',
|
||||||
|
properties: {
|
||||||
|
class: 'toolbar-item',
|
||||||
|
},
|
||||||
|
children: toolbarContents,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const transformers = baseTransformers.concat({
|
||||||
|
pre(node) {
|
||||||
|
this.addClassToHast(node, 'syntax-hl');
|
||||||
|
if (language.includes('line-numbers')) {
|
||||||
|
this.addClassToHast(node, 'line-numbers');
|
||||||
|
}
|
||||||
|
node.children.push(toolbar);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const $plain = $(shikiPlain.codeToHtml($code.text(), {
|
||||||
|
lang: 'text',
|
||||||
|
theme: 'light-plus',
|
||||||
|
meta: {
|
||||||
|
__raw: m[2] ? `{${m[2]}}` : null,
|
||||||
|
},
|
||||||
|
transformers,
|
||||||
|
}));
|
||||||
|
$pre.replaceWith($plain);
|
||||||
|
requestedLanguages.add(name);
|
||||||
|
tasks.push((shiki) => {
|
||||||
|
if (!bundledLanguages[name]) return;
|
||||||
|
$plain.replaceWith($(shiki.codeToHtml($code.text(), {
|
||||||
|
lang: name,
|
||||||
|
theme: 'light-plus',
|
||||||
|
meta: {
|
||||||
|
__raw: m[2] ? `{${m[2]}}` : null,
|
||||||
|
},
|
||||||
|
transformers,
|
||||||
|
})));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
for (const name of requestedLanguages) {
|
||||||
|
if (!bundledLanguages[name]) {
|
||||||
|
const features = await getFeatures(`shiki-${name}`);
|
||||||
for (const item of features) {
|
for (const item of features) {
|
||||||
let apply = typeof item === 'function'
|
let apply = typeof item === 'function'
|
||||||
? item
|
? item
|
||||||
@@ -51,57 +135,10 @@ async function highlightBlocks($dom) {
|
|||||||
if (typeof apply === 'function') await apply(addLanguage);
|
if (typeof apply === 'function') await apply(addLanguage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const highlightLang = bundledLanguages[m[1]] ? m[1] : 'none';
|
if (!bundledLanguages[name]) requestedLanguages.delete(name);
|
||||||
const shiki = await createHighlighter({
|
|
||||||
langs: [highlightLang],
|
|
||||||
themes: ['github-dark', 'light-plus'],
|
|
||||||
});
|
|
||||||
$pre.replaceWith($(shiki.codeToHtml($code.text(), {
|
|
||||||
lang: highlightLang,
|
|
||||||
theme: 'light-plus',
|
|
||||||
meta: {
|
|
||||||
__raw: m[2] ? `{${m[2]}}` : null,
|
|
||||||
},
|
|
||||||
transformers: transformers.concat({
|
|
||||||
pre(node) {
|
|
||||||
this.addClassToHast(node, 'syntax-hl');
|
|
||||||
if (language.includes('line-numbers')) {
|
|
||||||
this.addClassToHast(node, 'line-numbers');
|
|
||||||
}
|
|
||||||
node.children.push({
|
|
||||||
tagName: 'div',
|
|
||||||
type: 'element',
|
|
||||||
properties: {
|
|
||||||
class: 'toolbar',
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
tagName: 'div',
|
|
||||||
type: 'element',
|
|
||||||
properties: {
|
|
||||||
class: 'toolbar-item',
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
tagName: 'a',
|
|
||||||
type: 'element',
|
|
||||||
properties: {
|
|
||||||
href: 'javascript:;',
|
|
||||||
class: 'copy-to-clipboard',
|
|
||||||
'data-clipboard-text': $code.text(),
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{ type: 'text', value: 'Copy' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
})));
|
|
||||||
}
|
}
|
||||||
|
const shiki = await createHighlighter({ langs: Array.from(requestedLanguages), themes: ['github-dark', 'light-plus'] });
|
||||||
|
for (const task of tasks) task(shiki);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function highlight(text: string, grammar, language) {
|
async function highlight(text: string, grammar, language) {
|
||||||
|
|||||||
Reference in new issue
Block a user