原子编辑器
Obsidian 风格的现场预览 代码 6在反应.
标记下的一个编辑器,其中格式化会像您输入的那样使标题,粗体, 表格、图像、任务列表 —— 而下面的文本则保持平面标记. 您读取的文档是您编辑的文档: 不分割预览并复制 / 保存 / 圆通 行为完全像一个满是标记的纯文本区域 。 一个 可选读取模式锁定,但不会引入 单独的预览文档.
后面是书写面 原子个人知识 base ——取出以独立站立,并用真实用户文档加固.
特征
- 现场预览. 标题、重点、,
==highlights==,链接,图像, 和表格导出内行;原始语法只出现在行中 光标是打开的,然后在继续前进时把自己盖起来. - 原始马克德是真理的来源. 每个装饰都是唯景,所以 复制、 保存和通过其他标记下工具的回转为字节 与纯文本区域相同.
- 虚拟化和布局稳定. CM6 仅制作取景口和行 点击它们时永不回流——打开500页的文档并滚动 保持平稳,甚至在iOS上.
- (原始内容存档于2019-10-12). WYSIWYG tables. 单击单元格以编辑位置; 宽表格滚动 水平地在装有包装的包装内,而不是拉长页面.
- 维基链接.
[[target]]编号 :[[target|label]]与同步解析, 自动完成,并点击开通——用于知识库式交叉连接. - 聪明的列表. 输入收紧的子弹和任务复选框, 打开
空项缩进,以及
- [ ]成为真实的、可点击的复选框. - 语法高亮代码 对于20+语言,每个语法懒惰地加载 第一次栅栏使用它 所以没有使用的语言 从来没有击中线.
- 带有 CSS 变量的主题 ——默认为黑暗,光通过单光
data-theme="light"属性,每个颜色压倒一切. - 最小查找面板 (Ctrl/Cmd+F)风格相匹配编辑器.
安装
npm install @atomic-editor/editor \
@codemirror/state @codemirror/view @codemirror/commands \
@codemirror/autocomplete @codemirror/language @codemirror/search \
@codemirror/lang-markdown \
@lezer/common @lezer/highlight @lezer/markdown \
react react-dom
代码Mirror 和 React 软件包被宣布为 同行依赖关系
而不是常规的道具。 你把它们安装在编辑器旁边
您的捆绑者解决了单一共享副本—— 2份
@codemirror/state 一捆就能无声地打破编辑的
州域身份检查.
栅栏编码语言语法(@codemirror/lang-javascript, (中文(简体) ),
@codemirror/lang-python(等等)为: 选项同伴 - 只安装
那些你想强调。 见
语法突出显示 见下文.
使用
import { AtomicCodeMirrorEditor } from '@atomic-editor/editor';
import '@atomic-editor/editor/styles.css';
function App() {
return (
<AtomicCodeMirrorEditor
markdownSource={'# Hello\n\nA paragraph.'}
onMarkdownChange={(md) => console.log(md)}
onLinkClick={(url) => window.open(url, '_blank', 'noopener,noreferrer')}
/>
);
}
编辑器填充其母——用高放的弹性或网格包裹它 集装箱.
紧急握把
如果您需要从外部驱动编辑器, 请通过一个裁判—— 例如电线 工具栏按钮,或从全局打开搜索面板 密钥绑定 :
import { useRef } from 'react';
import {
AtomicCodeMirrorEditor,
type AtomicCodeMirrorEditorHandle,
} from '@atomic-editor/editor';
function App() {
const editor = useRef<AtomicCodeMirrorEditorHandle | null>(null);
return (
<>
<button onClick={() => editor.current?.openSearch()}>Search</button>
<AtomicCodeMirrorEditor
markdownSource={'…'}
editorHandleRef={editor}
/>
</>
);
}
方法: focus, (中文(简体) ), undo, (中文(简体) ), redo, (中文(简体) ), openSearch(query?), (中文(简体) ), closeSearch, (中文(简体) ),
revealText(query), (中文(简体) ), isSearchOpen, (中文(简体) ), getMarkdown, (中文(简体) ), getContentDOM, (中文(简体) ),
setReadOnly(readOnly)。 。 。 .
只读( 正在读取) 模式
过 readOnly 使文档成为读取表面,例如
Obsidian的阅读视图:
<AtomicCodeMirrorEditor markdownSource={'…'} readOnly />
在只读模式下, 整个文档会继续提供—— 源代码从不 显示在护栏下——打字/粘贴/表格编辑被禁用, 并点击链接( 任何位置, 不只是线索图标) 打开 而不是放在护身符上 任务复选框保持可切换并 查找文档仍然有效.
readOnly 由代码密钥支持 Compartment,所以翻转它
重新配置现场视图——滚动位置和搜索状态
保存, 不重挂。 从道具上驱动,或绝对通过
editorHandle.setReadOnly(true) 在 React 外切换工具栏
使循环。 对于消费者来说,一个自定义编辑器,基础
readOnlyFacet 财务报告和审定财务报表 readOnlyExtension 也输出.
来自搜索结果
两个道具将用户放在挂载上的相关段落附近:
initialSearchText打开预填入的搜索面板 查询。 完全导航表面——通过匹配的箭头键, 差点被开除 当用户明确引用时, 效果良好 .initialRevealText使用 a 3.2 第一场比赛的淡出亮点——没有面板,没有光标 移动。 "我点击了搜索结果 带我去段落" 它来自".
两个都接受 string | null。显示匹配者倒下
逐渐——精确地,白空相撞,个别行,然后
截断前缀( 140和80个字符) —— 所以点击仍然解决
查询来自一个不匹配 LLM 磁盘片段
源字节换字节. 对于后挂载显示,呼叫
editorHandle.revealText(query) 通过必须的手柄.
淡出亮度使用 CSS 变量
--atomic-editor-initial-reveal-bg 财务报告和审定财务报表
--atomic-editor-initial-reveal-bg-strong; 取消主题
与主搜索匹配无关的峰值和已安放的颜色
调色板.
语法突出显示
栅栏码块默认为平地单空. 启用
突出显示,通过一个 codeLanguages 阵列. @codemirror/lang-markdown
动态导入每个语法 当一个栅栏第一次使用它,所以
大列表不会浮出水面.
备选案文1:使用编订的清单(~20种语言)
# Install the lang-* peers you want highlighted.
npm install \
@codemirror/lang-javascript @codemirror/lang-python \
@codemirror/lang-rust @codemirror/lang-go @codemirror/lang-html \
@codemirror/lang-css @codemirror/lang-json @codemirror/lang-yaml \
@codemirror/legacy-modes # ruby/swift/shell/toml/dockerfile
import { AtomicCodeMirrorEditor } from '@atomic-editor/editor';
import { ATOMIC_CODE_LANGUAGES } from '@atomic-editor/editor/code-languages';
<AtomicCodeMirrorEditor
markdownSource={'…'}
codeLanguages={ATOMIC_CODE_LANGUAGES}
/>
见 src/code-languages.ts 全文
列表( JavaScript, TypeScript, Python, Go, Rust, Ruby, Java, C, C++, ) 中文本无需修改 ,
PHP,斯威夫特,壳牌,SQL,HTML,CSS,XML,JSON,YAML,TOML,多克文件,
马克倒地).
备选案文2:自带
import { LanguageDescription } from '@codemirror/language';
import { python } from '@codemirror/lang-python';
const codeLanguages = [
LanguageDescription.of({
name: 'Python',
alias: ['py'],
extensions: ['py'],
load: () => Promise.resolve(python()),
}),
];
<AtomicCodeMirrorEditor markdownSource={'…'} codeLanguages={codeLanguages} />
维基链接
[[target]] 财务报告和审定财务报表 [[target|label]] 链接——原子和斜面方式
交叉链接注释——以船舶为可堆放扩展. 它使标签链接,
同步解决赤色目标(以显示真正的标题和
解析/ 缺少状态),单击时打开链接,并按
您一键入 [[数字 :
import { AtomicCodeMirrorEditor, wikiLinks } from '@atomic-editor/editor';
<AtomicCodeMirrorEditor
markdownSource={'See [[atom-42|the design doc]] for details.'}
extensions={[
wikiLinks({
suggest: async (query) => store.search(query), // autocomplete source
resolve: async (target) => store.resolve(target), // label + status for bare links
onOpen: (target) => router.open(target), // click / Cmd-click to navigate
}),
]}
/>;
草稿链接在光标在其中时仍可编辑;解析为
出而缓取. 见 src/wiki-links.ts 联 合 国
完全配置——自定义序列化,解析器政策,建议限制,以及
页:1 WikiLinkSuggestion 编号 : WikiLinkResolvedTarget 类型.
他们
每种颜色、字体和大小都来自 CSS 自定义属性 内入倒地. 征服编辑的祖先.
货包船a 光变体 随时激活
data-theme="light" 设定在祖先上,包括 <html> 或者说
<body>。黑暗默认值保持不变;光块只是
重映射相同的变量.
<html data-theme="light">…</html>
| 变量 | 黑暗默认值( 自动打开) [data-theme="light"](中文(简体) ) |
|---|---|
--atomic-editor-font | 系统 sans |
--atomic-editor-font-mono | 系统单 |
--atomic-editor-body-size | 1.0625rem |
--atomic-editor-body-leading | 1.7 |
--atomic-editor-measure | 70ch |
--atomic-editor-fg | #dcddde |
--atomic-editor-fg-muted | #888 |
--atomic-editor-fg-faint | #666 |
--atomic-editor-bg | #1e1e1e |
--atomic-editor-bg-panel | #252525 |
--atomic-editor-bg-surface | #2d2d2d |
--atomic-editor-border | #3d3d3d |
--atomic-editor-accent | #7c3aed |
--atomic-editor-accent-bright | #a78bfa |
--atomic-editor-accent-soft | 铁道/ 显示锡 |
--atomic-editor-link | #818cf8 |
--atomic-editor-link-hover | #a5b4fc |
--atomic-editor-code-bg | 微妙的暗面板 |
--atomic-editor-selection-bg | 重音调为28% |
--atomic-editor-search-bg | 重音调为28% |
--atomic-editor-search-bg-active | 重音调为60% |
| 代码 (Palenight) (法语) | |
--atomic-editor-hl-keyword | #c792ea |
--atomic-editor-hl-string | #c3e88d |
--atomic-editor-hl-number | #f78c6c |
--atomic-editor-hl-comment | #6a7a82 |
--atomic-editor-hl-type | #ffcb6b |
--atomic-editor-hl-function | #82aaff |
--atomic-editor-hl-property | #82aaff |
--atomic-editor-hl-regexp | #f07178 |
--atomic-editor-hl-escape | #89ddff |
--atomic-editor-hl-tag | #f07178 |
--atomic-editor-hl-variable | #eeffff |
--atomic-editor-hl-operator | #89ddff |
--atomic-editor-hl-invalid | #ff5370 |
以插件扩展
CodeMiror 6基于扩展,这个包也一样. 传出任何
通过 extensions 道克到层入
自动完整源、 自定义装饰、 指定域的密钥图、,
合作(yjs),vim模式,或者其他任何东西. (本节)
维基链接 上面的扩展就是用这个钩子建造的。 )
import { autocompletion, type CompletionContext } from '@codemirror/autocomplete';
const hashtags = autocompletion({
override: [(ctx: CompletionContext) => {
const match = ctx.matchBefore(/#\w*$/);
if (!match) return null;
return {
from: match.from + 1,
options: myTagStore.list().map((tag) => ({ label: tag })),
};
}],
});
<AtomicCodeMirrorEditor
markdownSource={'…'}
extensions={[hashtags]}
/>
消费者的扩展在内置后附加, 所以包裹一个自定义
键盘映射在 Prec.high (从) @codemirror/state如果它需要击败
默认绑定。 阵列在山上被捕获——通过一个马厩
引用,除非您想要重载.
低级组成
如果反相包装器的扩展集 意见太强,每个片段 单独导出, 这样您就可以组装一个完全自定义的编辑器 :
import {
inlinePreview, // live preview decorations
imageBlocks, // rendered image widgets
tables, // WYSIWYG table widget
wikiLinks, // [[...]] links
atomicEditorTheme,
atomicMarkdownSyntax,
extendEmphasisPair,
} from '@atomic-editor/editor';
你可以建立一个编辑器,包括 inlinePreview() + 键 tables()
跳过 atomicEditorTheme 为了你自己 EditorView.theme({...}), (中文(简体) ),
或互换 atomicMarkdownSyntax 对于自定义
syntaxHighlighting(HighlightStyle.define([...]))。此时此刻
你在反应包装器外 和平地CM6领地.
设计说明
见 文件/建筑图 完全设计 理由说明。 短版本 :
- 原始马克德是真理的来源. 所有装饰都是 仅查看 – 复制、 保存和回转到任何下标分解器 和你期望的一样.
- 没有布局变化. 每一行的高度都稳定 光标位置 。 内置装饰在不活动时隐藏语法符号 行不改变行高.
- 窄无效 . 装饰只重建其触摸线 内容( 或周围触发字符) 已更改, 因此编辑 a 在50KB doc中,段落成本为O(改变大小),而不是O(doc).
- 老鼠冻护. 点击不会触发重建装饰 中相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相.
- iOS意识. 移动- 滚动停止( 图像重挂 Jank, 高地图) 漂流,锚地冲突)被追踪并被固定;演示的 样本大小的采取者双倍地作为检测任何 回归.
捐款
发展需要节点20.19+,22.12+,或24+. 出版编辑 自己继续支持Node.js 18和较新的.
git clone https://github.com/kenforthewin/atomic-editor
cd atomic-editor
npm install
npm run dev # demo dev server at http://localhost:5173
npm test # vitest unit tests
npm run build # tsc emit to dist/
npm run test:e2e # legacy probes + deterministic browser suites
npm run test:package # pack and build a clean consumer app
浏览器把广泛的遗产探测器套件 和焦距, 孤立的 Playwright 测试规格 。 铬运行完整的矩阵; Firefox 和 WebKit运行兼容性烟雾测试. 见 文件/测试 对于层,命令,和规则 将错误修复变成持久的回归测试.
因为编辑们把船开进去了 原子, (中文(简体) ), 真实的用户文档是其de-facto模糊体——奇数输入(多行) 链接标题、超省 RSS 导入、宽表) 先把这里修好 问题和公关欢迎.
许可证
麻省理工学院. 见 自由主义。 。 。 .