文件
mynode/packages/editor/CodeMirror/configFromSettings.ts
chen 301194963b
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
feat: Initial clean release of CHM
2026-11-04 11:29:39 +08:00

144 行
5.8 KiB
TypeScript

import { EditorView, keymap } from '@codemirror/view';
import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
import { EditorKeymap, EditorLanguageType, EditorSettings } from '../types';
import createTheme from './theme';
import { EditorState, Prec, StateField } from '@codemirror/state';
import { deleteMarkupBackward, markdown, markdownLanguage } from '@codemirror/lang-markdown';
import { GFM as GitHubFlavoredMarkdownExtension } from '@lezer/markdown';
import markdownMathExtension from './extensions/markdownMathExtension';
import markdownHighlightExtension, { markdownInsertExtension } from './extensions/markdownHighlightExtension';
import markdownFrontMatterExtension from './extensions/markdownFrontMatterExtension';
import lookUpLanguage from './utils/markdown/codeBlockLanguages/lookUpLanguage';
import { html } from '@codemirror/lang-html';
import { defaultKeymap, emacsStyleKeymap } from '@codemirror/commands';
import { vim } from '@replit/codemirror-vim';
import { indentUnit } from '@codemirror/language';
import insertNewlineContinueMarkup from './editorCommands/insertNewlineContinueMarkup';
import renderingExtension from './extensions/rendering/renderingExtension';
import renderTables from './extensions/rendering/renderTables';
import { RenderedContentContext } from './extensions/rendering/types';
import highlightActiveLineExtension from './extensions/highlightActiveLineExtension';
import renderBlockImages from './extensions/rendering/renderBlockImages';
import renderBlockMedia from './extensions/rendering/renderBlockMedia';
import quickTimestampExtension from './extensions/quickTimestampExtension';
import wikiLinkAutocompleteExtension from './extensions/wikiLinkAutocompleteExtension';
const closingFencedBlock = StateField.define<boolean>({
create: () => false,
update: (_, tr) => {
const pos = tr.state.selection.main.from;
const textBefore = tr.state.doc.sliceString(Math.max(0, pos - 2), pos);
const backticksBefore = textBefore.length - textBefore.replace(/`+$/, '').length;
return backticksBefore >= 2;
},
});
const configFromSettings = (settings: EditorSettings, context: RenderedContentContext) => {
const languageExtension = (() => {
const openingBrackets = '`([{\'"‘“(《「『【〔〖〘〚'.split('');
const language = settings.language;
if (language === EditorLanguageType.Markdown) {
return [
markdown({
extensions: [
GitHubFlavoredMarkdownExtension,
// FrontMatter support (YAML blocks at start of document)
markdownFrontMatterExtension,
settings.markdownMarkEnabled ? markdownHighlightExtension : [],
settings.markdownInsertEnabled ? markdownInsertExtension : [],
// Don't highlight KaTeX if the user disabled it
settings.katexEnabled ? markdownMathExtension : [],
],
codeLanguages: lookUpLanguage,
...(settings.autocompleteMarkup ? {
// Most Markup completion is enabled by default
addKeymap: false, // However, we have our own keymap
} : {
addKeymap: false,
completeHTMLTags: false,
htmlTagLanguage: html({ matchClosingTags: false, autoCloseTags: false }),
}),
}),
markdownLanguage.data.compute([closingFencedBlock], state => {
// Don't auto-complete `s when closing a code block.
// See https://github.com/laurent22/joplin/issues/12569.
if (state.field(closingFencedBlock)) {
return { closeBrackets: { brackets: openingBrackets.filter(b => b !== '`') } };
}
return { closeBrackets: { brackets: openingBrackets } };
}),
keymap.of(settings.autocompleteMarkup ? [
{ key: 'Enter', run: insertNewlineContinueMarkup },
{ key: 'Backspace', run: deleteMarkupBackward },
] : []),
];
} else if (language === EditorLanguageType.Html) {
return html({ autoCloseTags: settings.autocompleteMarkup });
} else {
const exhaustivenessCheck: never = language;
return exhaustivenessCheck;
}
})();
const extensions = [
languageExtension,
closingFencedBlock,
createTheme(settings.themeData),
EditorView.contentAttributes.of({
autocapitalize: 'sentence',
autocorrect: settings.spellcheckEnabled ? 'true' : 'false',
spellcheck: settings.spellcheckEnabled ? 'true' : 'false',
'aria-label': settings.editorLabel,
}),
EditorState.readOnly.of(settings.readOnly),
indentUnit.of(settings.indentWithTabs ? '\t' : ' '),
];
if (settings.automatchBraces) {
extensions.push(closeBrackets());
extensions.push(keymap.of(closeBracketsKeymap));
}
if (settings.keymap === EditorKeymap.Vim) {
extensions.push(Prec.high(vim()));
} else if (settings.keymap === EditorKeymap.Emacs) {
extensions.push(keymap.of(emacsStyleKeymap));
}
if (!settings.ignoreModifiers) {
extensions.push(Prec.low(keymap.of(defaultKeymap)));
}
// Only enable in-editor rendering for Markdown notes. In-editor rendering can result in
// confusing output in HTML notes (e.g. some, but not most, tags hidden).
if (settings.inlineRenderingEnabled && settings.language === EditorLanguageType.Markdown) {
extensions.push(renderingExtension(context, settings.tableEditingEnabled));
} else if (settings.tableEditingEnabled && settings.language === EditorLanguageType.Markdown) {
// Table editing can work independently of inline rendering so users
// who disable inline rendering can still use the interactive widget.
extensions.push(renderTables(context));
}
if (settings.imageRenderingEnabled) {
extensions.push(renderBlockImages(context));
extensions.push(renderBlockMedia(context));
}
if (settings.highlightActiveLine) {
extensions.push(highlightActiveLineExtension());
}
if (settings.language === EditorLanguageType.Markdown) {
extensions.push(quickTimestampExtension());
extensions.push(wikiLinkAutocompleteExtension(context));
}
return extensions;
};
export default configFromSettings;