创高项目初始化
This commit is contained in:
332
client/node_modules/quill/modules/syntax.js
generated
vendored
Normal file
332
client/node_modules/quill/modules/syntax.js
generated
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
import Delta from 'quill-delta';
|
||||
import { ClassAttributor, Scope } from 'parchment';
|
||||
import Inline from '../blots/inline.js';
|
||||
import Quill from '../core/quill.js';
|
||||
import Module from '../core/module.js';
|
||||
import { blockDelta } from '../blots/block.js';
|
||||
import BreakBlot from '../blots/break.js';
|
||||
import CursorBlot from '../blots/cursor.js';
|
||||
import TextBlot, { escapeText } from '../blots/text.js';
|
||||
import CodeBlock, { CodeBlockContainer } from '../formats/code.js';
|
||||
import { traverse } from './clipboard.js';
|
||||
const TokenAttributor = new ClassAttributor('code-token', 'hljs', {
|
||||
scope: Scope.INLINE
|
||||
});
|
||||
class CodeToken extends Inline {
|
||||
static formats(node, scroll) {
|
||||
while (node != null && node !== scroll.domNode) {
|
||||
if (node.classList && node.classList.contains(CodeBlock.className)) {
|
||||
// @ts-expect-error
|
||||
return super.formats(node, scroll);
|
||||
}
|
||||
// @ts-expect-error
|
||||
node = node.parentNode;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
constructor(scroll, domNode, value) {
|
||||
// @ts-expect-error
|
||||
super(scroll, domNode, value);
|
||||
TokenAttributor.add(this.domNode, value);
|
||||
}
|
||||
format(format, value) {
|
||||
if (format !== CodeToken.blotName) {
|
||||
super.format(format, value);
|
||||
} else if (value) {
|
||||
TokenAttributor.add(this.domNode, value);
|
||||
} else {
|
||||
TokenAttributor.remove(this.domNode);
|
||||
this.domNode.classList.remove(this.statics.className);
|
||||
}
|
||||
}
|
||||
optimize() {
|
||||
// @ts-expect-error
|
||||
super.optimize(...arguments);
|
||||
if (!TokenAttributor.value(this.domNode)) {
|
||||
this.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
CodeToken.blotName = 'code-token';
|
||||
CodeToken.className = 'ql-token';
|
||||
class SyntaxCodeBlock extends CodeBlock {
|
||||
static create(value) {
|
||||
const domNode = super.create(value);
|
||||
if (typeof value === 'string') {
|
||||
domNode.setAttribute('data-language', value);
|
||||
}
|
||||
return domNode;
|
||||
}
|
||||
static formats(domNode) {
|
||||
// @ts-expect-error
|
||||
return domNode.getAttribute('data-language') || 'plain';
|
||||
}
|
||||
static register() {} // Syntax module will register
|
||||
|
||||
format(name, value) {
|
||||
if (name === this.statics.blotName && value) {
|
||||
// @ts-expect-error
|
||||
this.domNode.setAttribute('data-language', value);
|
||||
} else {
|
||||
super.format(name, value);
|
||||
}
|
||||
}
|
||||
replaceWith(name, value) {
|
||||
this.formatAt(0, this.length(), CodeToken.blotName, false);
|
||||
return super.replaceWith(name, value);
|
||||
}
|
||||
}
|
||||
class SyntaxCodeBlockContainer extends CodeBlockContainer {
|
||||
attach() {
|
||||
super.attach();
|
||||
this.forceNext = false;
|
||||
// @ts-expect-error
|
||||
this.scroll.emitMount(this);
|
||||
}
|
||||
format(name, value) {
|
||||
if (name === SyntaxCodeBlock.blotName) {
|
||||
this.forceNext = true;
|
||||
this.children.forEach(child => {
|
||||
// @ts-expect-error
|
||||
child.format(name, value);
|
||||
});
|
||||
}
|
||||
}
|
||||
formatAt(index, length, name, value) {
|
||||
if (name === SyntaxCodeBlock.blotName) {
|
||||
this.forceNext = true;
|
||||
}
|
||||
super.formatAt(index, length, name, value);
|
||||
}
|
||||
highlight(highlight) {
|
||||
let forced = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||||
if (this.children.head == null) return;
|
||||
const nodes = Array.from(this.domNode.childNodes).filter(node => node !== this.uiNode);
|
||||
const text = `${nodes.map(node => node.textContent).join('\n')}\n`;
|
||||
const language = SyntaxCodeBlock.formats(this.children.head.domNode);
|
||||
if (forced || this.forceNext || this.cachedText !== text) {
|
||||
if (text.trim().length > 0 || this.cachedText == null) {
|
||||
const oldDelta = this.children.reduce((delta, child) => {
|
||||
// @ts-expect-error
|
||||
return delta.concat(blockDelta(child, false));
|
||||
}, new Delta());
|
||||
const delta = highlight(text, language);
|
||||
oldDelta.diff(delta).reduce((index, _ref) => {
|
||||
let {
|
||||
retain,
|
||||
attributes
|
||||
} = _ref;
|
||||
// Should be all retains
|
||||
if (!retain) return index;
|
||||
if (attributes) {
|
||||
Object.keys(attributes).forEach(format => {
|
||||
if ([SyntaxCodeBlock.blotName, CodeToken.blotName].includes(format)) {
|
||||
// @ts-expect-error
|
||||
this.formatAt(index, retain, format, attributes[format]);
|
||||
}
|
||||
});
|
||||
}
|
||||
// @ts-expect-error
|
||||
return index + retain;
|
||||
}, 0);
|
||||
}
|
||||
this.cachedText = text;
|
||||
this.forceNext = false;
|
||||
}
|
||||
}
|
||||
html(index, length) {
|
||||
const [codeBlock] = this.children.find(index);
|
||||
const language = codeBlock ? SyntaxCodeBlock.formats(codeBlock.domNode) : 'plain';
|
||||
return `<pre data-language="${language}">\n${escapeText(this.code(index, length))}\n</pre>`;
|
||||
}
|
||||
optimize(context) {
|
||||
super.optimize(context);
|
||||
if (this.parent != null && this.children.head != null && this.uiNode != null) {
|
||||
const language = SyntaxCodeBlock.formats(this.children.head.domNode);
|
||||
// @ts-expect-error
|
||||
if (language !== this.uiNode.value) {
|
||||
// @ts-expect-error
|
||||
this.uiNode.value = language;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SyntaxCodeBlockContainer.allowedChildren = [SyntaxCodeBlock];
|
||||
SyntaxCodeBlock.requiredContainer = SyntaxCodeBlockContainer;
|
||||
SyntaxCodeBlock.allowedChildren = [CodeToken, CursorBlot, TextBlot, BreakBlot];
|
||||
const highlight = (lib, language, text) => {
|
||||
if (typeof lib.versionString === 'string') {
|
||||
const majorVersion = lib.versionString.split('.')[0];
|
||||
if (parseInt(majorVersion, 10) >= 11) {
|
||||
return lib.highlight(text, {
|
||||
language
|
||||
}).value;
|
||||
}
|
||||
}
|
||||
return lib.highlight(language, text).value;
|
||||
};
|
||||
class Syntax extends Module {
|
||||
static register() {
|
||||
Quill.register(CodeToken, true);
|
||||
Quill.register(SyntaxCodeBlock, true);
|
||||
Quill.register(SyntaxCodeBlockContainer, true);
|
||||
}
|
||||
constructor(quill, options) {
|
||||
super(quill, options);
|
||||
if (this.options.hljs == null) {
|
||||
throw new Error('Syntax module requires highlight.js. Please include the library on the page before Quill.');
|
||||
}
|
||||
// @ts-expect-error Fix me later
|
||||
this.languages = this.options.languages.reduce((memo, _ref2) => {
|
||||
let {
|
||||
key
|
||||
} = _ref2;
|
||||
memo[key] = true;
|
||||
return memo;
|
||||
}, {});
|
||||
this.highlightBlot = this.highlightBlot.bind(this);
|
||||
this.initListener();
|
||||
this.initTimer();
|
||||
}
|
||||
initListener() {
|
||||
this.quill.on(Quill.events.SCROLL_BLOT_MOUNT, blot => {
|
||||
if (!(blot instanceof SyntaxCodeBlockContainer)) return;
|
||||
const select = this.quill.root.ownerDocument.createElement('select');
|
||||
// @ts-expect-error Fix me later
|
||||
this.options.languages.forEach(_ref3 => {
|
||||
let {
|
||||
key,
|
||||
label
|
||||
} = _ref3;
|
||||
const option = select.ownerDocument.createElement('option');
|
||||
option.textContent = label;
|
||||
option.setAttribute('value', key);
|
||||
select.appendChild(option);
|
||||
});
|
||||
select.addEventListener('change', () => {
|
||||
blot.format(SyntaxCodeBlock.blotName, select.value);
|
||||
this.quill.root.focus(); // Prevent scrolling
|
||||
this.highlight(blot, true);
|
||||
});
|
||||
if (blot.uiNode == null) {
|
||||
blot.attachUI(select);
|
||||
if (blot.children.head) {
|
||||
select.value = SyntaxCodeBlock.formats(blot.children.head.domNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
initTimer() {
|
||||
let timer = null;
|
||||
this.quill.on(Quill.events.SCROLL_OPTIMIZE, () => {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
timer = setTimeout(() => {
|
||||
this.highlight();
|
||||
timer = null;
|
||||
}, this.options.interval);
|
||||
});
|
||||
}
|
||||
highlight() {
|
||||
let blot = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
||||
let force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||||
if (this.quill.selection.composing) return;
|
||||
this.quill.update(Quill.sources.USER);
|
||||
const range = this.quill.getSelection();
|
||||
const blots = blot == null ? this.quill.scroll.descendants(SyntaxCodeBlockContainer) : [blot];
|
||||
blots.forEach(container => {
|
||||
container.highlight(this.highlightBlot, force);
|
||||
});
|
||||
this.quill.update(Quill.sources.SILENT);
|
||||
if (range != null) {
|
||||
this.quill.setSelection(range, Quill.sources.SILENT);
|
||||
}
|
||||
}
|
||||
highlightBlot(text) {
|
||||
let language = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'plain';
|
||||
language = this.languages[language] ? language : 'plain';
|
||||
if (language === 'plain') {
|
||||
return escapeText(text).split('\n').reduce((delta, line, i) => {
|
||||
if (i !== 0) {
|
||||
delta.insert('\n', {
|
||||
[CodeBlock.blotName]: language
|
||||
});
|
||||
}
|
||||
return delta.insert(line);
|
||||
}, new Delta());
|
||||
}
|
||||
const container = this.quill.root.ownerDocument.createElement('div');
|
||||
container.classList.add(CodeBlock.className);
|
||||
container.innerHTML = highlight(this.options.hljs, language, text);
|
||||
return traverse(this.quill.scroll, container, [(node, delta) => {
|
||||
// @ts-expect-error
|
||||
const value = TokenAttributor.value(node);
|
||||
if (value) {
|
||||
return delta.compose(new Delta().retain(delta.length(), {
|
||||
[CodeToken.blotName]: value
|
||||
}));
|
||||
}
|
||||
return delta;
|
||||
}], [(node, delta) => {
|
||||
// @ts-expect-error
|
||||
return node.data.split('\n').reduce((memo, nodeText, i) => {
|
||||
if (i !== 0) memo.insert('\n', {
|
||||
[CodeBlock.blotName]: language
|
||||
});
|
||||
return memo.insert(nodeText);
|
||||
}, delta);
|
||||
}], new WeakMap());
|
||||
}
|
||||
}
|
||||
Syntax.DEFAULTS = {
|
||||
hljs: (() => {
|
||||
return window.hljs;
|
||||
})(),
|
||||
interval: 1000,
|
||||
languages: [{
|
||||
key: 'plain',
|
||||
label: 'Plain'
|
||||
}, {
|
||||
key: 'bash',
|
||||
label: 'Bash'
|
||||
}, {
|
||||
key: 'cpp',
|
||||
label: 'C++'
|
||||
}, {
|
||||
key: 'cs',
|
||||
label: 'C#'
|
||||
}, {
|
||||
key: 'css',
|
||||
label: 'CSS'
|
||||
}, {
|
||||
key: 'diff',
|
||||
label: 'Diff'
|
||||
}, {
|
||||
key: 'xml',
|
||||
label: 'HTML/XML'
|
||||
}, {
|
||||
key: 'java',
|
||||
label: 'Java'
|
||||
}, {
|
||||
key: 'javascript',
|
||||
label: 'JavaScript'
|
||||
}, {
|
||||
key: 'markdown',
|
||||
label: 'Markdown'
|
||||
}, {
|
||||
key: 'php',
|
||||
label: 'PHP'
|
||||
}, {
|
||||
key: 'python',
|
||||
label: 'Python'
|
||||
}, {
|
||||
key: 'ruby',
|
||||
label: 'Ruby'
|
||||
}, {
|
||||
key: 'sql',
|
||||
label: 'SQL'
|
||||
}]
|
||||
};
|
||||
export { SyntaxCodeBlock as CodeBlock, CodeToken, Syntax as default };
|
||||
//# sourceMappingURL=syntax.js.map
|
||||
Reference in New Issue
Block a user