⚡ Improve app launch speed
This commit is contained in:
@@ -24,6 +24,7 @@ import {moveLineDown, moveLineUp} from './moveLines';
|
||||
import {getCodeBlockLanguageExtension} from './lang-parser';
|
||||
import {createLanguageDetection} from './lang-detect';
|
||||
import {SupportedLanguage} from './types';
|
||||
import {getMathBlockExtensions} from './mathBlock';
|
||||
|
||||
/**
|
||||
* 代码块扩展配置选项
|
||||
@@ -117,6 +118,9 @@ export function createCodeBlockExtension(options: CodeBlockOptions = {}): Extens
|
||||
// 复制粘贴功能
|
||||
...getCopyPasteExtensions(),
|
||||
|
||||
// 数学块功能
|
||||
...getMathBlockExtensions(),
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
@@ -149,7 +153,7 @@ export {
|
||||
export * from './commands';
|
||||
|
||||
// 格式化功能
|
||||
export { formatBlockContent } from './formatCode';
|
||||
export {formatBlockContent} from './formatCode';
|
||||
|
||||
// 选择功能
|
||||
export {
|
||||
@@ -202,6 +206,11 @@ export {
|
||||
// 行号相关
|
||||
export {getBlockLineFromPos, blockLineNumbers};
|
||||
|
||||
// 数学块功能
|
||||
export {
|
||||
getMathBlockExtensions
|
||||
} from './mathBlock';
|
||||
|
||||
/**
|
||||
* 默认导出
|
||||
*/
|
||||
|
||||
@@ -16,7 +16,7 @@ BlockLanguage {
|
||||
"text" | "json" | "py" | "html" | "sql" | "md" | "java" | "php" |
|
||||
"css" | "xml" | "cpp" | "rs" | "cs" | "rb" | "sh" | "yaml" | "toml" |
|
||||
"go" | "clj" | "ex" | "erl" | "js" | "ts" | "swift" | "kt" | "groovy" |
|
||||
"ps1" | "dart" | "scala"
|
||||
"ps1" | "dart" | "scala" | "math" | "dockerfile" | "lua"
|
||||
}
|
||||
|
||||
@tokens {
|
||||
|
||||
@@ -38,19 +38,16 @@ import htmlPrettierPlugin from "prettier/plugins/html"
|
||||
import cssPrettierPlugin from "prettier/plugins/postcss"
|
||||
import markdownPrettierPlugin from "prettier/plugins/markdown"
|
||||
import yamlPrettierPlugin from "prettier/plugins/yaml"
|
||||
import goPrettierPlugin from "@/common/prettier/plugins/go/go.mjs"
|
||||
import goPrettierPlugin from "@/common/prettier/plugins/go"
|
||||
import sqlPrettierPlugin from "@/common/prettier/plugins/sql"
|
||||
import phpPrettierPlugin from "@/common/prettier/plugins/php"
|
||||
import javaPrettierPlugin from "@/common/prettier/plugins/java"
|
||||
import xmlPrettierPlugin from "@prettier/plugin-xml"
|
||||
import * as rustPrettierPlugin from "@/common/prettier/plugins/rust";
|
||||
import * as shellPrettierPlugin from "@/common/prettier/plugins/shell";
|
||||
import * as dockerfilePrettierPlugin from "@/common/prettier/plugins/shell";
|
||||
// import rustPrettierPlugin from "@/common/prettier/plugins/rust_fmt";
|
||||
import rustPrettierPlugin from "@/common/prettier/plugins/rust";
|
||||
import tomlPrettierPlugin from "@/common/prettier/plugins/toml";
|
||||
import clojurePrettierPlugin from "@cospaia/prettier-plugin-clojure";
|
||||
import groovyPrettierPlugin from "@/common/prettier/plugins/groovy";
|
||||
import scalaPrettierPlugin from "@/common/prettier/plugins/scala";
|
||||
import clangPrettierPlugin from "@/common/prettier/plugins/clang";
|
||||
import pythonPrettierPlugin from "@/common/prettier/plugins/python";
|
||||
import dartPrettierPlugin from "@/common/prettier/plugins/dart";
|
||||
@@ -147,7 +144,7 @@ export const LANGUAGES: LanguageInfo[] = [
|
||||
plugins: [tomlPrettierPlugin]
|
||||
}),
|
||||
new LanguageInfo("go", "Go", StreamLanguage.define(go).parser, ["go"], {
|
||||
parser: "go-format",
|
||||
parser: "go",
|
||||
plugins: [goPrettierPlugin]
|
||||
}),
|
||||
new LanguageInfo("clj", "Clojure", StreamLanguage.define(clojure).parser, ["clj"], {
|
||||
@@ -175,18 +172,16 @@ export const LANGUAGES: LanguageInfo[] = [
|
||||
parser: "dart",
|
||||
plugins: [dartPrettierPlugin]
|
||||
}),
|
||||
new LanguageInfo("scala", "Scala", StreamLanguage.define(scala).parser, ["scala"], {
|
||||
parser: "scala",
|
||||
plugins: [scalaPrettierPlugin]
|
||||
}),
|
||||
new LanguageInfo("scala", "Scala", StreamLanguage.define(scala).parser, ["scala"]),
|
||||
new LanguageInfo("dockerfile", "Dockerfile", StreamLanguage.define(dockerFile).parser, ["dockerfile"], {
|
||||
parser: "dockerfile",
|
||||
plugins: [dockerfilePrettierPlugin]
|
||||
plugins: [shellPrettierPlugin]
|
||||
}),
|
||||
new LanguageInfo("lua", "Lua", StreamLanguage.define(lua).parser, ["lua"], {
|
||||
parser: "lua",
|
||||
plugins: [luaPrettierPlugin]
|
||||
}),
|
||||
new LanguageInfo("math", "Math", null, ["math"]),
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,14 +3,14 @@ import {LRParser} from "@lezer/lr"
|
||||
import {blockContent} from "./external-tokens.js"
|
||||
export const parser = LRParser.deserialize({
|
||||
version: 14,
|
||||
states: "!jQQOQOOOVOQO'#C`O#SOPO'#C_OOOO'#Cc'#CcQQOQOOOOOO'#Ca'#CaO#XOSO,58zOOOO,58y,58yOOOO-E6a-E6aOOOP1G.f1G.fO#aOSO1G.fOOOP7+$Q7+$Q",
|
||||
stateData: "#f~OXPO~OYTOZTO[TO]TO^TO_TO`TOaTObTOcTOdTOeTOfTOgTOhTOiTOjTOkTOlTOmTOnTOoTOpTOqTOrTOsTOtTOuTOvTO~OPVO~OUYOwXO~OwZO~O",
|
||||
states: "!jQQOQOOOVOQO'#C`O#]OPO'#C_OOOO'#Cc'#CcQQOQOOOOOO'#Ca'#CaO#bOSO,58zOOOO,58y,58yOOOO-E6a-E6aOOOP1G.f1G.fO#jOSO1G.fOOOP7+$Q7+$Q",
|
||||
stateData: "#o~OXPO~OYTOZTO[TO]TO^TO_TO`TOaTObTOcTOdTOeTOfTOgTOhTOiTOjTOkTOlTOmTOnTOoTOpTOqTOrTOsTOtTOuTOvTOwTOxTOyTO~OPVO~OUYOzXO~OzZO~O",
|
||||
goto: "jWPPPX]aPdTROSTQOSRUPQSORWS",
|
||||
nodeNames: "⚠ BlockContent Document Block BlockDelimiter BlockLanguage Auto",
|
||||
maxTerm: 39,
|
||||
maxTerm: 42,
|
||||
skippedNodes: [0],
|
||||
repeatNodeCount: 1,
|
||||
tokenData: ",s~R`YZ!T}!O!n#V#W!y#W#X#z#X#Y$c#Z#[$|#[#]%y#^#_&b#_#`'a#a#b'l#d#e'w#f#g(p#g#h)T#h#i*t#l#m+y#m#n,[R!YPwQ%&x%&y!]P!`P%&x%&y!cP!fP%&x%&y!iP!nOXP~!qP#T#U!t~!yOU~~!|R#`#a#V#d#e#b#g#h#m~#YP#^#_#]~#bOl~~#eP#d#e#h~#mOd~~#rPf~#g#h#u~#zOb~~#}P#T#U$Q~$TP#f#g$W~$ZP#h#i$^~$cOu~~$fQ#f#g$l#l#m$w~$oP#`#a$r~$wOn~~$|Om~~%PQ#c#d%V#f#g%[~%[Ok~~%_P#c#d%b~%eP#c#d%h~%kP#j#k%n~%qP#m#n%t~%yOs~~%|P#h#i&P~&SP#a#b&V~&YP#`#a&]~&bO]~~&eQ#T#U&k#g#h&|~&nP#j#k&q~&tP#T#U&w~&|O`~~'RPo~#c#d'U~'XP#b#c'[~'aOZ~~'dP#h#i'g~'lOr~~'oP#W#X'r~'wO_~~'zR#[#](T#g#h(`#m#n(k~(WP#d#e(Z~(`Oa~~(cP!R!S(f~(kOt~~(pO[~~(sQ#U#V(y#g#h)O~)OOg~~)TOe~~)WS#V#W)d#[#]){#e#f*Q#k#l*]~)gP#T#U)j~)mP#`#a)p~)sP#T#U)v~){Ov~~*QOh~~*TP#`#a*W~*]O^~~*`P#]#^*c~*fP#Y#Z*i~*lP#h#i*o~*tOq~~*wR#X#Y+Q#c#d+c#g#h+t~+TP#l#m+W~+ZP#h#i+^~+cOY~~+fP#a#b+i~+lP#`#a+o~+tOj~~+yOp~~+|P#a#b,P~,SP#`#a,V~,[Oc~~,_P#T#U,b~,eP#a#b,h~,kP#`#a,n~,sOi~",
|
||||
tokenData: ".w~RaYZ!W}!O!q#V#W!|#W#X#}#X#Y%p#Z#[&Z#[#]'W#^#_'o#_#`(n#`#a(y#a#b)[#d#e){#f#g*t#g#h+X#h#i,x#l#m-}#m#n.`R!]PzQ%&x%&y!`P!cP%&x%&y!fP!iP%&x%&y!lP!qOXP~!tP#T#U!w~!|OU~~#PR#`#a#Y#d#e#e#g#h#p~#]P#^#_#`~#eOl~~#hP#d#e#k~#pOd~~#uPf~#g#h#x~#}Ob~~$QQ#T#U$W#c#d$i~$ZP#f#g$^~$aP#h#i$d~$iOu~~$lP#V#W$o~$rP#_#`$u~$xP#X#Y${~%OP#f#g%R~%UP#Y#Z%X~%[P#]#^%_~%bP#`#a%e~%hP#X#Y%k~%pOx~~%sQ#f#g%y#l#m&U~%|P#`#a&P~&UOn~~&ZOm~~&^Q#c#d&d#f#g&i~&iOk~~&lP#c#d&o~&rP#c#d&u~&xP#j#k&{~'OP#m#n'R~'WOs~~'ZP#h#i'^~'aP#a#b'd~'gP#`#a'j~'oO]~~'rQ#T#U'x#g#h(Z~'{P#j#k(O~(RP#T#U(U~(ZO`~~(`Po~#c#d(c~(fP#b#c(i~(nOZ~~(qP#h#i(t~(yOr~~(|P#i#j)P~)SP#T#U)V~)[Oy~~)_Q#T#U)e#W#X)v~)hP#h#i)k~)nP#[#])q~)vOw~~){O_~~*OR#[#]*X#g#h*d#m#n*o~*[P#d#e*_~*dOa~~*gP!R!S*j~*oOt~~*tO[~~*wQ#U#V*}#g#h+S~+SOg~~+XOe~~+[S#V#W+h#[#],P#e#f,U#k#l,a~+kP#T#U+n~+qP#`#a+t~+wP#T#U+z~,POv~~,UOh~~,XP#`#a,[~,aO^~~,dP#]#^,g~,jP#Y#Z,m~,pP#h#i,s~,xOq~~,{R#X#Y-U#c#d-g#g#h-x~-XP#l#m-[~-_P#h#i-b~-gOY~~-jP#a#b-m~-pP#`#a-s~-xOj~~-}Op~~.QP#a#b.T~.WP#`#a.Z~.`Oc~~.cP#T#U.f~.iP#a#b.l~.oP#`#a.r~.wOi~",
|
||||
tokenizers: [blockContent, 0, 1],
|
||||
topRules: {"Document":[0,2]},
|
||||
tokenPrec: 0
|
||||
|
||||
165
frontend/src/views/editor/extensions/codeblock/mathBlock.ts
Normal file
165
frontend/src/views/editor/extensions/codeblock/mathBlock.ts
Normal file
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* 数学块扩展
|
||||
* 提供数学表达式计算功能,支持实时显示计算结果
|
||||
*/
|
||||
|
||||
import { ViewPlugin, Decoration, WidgetType } from "@codemirror/view";
|
||||
import { RangeSetBuilder } from "@codemirror/state";
|
||||
import { getNoteBlockFromPos } from "./state";
|
||||
// 声明全局math对象
|
||||
declare global {
|
||||
interface Window {
|
||||
math: any;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数学结果小部件
|
||||
*/
|
||||
class MathResult extends WidgetType {
|
||||
constructor(
|
||||
private displayResult: string,
|
||||
private copyResult: string
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
eq(other: MathResult): boolean {
|
||||
return other.displayResult === this.displayResult;
|
||||
}
|
||||
|
||||
toDOM(): HTMLElement {
|
||||
const wrap = document.createElement("span");
|
||||
wrap.className = "code-blocks-math-result";
|
||||
|
||||
const inner = document.createElement("span");
|
||||
inner.className = "inner";
|
||||
inner.innerHTML = this.displayResult;
|
||||
wrap.appendChild(inner);
|
||||
|
||||
inner.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
navigator.clipboard.writeText(this.copyResult);
|
||||
const copyElement = document.createElement("i");
|
||||
copyElement.className = "code-blocks-math-result-copied";
|
||||
copyElement.innerHTML = "Copied!";
|
||||
wrap.appendChild(copyElement);
|
||||
copyElement.offsetWidth; // trigger reflow so that the animation is shown
|
||||
copyElement.className = "code-blocks-math-result-copied fade-out";
|
||||
setTimeout(() => {
|
||||
copyElement.remove();
|
||||
}, 1700);
|
||||
});
|
||||
|
||||
return wrap;
|
||||
}
|
||||
|
||||
ignoreEvent(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数学装饰函数
|
||||
*/
|
||||
function mathDeco(view: any): any {
|
||||
let mathParsers = new WeakMap();
|
||||
let builder = new RangeSetBuilder();
|
||||
|
||||
for (let { from, to } of view.visibleRanges) {
|
||||
for (let pos = from; pos <= to;) {
|
||||
let line = view.state.doc.lineAt(pos);
|
||||
var block = getNoteBlockFromPos(view.state, pos);
|
||||
|
||||
if (block && block.language.name === "math") {
|
||||
// get math.js parser and cache it for this block
|
||||
let { parser, prev } = mathParsers.get(block) || {};
|
||||
if (!parser) {
|
||||
if (typeof window.math !== 'undefined') {
|
||||
parser = window.math.parser();
|
||||
mathParsers.set(block, { parser, prev });
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate math line
|
||||
let result: any;
|
||||
try {
|
||||
if (parser) {
|
||||
parser.set("prev", prev);
|
||||
result = parser.evaluate(line.text);
|
||||
if (result !== undefined) {
|
||||
mathParsers.set(block, { parser, prev: result });
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// suppress any errors
|
||||
}
|
||||
|
||||
// if we got a result from math.js, add the result decoration
|
||||
if (result !== undefined) {
|
||||
let format = parser?.get("format");
|
||||
|
||||
let resultWidget: MathResult | undefined;
|
||||
if (typeof(result) === "string") {
|
||||
resultWidget = new MathResult(result, result);
|
||||
} else if (format !== undefined && typeof(format) === "function") {
|
||||
try {
|
||||
resultWidget = new MathResult(format(result), format(result));
|
||||
} catch (e) {
|
||||
// suppress any errors
|
||||
}
|
||||
}
|
||||
|
||||
if (resultWidget === undefined && typeof window.math !== 'undefined') {
|
||||
resultWidget = new MathResult(
|
||||
window.math.format(result, {
|
||||
precision: 8,
|
||||
upperExp: 8,
|
||||
lowerExp: -6,
|
||||
}),
|
||||
window.math.format(result, {
|
||||
notation: "fixed",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (resultWidget) {
|
||||
builder.add(line.to, line.to, Decoration.widget({
|
||||
widget: resultWidget,
|
||||
side: 1,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
pos = line.to + 1;
|
||||
}
|
||||
}
|
||||
return builder.finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* 数学块视图插件
|
||||
*/
|
||||
export const mathBlock = ViewPlugin.fromClass(class {
|
||||
decorations: any;
|
||||
|
||||
constructor(view: any) {
|
||||
this.decorations = mathDeco(view);
|
||||
}
|
||||
|
||||
update(update: any) {
|
||||
// If the document changed, the viewport changed, update the decorations
|
||||
if (update.docChanged || update.viewportChanged) {
|
||||
this.decorations = mathDeco(update.view);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
decorations: v => v.decorations
|
||||
});
|
||||
|
||||
/**
|
||||
* 获取数学块扩展
|
||||
*/
|
||||
export function getMathBlockExtensions() {
|
||||
return [mathBlock];
|
||||
}
|
||||
@@ -56,6 +56,7 @@ export type SupportedLanguage =
|
||||
| 'scala'
|
||||
| 'dockerfile'
|
||||
| 'lua'
|
||||
| 'math'
|
||||
|
||||
/**
|
||||
* 创建块的选项
|
||||
|
||||
@@ -188,6 +188,32 @@ export function createDarkTheme(colors = defaultDarkColors) {
|
||||
background: colors.backgroundSecondary,
|
||||
borderTop: `1px solid ${colors.borderColor}`,
|
||||
},
|
||||
'.code-blocks-math-result': {
|
||||
paddingLeft: "12px",
|
||||
position: "relative",
|
||||
},
|
||||
".code-blocks-math-result .inner": {
|
||||
background: "#0e1217",
|
||||
color: "#a0e7c7",
|
||||
padding: '0px 4px',
|
||||
borderRadius: '2px',
|
||||
boxShadow: '0 0 3px rgba(0,0,0, 0.3)',
|
||||
cursor: 'pointer',
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
'.code-blocks-math-result-copied': {
|
||||
position: "absolute",
|
||||
top: "0px",
|
||||
left: "0px",
|
||||
marginLeft: "calc(100% + 10px)",
|
||||
width: "60px",
|
||||
transition: "opacity 500ms",
|
||||
transitionDelay: "1000ms",
|
||||
color: "rgba(220,240,230, 1.0)",
|
||||
},
|
||||
'.code-blocks-math-result-copied.fade-out': {
|
||||
opacity: 0,
|
||||
},
|
||||
|
||||
// 代码块开始标记
|
||||
'.code-block-start': {
|
||||
|
||||
@@ -1,243 +1,272 @@
|
||||
import { EditorView } from '@codemirror/view';
|
||||
import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
|
||||
import { tags } from '@lezer/highlight';
|
||||
import {EditorView} from '@codemirror/view';
|
||||
import {HighlightStyle, syntaxHighlighting} from '@codemirror/language';
|
||||
import {tags} from '@lezer/highlight';
|
||||
|
||||
// 默认浅色主题颜色
|
||||
export const defaultLightColors = {
|
||||
// 基础色调
|
||||
background: '#ffffff', // 主背景色
|
||||
backgroundSecondary: '#f1faf1', // 次要背景色
|
||||
surface: '#f5f5f5', // 面板背景
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#444d56', // 主文本色
|
||||
foregroundSecondary: '#6a737d', // 次要文本色
|
||||
comment: '#6a737d', // 注释色
|
||||
|
||||
// 语法高亮色
|
||||
keyword: '#d73a49', // 关键字
|
||||
string: '#032f62', // 字符串
|
||||
function: '#005cc5', // 函数名
|
||||
number: '#005cc5', // 数字
|
||||
operator: '#d73a49', // 操作符
|
||||
variable: '#24292e', // 变量
|
||||
type: '#6f42c1', // 类型
|
||||
|
||||
// 界面元素
|
||||
cursor: '#000000', // 光标
|
||||
selection: '#77baff', // 选中背景
|
||||
selectionBlur: '#b2c2ca', // 失焦选中背景
|
||||
activeLine: '#0000000a', // 当前行高亮
|
||||
lineNumber: '#00000040', // 行号
|
||||
activeLineNumber: '#000000aa', // 活动行号
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#dfdfdf', // 边框色
|
||||
borderLight: '#0000000c', // 浅色边框
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#005cc5', // 搜索匹配
|
||||
matchingBracket: '#00000019', // 匹配括号
|
||||
// 基础色调
|
||||
background: '#ffffff', // 主背景色
|
||||
backgroundSecondary: '#f1faf1', // 次要背景色
|
||||
surface: '#f5f5f5', // 面板背景
|
||||
|
||||
// 文本颜色
|
||||
foreground: '#444d56', // 主文本色
|
||||
foregroundSecondary: '#6a737d', // 次要文本色
|
||||
comment: '#6a737d', // 注释色
|
||||
|
||||
// 语法高亮色
|
||||
keyword: '#d73a49', // 关键字
|
||||
string: '#032f62', // 字符串
|
||||
function: '#005cc5', // 函数名
|
||||
number: '#005cc5', // 数字
|
||||
operator: '#d73a49', // 操作符
|
||||
variable: '#24292e', // 变量
|
||||
type: '#6f42c1', // 类型
|
||||
|
||||
// 界面元素
|
||||
cursor: '#000000', // 光标
|
||||
selection: '#77baff', // 选中背景
|
||||
selectionBlur: '#b2c2ca', // 失焦选中背景
|
||||
activeLine: '#0000000a', // 当前行高亮
|
||||
lineNumber: '#00000040', // 行号
|
||||
activeLineNumber: '#000000aa', // 活动行号
|
||||
|
||||
// 边框和分割线
|
||||
borderColor: '#dfdfdf', // 边框色
|
||||
borderLight: '#0000000c', // 浅色边框
|
||||
|
||||
// 搜索和匹配
|
||||
searchMatch: '#005cc5', // 搜索匹配
|
||||
matchingBracket: '#00000019', // 匹配括号
|
||||
};
|
||||
|
||||
// 创建浅色主题
|
||||
export function createLightTheme(colors = defaultLightColors) {
|
||||
const lightTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: colors.foreground,
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
|
||||
// 确保编辑器容器背景一致
|
||||
'.cm-editor': {
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
|
||||
// 确保滚动区域背景一致
|
||||
'.cm-scroller': {
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
|
||||
// 编辑器内容
|
||||
'.cm-content': {
|
||||
caretColor: colors.cursor,
|
||||
paddingTop: '4px',
|
||||
},
|
||||
|
||||
// 光标
|
||||
'.cm-cursor, .cm-dropCursor': {
|
||||
borderLeftColor: colors.cursor,
|
||||
borderLeftWidth: '2px',
|
||||
paddingTop: '4px',
|
||||
marginTop: '-2px',
|
||||
},
|
||||
|
||||
// 选择
|
||||
'.cm-selectionBackground': {
|
||||
backgroundColor: colors.selectionBlur,
|
||||
},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground': {
|
||||
backgroundColor: colors.selection,
|
||||
},
|
||||
'.cm-activeLine.code-empty-block-selected': {
|
||||
backgroundColor: colors.selection,
|
||||
},
|
||||
|
||||
// 当前行高亮
|
||||
'.cm-activeLine': {
|
||||
backgroundColor: colors.activeLine
|
||||
},
|
||||
|
||||
// 行号区域
|
||||
'.cm-gutters': {
|
||||
backgroundColor: 'rgba(0,0,0, 0.04)',
|
||||
color: colors.lineNumber,
|
||||
border: 'none',
|
||||
borderRight: `1px solid ${colors.borderLight}`,
|
||||
padding: '0 2px 0 4px',
|
||||
userSelect: 'none',
|
||||
},
|
||||
'.cm-activeLineGutter': {
|
||||
backgroundColor: 'transparent',
|
||||
color: colors.activeLineNumber,
|
||||
},
|
||||
|
||||
// 折叠功能
|
||||
'.cm-foldGutter': {
|
||||
marginLeft: '0px',
|
||||
},
|
||||
'.cm-foldGutter .cm-gutterElement': {
|
||||
opacity: 0,
|
||||
transition: 'opacity 400ms',
|
||||
},
|
||||
'.cm-gutters:hover .cm-gutterElement': {
|
||||
opacity: 1,
|
||||
},
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: colors.comment,
|
||||
},
|
||||
const lightTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: colors.foreground,
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
|
||||
|
||||
// 搜索匹配
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: 'transparent',
|
||||
outline: `1px solid ${colors.searchMatch}`,
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: colors.searchMatch,
|
||||
color: colors.background,
|
||||
},
|
||||
'.cm-selectionMatch': {
|
||||
backgroundColor: '#e6f3ff',
|
||||
},
|
||||
|
||||
// 括号匹配
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
outline: `0.5px solid ${colors.searchMatch}`,
|
||||
},
|
||||
'&.cm-focused .cm-matchingBracket': {
|
||||
backgroundColor: colors.matchingBracket,
|
||||
color: 'inherit',
|
||||
},
|
||||
'&.cm-focused .cm-nonmatchingBracket': {
|
||||
outline: '0.5px solid #d73a49',
|
||||
},
|
||||
|
||||
// 编辑器焦点
|
||||
'&.cm-editor.cm-focused': {
|
||||
outline: 'none',
|
||||
},
|
||||
|
||||
// 工具提示
|
||||
'.cm-tooltip': {
|
||||
border: 'none',
|
||||
backgroundColor: colors.surface,
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent',
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: colors.surface,
|
||||
borderBottomColor: colors.surface,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
backgroundColor: colors.activeLine,
|
||||
color: colors.foreground,
|
||||
},
|
||||
},
|
||||
|
||||
// 代码块层
|
||||
'.code-blocks-layer': {
|
||||
width: '100%',
|
||||
},
|
||||
'.code-blocks-layer .block-even, .code-blocks-layer .block-odd': {
|
||||
width: '100%',
|
||||
boxSizing: 'content-box',
|
||||
},
|
||||
'.code-blocks-layer .block-even': {
|
||||
background: colors.background,
|
||||
borderTop: `1px solid ${colors.borderColor}`,
|
||||
},
|
||||
'.code-blocks-layer .block-even:first-child': {
|
||||
borderTop: 'none',
|
||||
},
|
||||
'.code-blocks-layer .block-odd': {
|
||||
background: colors.backgroundSecondary,
|
||||
borderTop: `1px solid ${colors.borderColor}`,
|
||||
},
|
||||
|
||||
// 代码块开始标记
|
||||
'.code-block-start': {
|
||||
height: '12px',
|
||||
},
|
||||
'.code-block-start.first': {
|
||||
height: '0px',
|
||||
},
|
||||
}, { dark: false });
|
||||
// 确保编辑器容器背景一致
|
||||
'.cm-editor': {
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
|
||||
// 语法高亮样式
|
||||
const lightHighlightStyle = HighlightStyle.define([
|
||||
{ tag: tags.keyword, color: colors.keyword },
|
||||
{ tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName], color: colors.variable },
|
||||
{ tag: [tags.variableName], color: colors.variable },
|
||||
{ tag: [tags.function(tags.variableName)], color: colors.function },
|
||||
{ tag: [tags.labelName], color: colors.operator },
|
||||
{ tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], color: colors.keyword },
|
||||
{ tag: [tags.definition(tags.name), tags.separator], color: colors.function },
|
||||
{ tag: [tags.brace], color: colors.variable },
|
||||
{ tag: [tags.annotation], color: '#d73a49' },
|
||||
{ tag: [tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace], color: colors.number },
|
||||
{ tag: [tags.typeName, tags.className], color: colors.type },
|
||||
{ tag: [tags.operator, tags.operatorKeyword], color: colors.operator },
|
||||
{ tag: [tags.tagName], color: colors.type },
|
||||
{ tag: [tags.squareBracket], color: colors.keyword },
|
||||
{ tag: [tags.angleBracket], color: colors.operator },
|
||||
{ tag: [tags.attributeName], color: colors.variable },
|
||||
{ tag: [tags.regexp], color: colors.string },
|
||||
{ tag: [tags.quote], color: colors.comment },
|
||||
{ tag: [tags.string], color: colors.string },
|
||||
{ tag: tags.link, color: colors.function, textDecoration: 'underline' },
|
||||
{ tag: [tags.url, tags.escape, tags.special(tags.string)], color: colors.string },
|
||||
{ tag: [tags.meta], color: colors.comment },
|
||||
{ tag: [tags.comment], color: colors.comment, fontStyle: 'italic' },
|
||||
{ tag: tags.strong, fontWeight: 'bold' },
|
||||
{ tag: tags.emphasis, fontStyle: 'italic' },
|
||||
{ tag: tags.strikethrough, textDecoration: 'line-through' },
|
||||
{ tag: tags.heading, fontWeight: 'bold', color: colors.keyword },
|
||||
{ tag: [tags.heading1, tags.heading2], fontSize: '1.4em' },
|
||||
{ tag: [tags.heading3, tags.heading4], fontSize: '1.2em' },
|
||||
{ tag: [tags.heading5, tags.heading6], fontSize: '1.1em' },
|
||||
]);
|
||||
// 确保滚动区域背景一致
|
||||
'.cm-scroller': {
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
|
||||
return [
|
||||
lightTheme,
|
||||
syntaxHighlighting(lightHighlightStyle),
|
||||
];
|
||||
// 编辑器内容
|
||||
'.cm-content': {
|
||||
caretColor: colors.cursor,
|
||||
paddingTop: '4px',
|
||||
},
|
||||
|
||||
// 光标
|
||||
'.cm-cursor, .cm-dropCursor': {
|
||||
borderLeftColor: colors.cursor,
|
||||
borderLeftWidth: '2px',
|
||||
paddingTop: '4px',
|
||||
marginTop: '-2px',
|
||||
},
|
||||
|
||||
// 选择
|
||||
'.cm-selectionBackground': {
|
||||
backgroundColor: colors.selectionBlur,
|
||||
},
|
||||
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground': {
|
||||
backgroundColor: colors.selection,
|
||||
},
|
||||
'.cm-activeLine.code-empty-block-selected': {
|
||||
backgroundColor: colors.selection,
|
||||
},
|
||||
|
||||
// 当前行高亮
|
||||
'.cm-activeLine': {
|
||||
backgroundColor: colors.activeLine
|
||||
},
|
||||
|
||||
// 行号区域
|
||||
'.cm-gutters': {
|
||||
backgroundColor: 'rgba(0,0,0, 0.04)',
|
||||
color: colors.lineNumber,
|
||||
border: 'none',
|
||||
borderRight: `1px solid ${colors.borderLight}`,
|
||||
padding: '0 2px 0 4px',
|
||||
userSelect: 'none',
|
||||
},
|
||||
'.cm-activeLineGutter': {
|
||||
backgroundColor: 'transparent',
|
||||
color: colors.activeLineNumber,
|
||||
},
|
||||
|
||||
// 折叠功能
|
||||
'.cm-foldGutter': {
|
||||
marginLeft: '0px',
|
||||
},
|
||||
'.cm-foldGutter .cm-gutterElement': {
|
||||
opacity: 0,
|
||||
transition: 'opacity 400ms',
|
||||
},
|
||||
'.cm-gutters:hover .cm-gutterElement': {
|
||||
opacity: 1,
|
||||
},
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'transparent',
|
||||
border: 'none',
|
||||
color: colors.comment,
|
||||
},
|
||||
|
||||
|
||||
// 搜索匹配
|
||||
'.cm-searchMatch': {
|
||||
backgroundColor: 'transparent',
|
||||
outline: `1px solid ${colors.searchMatch}`,
|
||||
},
|
||||
'.cm-searchMatch.cm-searchMatch-selected': {
|
||||
backgroundColor: colors.searchMatch,
|
||||
color: colors.background,
|
||||
},
|
||||
'.cm-selectionMatch': {
|
||||
backgroundColor: '#e6f3ff',
|
||||
},
|
||||
|
||||
// 括号匹配
|
||||
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
|
||||
outline: `0.5px solid ${colors.searchMatch}`,
|
||||
},
|
||||
'&.cm-focused .cm-matchingBracket': {
|
||||
backgroundColor: colors.matchingBracket,
|
||||
color: 'inherit',
|
||||
},
|
||||
'&.cm-focused .cm-nonmatchingBracket': {
|
||||
outline: '0.5px solid #d73a49',
|
||||
},
|
||||
|
||||
// 编辑器焦点
|
||||
'&.cm-editor.cm-focused': {
|
||||
outline: 'none',
|
||||
},
|
||||
|
||||
// 工具提示
|
||||
'.cm-tooltip': {
|
||||
border: 'none',
|
||||
backgroundColor: colors.surface,
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:before': {
|
||||
borderTopColor: 'transparent',
|
||||
borderBottomColor: 'transparent',
|
||||
},
|
||||
'.cm-tooltip .cm-tooltip-arrow:after': {
|
||||
borderTopColor: colors.surface,
|
||||
borderBottomColor: colors.surface,
|
||||
},
|
||||
'.cm-tooltip-autocomplete': {
|
||||
'& > ul > li[aria-selected]': {
|
||||
backgroundColor: colors.activeLine,
|
||||
color: colors.foreground,
|
||||
},
|
||||
},
|
||||
|
||||
// 代码块层
|
||||
'.code-blocks-layer': {
|
||||
width: '100%',
|
||||
},
|
||||
'.code-blocks-layer .block-even, .code-blocks-layer .block-odd': {
|
||||
width: '100%',
|
||||
boxSizing: 'content-box',
|
||||
},
|
||||
'.code-blocks-layer .block-even': {
|
||||
background: colors.background,
|
||||
borderTop: `1px solid ${colors.borderColor}`,
|
||||
},
|
||||
'.code-blocks-layer .block-even:first-child': {
|
||||
borderTop: 'none',
|
||||
},
|
||||
'.code-blocks-layer .block-odd': {
|
||||
background: colors.backgroundSecondary,
|
||||
borderTop: `1px solid ${colors.borderColor}`,
|
||||
},
|
||||
'.code-blocks-math-result': {
|
||||
paddingLeft: "12px",
|
||||
position: "relative",
|
||||
},
|
||||
'.code-blocks-math-result .inner': {
|
||||
background: '#48b57e',
|
||||
color: '#fff',
|
||||
padding: '0px 4px',
|
||||
borderRadius: '2px',
|
||||
boxShadow: '0 0 3px rgba(0,0,0, 0.1)',
|
||||
cursor: 'pointer',
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
'.code-blocks-math-result-copied': {
|
||||
position: "absolute",
|
||||
top: "0px",
|
||||
left: "0px",
|
||||
marginLeft: "calc(100% + 10px)",
|
||||
width: "60px",
|
||||
transition: "opacity 500ms",
|
||||
transitionDelay: "1000ms",
|
||||
color: "rgba(0,0,0, 0.8)",
|
||||
},
|
||||
'.code-blocks-math-result-copied.fade-out': {
|
||||
opacity: 0,
|
||||
},
|
||||
|
||||
// 代码块开始标记
|
||||
'.code-block-start': {
|
||||
height: '12px',
|
||||
},
|
||||
'.code-block-start.first': {
|
||||
height: '0px',
|
||||
},
|
||||
}, {dark: false});
|
||||
|
||||
// 语法高亮样式
|
||||
const lightHighlightStyle = HighlightStyle.define([
|
||||
{tag: tags.keyword, color: colors.keyword},
|
||||
{tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName], color: colors.variable},
|
||||
{tag: [tags.variableName], color: colors.variable},
|
||||
{tag: [tags.function(tags.variableName)], color: colors.function},
|
||||
{tag: [tags.labelName], color: colors.operator},
|
||||
{tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], color: colors.keyword},
|
||||
{tag: [tags.definition(tags.name), tags.separator], color: colors.function},
|
||||
{tag: [tags.brace], color: colors.variable},
|
||||
{tag: [tags.annotation], color: '#d73a49'},
|
||||
{
|
||||
tag: [tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace],
|
||||
color: colors.number
|
||||
},
|
||||
{tag: [tags.typeName, tags.className], color: colors.type},
|
||||
{tag: [tags.operator, tags.operatorKeyword], color: colors.operator},
|
||||
{tag: [tags.tagName], color: colors.type},
|
||||
{tag: [tags.squareBracket], color: colors.keyword},
|
||||
{tag: [tags.angleBracket], color: colors.operator},
|
||||
{tag: [tags.attributeName], color: colors.variable},
|
||||
{tag: [tags.regexp], color: colors.string},
|
||||
{tag: [tags.quote], color: colors.comment},
|
||||
{tag: [tags.string], color: colors.string},
|
||||
{tag: tags.link, color: colors.function, textDecoration: 'underline'},
|
||||
{tag: [tags.url, tags.escape, tags.special(tags.string)], color: colors.string},
|
||||
{tag: [tags.meta], color: colors.comment},
|
||||
{tag: [tags.comment], color: colors.comment, fontStyle: 'italic'},
|
||||
{tag: tags.strong, fontWeight: 'bold'},
|
||||
{tag: tags.emphasis, fontStyle: 'italic'},
|
||||
{tag: tags.strikethrough, textDecoration: 'line-through'},
|
||||
{tag: tags.heading, fontWeight: 'bold', color: colors.keyword},
|
||||
{tag: [tags.heading1, tags.heading2], fontSize: '1.4em'},
|
||||
{tag: [tags.heading3, tags.heading4], fontSize: '1.2em'},
|
||||
{tag: [tags.heading5, tags.heading6], fontSize: '1.1em'},
|
||||
]);
|
||||
|
||||
return [
|
||||
lightTheme,
|
||||
syntaxHighlighting(lightHighlightStyle),
|
||||
];
|
||||
}
|
||||
|
||||
// 默认浅色主题
|
||||
|
||||
Reference in New Issue
Block a user