cm-live-markdown 0.0.0-stage → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +213 -2
- package/dist/commands.d.ts +19 -0
- package/dist/commands.js +324 -0
- package/dist/commands.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/live.d.ts +69 -0
- package/dist/live.js +550 -0
- package/dist/live.js.map +1 -0
- package/dist/react.d.ts +37 -0
- package/dist/react.js +109 -0
- package/dist/react.js.map +1 -0
- package/dist/theme.d.ts +14 -0
- package/dist/theme.js +113 -0
- package/dist/theme.js.map +1 -0
- package/package.json +85 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jason
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,214 @@
|
|
|
1
|
-
#
|
|
1
|
+
# cm-live-markdown
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Живой Markdown для [CodeMirror 6](https://codemirror.net) — как Live Preview в Obsidian. Текст остаётся обычным Markdown, оформление рисуется поверх, а служебные символы видны только там, где стоит курсор. Без фокуса весь текст показан оформлённым, как в просмотре.
|
|
4
|
+
|
|
5
|
+
- Заголовки, **жирный**, _курсив_, `код`, ~~зачёркнутое~~, ссылки (Ctrl/Cmd+клик — открыть), цитаты, блоки кода, горизонтальная линия.
|
|
6
|
+
- Списки: маркеры «•», «• •» по уровню вложенности и нумерация «3.1.»; чекбоксы `- [ ]` кликаются.
|
|
7
|
+
- Таблицы вне курсора отрисованы, клик по ячейке раскрывает исходник на нужной строке.
|
|
8
|
+
- Картинки `` — свой преобразователь адреса, вставка и перетаскивание файлов.
|
|
9
|
+
- Свои строчные токены: упоминания, теги, ссылки на сущности — регулярка и функция отрисовки значка.
|
|
10
|
+
- Сочетания: Tab / Shift+Tab (вложенность пунктов, ячейки таблиц), Backspace за маркером снимает его целиком, Enter продолжает список, Ctrl/Cmd+B / I / E / K, Ctrl/Cmd+Shift+X, Ctrl/Cmd+Enter — чекбокс.
|
|
11
|
+
- Оформление — CSS-переменные, без привязки к дизайну сайта.
|
|
12
|
+
|
|
13
|
+
Ядро — набор расширений CodeMirror без React; к нему тонкая обёртка для React (`cm-live-markdown/react`).
|
|
14
|
+
|
|
15
|
+
## Установка
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm i cm-live-markdown @codemirror/state @codemirror/view @codemirror/language @codemirror/lang-markdown @codemirror/commands @lezer/common
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Пакеты `@codemirror/*` — peer-зависимости: используется та же копия, что у вас в проекте. React (≥ 18) нужен только для `cm-live-markdown/react`. Пакет только ESM.
|
|
22
|
+
|
|
23
|
+
## Без React
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { EditorView, keymap } from '@codemirror/view';
|
|
27
|
+
import { EditorState } from '@codemirror/state';
|
|
28
|
+
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
|
|
29
|
+
import { liveMarkdown } from 'cm-live-markdown';
|
|
30
|
+
|
|
31
|
+
new EditorView({
|
|
32
|
+
parent: document.querySelector('#editor')!,
|
|
33
|
+
state: EditorState.create({
|
|
34
|
+
doc: '# Привет\n\n- [ ] дело',
|
|
35
|
+
extensions: [history(), keymap.of([...defaultKeymap, ...historyKeymap]), EditorView.lineWrapping, liveMarkdown()],
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`liveMarkdown()` подключает язык Markdown (GFM), отрисовку, таблицы, сочетания и тему. Историю правок, базовые сочетания и перенос строк добавьте сами — как в примере.
|
|
41
|
+
|
|
42
|
+
## React
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { useState } from 'react';
|
|
46
|
+
import { LiveMarkdown } from 'cm-live-markdown/react';
|
|
47
|
+
|
|
48
|
+
function Note() {
|
|
49
|
+
const [text, setText] = useState('');
|
|
50
|
+
return <LiveMarkdown value={text} onChange={setText} placeholder="Пишите…" lang="ru" />;
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
| свойство | что |
|
|
55
|
+
| ------------------------------------------------------------ | ---------------------------------------------------------------- |
|
|
56
|
+
| `value`, `onChange` | текст; правки снаружи применяются кусочком, курсор не сбивается |
|
|
57
|
+
| `onSelect(range)` | выделение `[from, to]` |
|
|
58
|
+
| `onBlur` | редактор потерял фокус |
|
|
59
|
+
| `placeholder`, `autoFocus`, `maxLength`, `lang`, `className` | как у поля ввода |
|
|
60
|
+
| `onImages(files, pos)` | вставили или бросили картинки; нет обработчика — обычная вставка |
|
|
61
|
+
| `onMediaChange(srcs)` | набор адресов картинок в тексте изменился (и при открытии) |
|
|
62
|
+
| `options` | настройки `liveMarkdown()` (ниже); читаются при создании |
|
|
63
|
+
| `extensions` | ещё расширения CodeMirror |
|
|
64
|
+
|
|
65
|
+
`ref` даёт `focus()`, `select(from, to?)` и `view` — сам `EditorView`.
|
|
66
|
+
|
|
67
|
+
Обёртка — `<div class="lmd">`, редактор внутри занимает всю её высоту. Чтобы поле прокручивалось, задайте высоту: `.lmd { height: 100%; }` в контейнере с высотой.
|
|
68
|
+
|
|
69
|
+
## Настройки
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
liveMarkdown({
|
|
73
|
+
tokens: [mention], // свои строчные токены
|
|
74
|
+
images: { resolve, pending, onFiles, accept, onChange }, // или false — картинки исходником
|
|
75
|
+
tables: { render }, // или false — таблицы текстом
|
|
76
|
+
phrases: {
|
|
77
|
+
imageLoading: 'Загрузка картинки…',
|
|
78
|
+
imageNotFound: 'Картинка не найдена',
|
|
79
|
+
tableHint: 'Нажмите, чтобы править таблицу',
|
|
80
|
+
},
|
|
81
|
+
language: true, // false — подключите свой markdown()
|
|
82
|
+
keymap: true, // false — без сочетаний
|
|
83
|
+
theme: true, // false — только ваш CSS
|
|
84
|
+
openLink: (url) => window.open(url, '_blank', 'noreferrer'),
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Свои токены
|
|
89
|
+
|
|
90
|
+
Всё, что совпало с регуляркой, вне курсора заменяется значком; под курсором видно исходник (класс `lmd-token-src`). Внутри кода токены не трогаются.
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
import { liveMarkdown, refreshLivePreview, type InlineToken } from 'cm-live-markdown';
|
|
94
|
+
|
|
95
|
+
const users = new Map<string, string>();
|
|
96
|
+
|
|
97
|
+
const mention: InlineToken = {
|
|
98
|
+
pattern: /@\[([a-z0-9]+)\]/g,
|
|
99
|
+
render: (m) => {
|
|
100
|
+
const chip = document.createElement('span');
|
|
101
|
+
chip.className = 'mention';
|
|
102
|
+
chip.textContent = users.get(m[1]) ?? m[1];
|
|
103
|
+
return chip;
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Справочник догрузился — перерисовать значки
|
|
108
|
+
loadUsers().then((list) => {
|
|
109
|
+
list.forEach((u) => users.set(u.id, u.name));
|
|
110
|
+
view.dispatch({ effects: refreshLivePreview.of(null) });
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Картинки
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
liveMarkdown({
|
|
118
|
+
images: {
|
|
119
|
+
// file:<id> → адрес для <img>; может вернуть Promise. Ошибка — подпись «не найдена»
|
|
120
|
+
resolve: (src) => (src.startsWith('file:') ? store.objectUrl(src.slice(5)) : src),
|
|
121
|
+
// Пока файл грузится, в тексте стоит  — показать подпись
|
|
122
|
+
pending: (src) => src.startsWith('uploading:'),
|
|
123
|
+
// Вставили или бросили файлы
|
|
124
|
+
onFiles: (files, pos, view) => {
|
|
125
|
+
upload(files).then((ids) =>
|
|
126
|
+
view.dispatch({ changes: { from: pos, insert: ids.map((id) => ``).join('\n') } }),
|
|
127
|
+
);
|
|
128
|
+
},
|
|
129
|
+
// Список адресов картинок в тексте — например, чтобы удалить файлы, которых больше нет
|
|
130
|
+
onChange: (srcs) => attachments.sync(srcs),
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Таблицы
|
|
136
|
+
|
|
137
|
+
По умолчанию таблица рисуется простой встроенной `<table class="lmd-table-view">` с текстом ячеек. Чтобы ячейки были оформлены так же, как в вашем просмотре, отдайте свой рендерер; он может вернуть функцию уборки:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { createRoot } from 'react-dom/client';
|
|
141
|
+
|
|
142
|
+
liveMarkdown({
|
|
143
|
+
tables: {
|
|
144
|
+
render(source, dom) {
|
|
145
|
+
const root = createRoot(dom);
|
|
146
|
+
root.render(<Markdown source={source} />);
|
|
147
|
+
return () => queueMicrotask(() => root.unmount()); // не посреди отрисовки React
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Таблица внутри списка или цитаты остаётся текстом.
|
|
154
|
+
|
|
155
|
+
## Оформление
|
|
156
|
+
|
|
157
|
+
Встроенная тема настраивается CSS-переменными на редакторе или любом предке:
|
|
158
|
+
|
|
159
|
+
| переменная | что | по умолчанию |
|
|
160
|
+
| ---------------------------------------------------- | ---------------------------------------- | ----------------------------------------- |
|
|
161
|
+
| `--lmd-bg`, `--lmd-text` | фон и текст | прозрачный, наследуется |
|
|
162
|
+
| `--lmd-muted` | маркеры списков, цитаты, исходник токена | серый |
|
|
163
|
+
| `--lmd-faint` | зачёркнутое, выполненное, подсказка | светло-серый |
|
|
164
|
+
| `--lmd-font`, `--lmd-font-size`, `--lmd-line-height` | шрифт текста | наследуется, 1.6 |
|
|
165
|
+
| `--lmd-mono` | шрифт кода и таблиц-исходников | системный моноширинный |
|
|
166
|
+
| `--lmd-padding` | поля | `14px 16px` |
|
|
167
|
+
| `--lmd-code-bg` | фон кода | полупрозрачный серый |
|
|
168
|
+
| `--lmd-link` | ссылки | синий |
|
|
169
|
+
| `--lmd-accent` | цвет флажков | системный |
|
|
170
|
+
| `--lmd-quote-border`, `--lmd-rule` | черта цитаты, линии и рамки таблиц | полупрозрачный серый |
|
|
171
|
+
| `--lmd-selection` | выделение | своё для светлой и тёмной темы CodeMirror |
|
|
172
|
+
|
|
173
|
+
```css
|
|
174
|
+
.lmd {
|
|
175
|
+
--lmd-text: var(--text);
|
|
176
|
+
--lmd-link: var(--brand);
|
|
177
|
+
--lmd-font-size: 14px;
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Классы для своего CSS: `lmd-h1`…`lmd-h6`, `lmd-strong`, `lmd-em`, `lmd-strike`, `lmd-code`, `lmd-link`, `lmd-codeblock`, `lmd-quote`, `lmd-hr`, `lmd-table`, `lmd-bullet`, `lmd-check`, `lmd-done`, `lmd-img-box`, `lmd-img`, `lmd-img-note`, `lmd-table-widget`, `lmd-token-src`.
|
|
182
|
+
|
|
183
|
+
## Команды отдельно
|
|
184
|
+
|
|
185
|
+
Команды — обычные `StateCommand` CodeMirror, их можно повесить на свои клавиши или кнопки:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
import { keymap } from '@codemirror/view';
|
|
189
|
+
import { liveMarkdown, wrap, toggleTask, shiftLists } from 'cm-live-markdown';
|
|
190
|
+
|
|
191
|
+
const extensions = [
|
|
192
|
+
liveMarkdown({ keymap: false }),
|
|
193
|
+
keymap.of([
|
|
194
|
+
{ key: 'Mod-b', run: wrap('**') },
|
|
195
|
+
{ key: 'Alt-x', run: toggleTask },
|
|
196
|
+
{ key: 'Tab', run: shiftLists(1), shift: shiftLists(-1) },
|
|
197
|
+
]),
|
|
198
|
+
];
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
`wrap(mark)`, `insertLink`, `toggleTask`, `shiftLists(dir)`, `tableCell(dir)`, `deleteListMarker`, весь набор — `liveMarkdownKeymap`. Также есть `cm-live-markdown/commands` — только команды, без отрисовки.
|
|
202
|
+
|
|
203
|
+
## Разработка
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
npm i
|
|
207
|
+
npm test # проверки команд на состояниях CodeMirror, без браузера
|
|
208
|
+
npm run demo # демо-страница (Vite)
|
|
209
|
+
npm run build # dist + типы
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Лицензия
|
|
213
|
+
|
|
214
|
+
MIT
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type StateCommand } from '@codemirror/state';
|
|
2
|
+
import type { KeyBinding } from '@codemirror/view';
|
|
3
|
+
/** Tab / Shift+Tab: сдвинуть пункты списка под курсором; не пункты — обычный отступ */
|
|
4
|
+
export declare function shiftLists(dir: 1 | -1): StateCommand;
|
|
5
|
+
/** Обернуть выделение меткой (`**`, `*`, `` ` ``, `~~`) или снять её, если выделение уже обёрнуто */
|
|
6
|
+
export declare function wrap(mark: string): StateCommand;
|
|
7
|
+
/** Ctrl+K: [выделение](url) — курсор на адрес */
|
|
8
|
+
export declare const insertLink: StateCommand;
|
|
9
|
+
/** Ctrl+Enter: переключить чекбокс; пункт без чекбокса или обычная строка — сделать чекбоксом */
|
|
10
|
+
export declare const toggleTask: StateCommand;
|
|
11
|
+
/** Tab / Shift+Tab в строке таблицы: к соседней ячейке */
|
|
12
|
+
export declare function tableCell(dir: 1 | -1): StateCommand;
|
|
13
|
+
/**
|
|
14
|
+
* Backspace сразу за маркером пункта (и чекбоксом) — снять разметку целиком, как в Obsidian.
|
|
15
|
+
* Стандартная команда превращает маркер в пробелы, и строка прилипает к пункту выше.
|
|
16
|
+
*/
|
|
17
|
+
export declare const deleteListMarker: StateCommand;
|
|
18
|
+
/** Сочетания живого Markdown. Ставить с Prec.high — раньше стандартных Tab и Backspace */
|
|
19
|
+
export declare const liveMarkdownKeymap: readonly KeyBinding[];
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { indentLess, indentMore } from '@codemirror/commands';
|
|
2
|
+
import { EditorSelection } from '@codemirror/state';
|
|
3
|
+
/**
|
|
4
|
+
* Команды «живого» Markdown: вложенность списков и сочетания оформления.
|
|
5
|
+
* Все команды — StateCommand: работают и с EditorView, и с голым `{ state, dispatch }` (проверки на node).
|
|
6
|
+
*/
|
|
7
|
+
// ------------------------------------------------------------------ списки: Tab / Shift+Tab
|
|
8
|
+
/** Пункт списка: отступ, маркер (`-`, `*`, `+`, `1.`, `1)`), пробелы после него */
|
|
9
|
+
const LIST_LINE = /^(\s*)([-*+]|(\d+)([.)]))(\s+)/;
|
|
10
|
+
function parseList(text) {
|
|
11
|
+
const m = LIST_LINE.exec(text);
|
|
12
|
+
if (!m)
|
|
13
|
+
return null;
|
|
14
|
+
return {
|
|
15
|
+
indent: m[1].length,
|
|
16
|
+
marker: m[2],
|
|
17
|
+
num: m[3] ? Number(m[3]) : undefined,
|
|
18
|
+
delim: m[4],
|
|
19
|
+
content: m[0].length,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const indentOf = (text) => /^\s*/.exec(text)[0].length;
|
|
23
|
+
/**
|
|
24
|
+
* Сдвиг пункта списка на строке `lineNo` (вместе с его вложенными строками).
|
|
25
|
+
* dir = 1 — вложить под предыдущий пункт того же уровня, -1 — поднять на уровень родителя.
|
|
26
|
+
* null — строка не пункт списка; [] — пункт, но сдвигать некуда.
|
|
27
|
+
* Shift+Tab на верхнем уровне снимает разметку списка.
|
|
28
|
+
*/
|
|
29
|
+
function shiftItem(state, lineNo, dir) {
|
|
30
|
+
const doc = state.doc;
|
|
31
|
+
const line = doc.line(lineNo);
|
|
32
|
+
const item = parseList(line.text);
|
|
33
|
+
if (!item)
|
|
34
|
+
return null;
|
|
35
|
+
let target = -1;
|
|
36
|
+
let number;
|
|
37
|
+
if (dir === 1) {
|
|
38
|
+
// Ближайший пункт выше с отступом не больше нашего: того же уровня — вкладываемся под него
|
|
39
|
+
for (let n = lineNo - 1; n >= 1; n--) {
|
|
40
|
+
const text = doc.line(n).text;
|
|
41
|
+
if (!text.trim())
|
|
42
|
+
continue;
|
|
43
|
+
const prev = parseList(text);
|
|
44
|
+
if (!prev) {
|
|
45
|
+
if (indentOf(text) > item.indent)
|
|
46
|
+
continue; // продолжение текста вложенного пункта
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
if (prev.indent > item.indent)
|
|
50
|
+
continue;
|
|
51
|
+
if (prev.indent === item.indent)
|
|
52
|
+
target = prev.content;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
if (target < 0)
|
|
56
|
+
return [];
|
|
57
|
+
// Нумерованный пункт в новом подсписке: продолжаем номер соседа на новом уровне или начинаем с 1
|
|
58
|
+
if (item.num !== undefined) {
|
|
59
|
+
number = 1;
|
|
60
|
+
for (let n = lineNo - 1; n >= 1; n--) {
|
|
61
|
+
const prev = parseList(doc.line(n).text);
|
|
62
|
+
if (!prev || prev.indent < target)
|
|
63
|
+
break;
|
|
64
|
+
if (prev.indent === target && prev.num !== undefined) {
|
|
65
|
+
number = prev.num + 1;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// Пункт верхнего уровня: Shift+Tab снимает разметку списка (и чекбокс) — строка становится обычным текстом
|
|
73
|
+
if (item.indent === 0) {
|
|
74
|
+
const task = /^\[[ xX]\]\s+/.exec(line.text.slice(item.content));
|
|
75
|
+
return [{ from: line.from, to: line.from + item.content + (task ? task[0].length : 0) }];
|
|
76
|
+
}
|
|
77
|
+
target = 0;
|
|
78
|
+
for (let n = lineNo - 1; n >= 1; n--) {
|
|
79
|
+
const parent = parseList(doc.line(n).text);
|
|
80
|
+
if (parent && parent.indent < item.indent) {
|
|
81
|
+
target = parent.indent;
|
|
82
|
+
if (item.num !== undefined && parent.num !== undefined)
|
|
83
|
+
number = parent.num + 1;
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const delta = target - item.indent;
|
|
89
|
+
const changes = [];
|
|
90
|
+
const reindent = (n) => {
|
|
91
|
+
const l = doc.line(n);
|
|
92
|
+
const cur = indentOf(l.text);
|
|
93
|
+
const next = Math.max(0, cur + delta);
|
|
94
|
+
changes.push({ from: l.from, to: l.from + cur, insert: ' '.repeat(next) });
|
|
95
|
+
};
|
|
96
|
+
reindent(lineNo);
|
|
97
|
+
if (number !== undefined) {
|
|
98
|
+
const from = line.from + item.indent;
|
|
99
|
+
changes.push({ from, to: from + item.marker.length, insert: `${number}${item.delim}` });
|
|
100
|
+
}
|
|
101
|
+
// Вложенные строки пункта (отступ больше нашего) едут вместе с ним
|
|
102
|
+
for (let n = lineNo + 1; n <= doc.lines; n++) {
|
|
103
|
+
const text = doc.line(n).text;
|
|
104
|
+
if (!text.trim()) {
|
|
105
|
+
const next = n < doc.lines ? doc.line(n + 1).text : '';
|
|
106
|
+
if (indentOf(next) > item.indent && next.trim())
|
|
107
|
+
continue;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
if (indentOf(text) <= item.indent) {
|
|
111
|
+
// Поднятый пункт забирает следующих соседей себе в дети — нумерованный подсписок начинаем с 1
|
|
112
|
+
const next = parseList(text);
|
|
113
|
+
if (dir === -1 && next?.num !== undefined && next.indent === item.indent) {
|
|
114
|
+
const l = doc.line(n);
|
|
115
|
+
changes.push({
|
|
116
|
+
from: l.from + next.indent,
|
|
117
|
+
to: l.from + next.indent + next.marker.length,
|
|
118
|
+
insert: `1${next.delim}`,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
reindent(n);
|
|
124
|
+
}
|
|
125
|
+
return changes;
|
|
126
|
+
}
|
|
127
|
+
/** Tab / Shift+Tab: сдвинуть пункты списка под курсором; не пункты — обычный отступ */
|
|
128
|
+
export function shiftLists(dir) {
|
|
129
|
+
return (target) => {
|
|
130
|
+
const { state } = target;
|
|
131
|
+
const lines = new Set();
|
|
132
|
+
for (const r of state.selection.ranges) {
|
|
133
|
+
const a = state.doc.lineAt(r.from).number;
|
|
134
|
+
const b = state.doc.lineAt(r.to).number;
|
|
135
|
+
for (let n = a; n <= b; n++)
|
|
136
|
+
lines.add(n);
|
|
137
|
+
}
|
|
138
|
+
// Не пункты — обычный отступ
|
|
139
|
+
const results = [...lines].map((n) => shiftItem(state, n, dir));
|
|
140
|
+
if (results.every((r) => r === null))
|
|
141
|
+
return dir === 1 ? indentMore(target) : indentLess(target);
|
|
142
|
+
// При выделении нескольких пунктов вложенные строки сдвигаются со своим пунктом — повторно не трогаем
|
|
143
|
+
const seen = new Set();
|
|
144
|
+
const changes = [];
|
|
145
|
+
for (const r of results)
|
|
146
|
+
for (const c of r ?? []) {
|
|
147
|
+
const { from, to } = c;
|
|
148
|
+
if (seen.has(`${from}:${to}`))
|
|
149
|
+
continue;
|
|
150
|
+
seen.add(`${from}:${to}`);
|
|
151
|
+
changes.push(c);
|
|
152
|
+
}
|
|
153
|
+
if (changes.length)
|
|
154
|
+
target.dispatch(state.update({ changes, userEvent: 'input.indent', scrollIntoView: true }));
|
|
155
|
+
return true;
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
// ------------------------------------------------------------------ оформление: Ctrl+B / I / E / Shift+X, ссылка, чекбокс
|
|
159
|
+
/** Сколько символов `ch` подряд идёт от позиции pos (dir 1 — вправо, -1 — влево), не больше 3 */
|
|
160
|
+
function run(text, ch, from, dir) {
|
|
161
|
+
let n = 0;
|
|
162
|
+
for (let i = dir === 1 ? from : from - 1; n < 3 && i >= 0 && i < text.length && text[i] === ch; i += dir)
|
|
163
|
+
n++;
|
|
164
|
+
return n;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Метка уже стоит, если по краям столько символов: для `*` и `**` считаем серию звёздочек,
|
|
168
|
+
* чтобы курсив и жирный не путались (`***x***` — оба, `**x**` — только жирный).
|
|
169
|
+
*/
|
|
170
|
+
function isOn(mark, n) {
|
|
171
|
+
if (mark === '*')
|
|
172
|
+
return n % 2 === 1;
|
|
173
|
+
if (mark === '**')
|
|
174
|
+
return n >= 2;
|
|
175
|
+
return n >= mark.length;
|
|
176
|
+
}
|
|
177
|
+
/** Обернуть выделение меткой (`**`, `*`, `` ` ``, `~~`) или снять её, если выделение уже обёрнуто */
|
|
178
|
+
export function wrap(mark) {
|
|
179
|
+
return ({ state, dispatch }) => {
|
|
180
|
+
const len = mark.length;
|
|
181
|
+
const ch = mark[0];
|
|
182
|
+
const doc = state.doc.toString();
|
|
183
|
+
const tr = state.changeByRange((r) => {
|
|
184
|
+
const outer = Math.min(run(doc, ch, r.from, -1), run(doc, ch, r.to, 1));
|
|
185
|
+
if (isOn(mark, outer))
|
|
186
|
+
return {
|
|
187
|
+
changes: [
|
|
188
|
+
{ from: r.from - len, to: r.from },
|
|
189
|
+
{ from: r.to, to: r.to + len },
|
|
190
|
+
],
|
|
191
|
+
range: EditorSelection.range(r.from - len, r.to - len),
|
|
192
|
+
};
|
|
193
|
+
const inner = state.sliceDoc(r.from, r.to);
|
|
194
|
+
const innerRun = Math.min(run(inner, ch, 0, 1), run(inner, ch, inner.length, -1));
|
|
195
|
+
if (inner.length >= 2 * len && isOn(mark, innerRun))
|
|
196
|
+
return {
|
|
197
|
+
changes: { from: r.from, to: r.to, insert: inner.slice(len, -len) },
|
|
198
|
+
range: EditorSelection.range(r.from, r.to - 2 * len),
|
|
199
|
+
};
|
|
200
|
+
return {
|
|
201
|
+
changes: [
|
|
202
|
+
{ from: r.from, insert: mark },
|
|
203
|
+
{ from: r.to, insert: mark },
|
|
204
|
+
],
|
|
205
|
+
range: EditorSelection.range(r.from + len, r.to + len),
|
|
206
|
+
};
|
|
207
|
+
});
|
|
208
|
+
dispatch(state.update(tr, { userEvent: 'input.format', scrollIntoView: true }));
|
|
209
|
+
return true;
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
/** Ctrl+K: [выделение](url) — курсор на адрес */
|
|
213
|
+
export const insertLink = ({ state, dispatch }) => {
|
|
214
|
+
const tr = state.changeByRange((r) => {
|
|
215
|
+
const text = state.sliceDoc(r.from, r.to);
|
|
216
|
+
const isUrl = /^https?:\/\/\S+$/.test(text);
|
|
217
|
+
const insert = isUrl ? `[](${text})` : `[${text}](https://)`;
|
|
218
|
+
const cursor = isUrl ? r.from + 1 : r.from + text.length + 3;
|
|
219
|
+
return {
|
|
220
|
+
changes: { from: r.from, to: r.to, insert },
|
|
221
|
+
range: isUrl ? EditorSelection.cursor(cursor) : EditorSelection.range(cursor, cursor + 'https://'.length),
|
|
222
|
+
};
|
|
223
|
+
});
|
|
224
|
+
dispatch(state.update(tr, { userEvent: 'input.format', scrollIntoView: true }));
|
|
225
|
+
return true;
|
|
226
|
+
};
|
|
227
|
+
const TASK = /^(\s*(?:[-*+]|\d+[.)])\s+)\[([ xX])\]/;
|
|
228
|
+
/** Ctrl+Enter: переключить чекбокс; пункт без чекбокса или обычная строка — сделать чекбоксом */
|
|
229
|
+
export const toggleTask = ({ state, dispatch }) => {
|
|
230
|
+
const lines = new Set();
|
|
231
|
+
for (const r of state.selection.ranges)
|
|
232
|
+
for (let n = state.doc.lineAt(r.from).number; n <= state.doc.lineAt(r.to).number; n++)
|
|
233
|
+
lines.add(n);
|
|
234
|
+
const changes = [];
|
|
235
|
+
for (const n of lines) {
|
|
236
|
+
const line = state.doc.line(n);
|
|
237
|
+
const task = TASK.exec(line.text);
|
|
238
|
+
if (task) {
|
|
239
|
+
const pos = line.from + task[1].length + 1;
|
|
240
|
+
changes.push({ from: pos, to: pos + 1, insert: task[2] === ' ' ? 'x' : ' ' });
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
const item = parseList(line.text);
|
|
244
|
+
if (item)
|
|
245
|
+
changes.push({ from: line.from + item.content, insert: '[ ] ' });
|
|
246
|
+
else {
|
|
247
|
+
const indent = indentOf(line.text);
|
|
248
|
+
changes.push({ from: line.from + indent, insert: '- [ ] ' });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
dispatch(state.update({ changes, userEvent: 'input.format' }));
|
|
252
|
+
return true;
|
|
253
|
+
};
|
|
254
|
+
// ------------------------------------------------------------------ таблицы: Tab / Shift+Tab — к соседней ячейке
|
|
255
|
+
/** Tab / Shift+Tab в строке таблицы: к соседней ячейке */
|
|
256
|
+
export function tableCell(dir) {
|
|
257
|
+
return ({ state, dispatch }) => {
|
|
258
|
+
const head = state.selection.main.head;
|
|
259
|
+
const line = state.doc.lineAt(head);
|
|
260
|
+
if (!line.text.trimStart().startsWith('|'))
|
|
261
|
+
return false;
|
|
262
|
+
// Начала ячеек: позиции сразу после каждого «|», кроме последнего
|
|
263
|
+
const starts = [];
|
|
264
|
+
for (let i = 0; i < line.text.length; i++)
|
|
265
|
+
if (line.text[i] === '|' && i < line.text.trimEnd().length - 1)
|
|
266
|
+
starts.push(i + 1);
|
|
267
|
+
const col = head - line.from;
|
|
268
|
+
let target;
|
|
269
|
+
if (dir === 1)
|
|
270
|
+
target = starts.find((p) => p > col);
|
|
271
|
+
else {
|
|
272
|
+
// Начало текущей ячейки, затем предыдущая; в первой ячейке — остаёмся
|
|
273
|
+
const cur = [...starts].reverse().find((p) => p <= col) ?? starts[0];
|
|
274
|
+
target = [...starts].reverse().find((p) => p < cur) ?? cur;
|
|
275
|
+
}
|
|
276
|
+
if (target === undefined) {
|
|
277
|
+
// За последней ячейкой — в первую ячейку следующей строки таблицы (через разделитель | --- |)
|
|
278
|
+
let n = line.number + 1;
|
|
279
|
+
while (n <= state.doc.lines && /^\s*\|[\s:|-]+\|\s*$/.test(state.doc.line(n).text))
|
|
280
|
+
n++;
|
|
281
|
+
if (n > state.doc.lines || !state.doc.line(n).text.trimStart().startsWith('|'))
|
|
282
|
+
return true;
|
|
283
|
+
const next = state.doc.line(n);
|
|
284
|
+
target = next.text.indexOf('|') + 1 + (next.from - line.from);
|
|
285
|
+
}
|
|
286
|
+
const pos = line.from + target;
|
|
287
|
+
// Курсор после пробела в начале ячейки
|
|
288
|
+
const skip = state.sliceDoc(pos, pos + 1) === ' ' ? 1 : 0;
|
|
289
|
+
dispatch(state.update({ selection: { anchor: pos + skip }, scrollIntoView: true }));
|
|
290
|
+
return true;
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Backspace сразу за маркером пункта (и чекбоксом) — снять разметку целиком, как в Obsidian.
|
|
295
|
+
* Стандартная команда превращает маркер в пробелы, и строка прилипает к пункту выше.
|
|
296
|
+
*/
|
|
297
|
+
export const deleteListMarker = ({ state, dispatch }) => {
|
|
298
|
+
const r = state.selection.main;
|
|
299
|
+
if (!r.empty || state.selection.ranges.length > 1)
|
|
300
|
+
return false;
|
|
301
|
+
const line = state.doc.lineAt(r.head);
|
|
302
|
+
const item = parseList(line.text);
|
|
303
|
+
if (!item)
|
|
304
|
+
return false;
|
|
305
|
+
const task = /^\[[ xX]\]\s+/.exec(line.text.slice(item.content));
|
|
306
|
+
const end = line.from + item.content + (task ? task[0].length : 0);
|
|
307
|
+
if (r.head !== end)
|
|
308
|
+
return false;
|
|
309
|
+
dispatch(state.update({ changes: { from: line.from, to: end }, userEvent: 'delete.backward', scrollIntoView: true }));
|
|
310
|
+
return true;
|
|
311
|
+
};
|
|
312
|
+
/** Сочетания живого Markdown. Ставить с Prec.high — раньше стандартных Tab и Backspace */
|
|
313
|
+
export const liveMarkdownKeymap = [
|
|
314
|
+
{ key: 'Backspace', run: deleteListMarker },
|
|
315
|
+
{ key: 'Tab', run: tableCell(1), shift: tableCell(-1) },
|
|
316
|
+
{ key: 'Tab', run: shiftLists(1), shift: shiftLists(-1) },
|
|
317
|
+
{ key: 'Mod-b', run: wrap('**') },
|
|
318
|
+
{ key: 'Mod-i', run: wrap('*') },
|
|
319
|
+
{ key: 'Mod-e', run: wrap('`') },
|
|
320
|
+
{ key: 'Mod-Shift-x', run: wrap('~~') },
|
|
321
|
+
{ key: 'Mod-k', run: insertLink },
|
|
322
|
+
{ key: 'Mod-Enter', run: toggleTask },
|
|
323
|
+
];
|
|
324
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { defaultPhrases, imageSources, liveMarkdown, refreshLivePreview, type ImageOptions, type InlineToken, type LiveMarkdownOptions, type Phrases, type TableOptions, } from './live.ts';
|
|
2
|
+
export { deleteListMarker, insertLink, liveMarkdownKeymap, shiftLists, tableCell, toggleTask, wrap, } from './commands.ts';
|
|
3
|
+
export { liveMarkdownTheme } from './theme.ts';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { defaultPhrases, imageSources, liveMarkdown, refreshLivePreview, } from "./live.js";
|
|
2
|
+
export { deleteListMarker, insertLink, liveMarkdownKeymap, shiftLists, tableCell, toggleTask, wrap, } from "./commands.js";
|
|
3
|
+
export { liveMarkdownTheme } from "./theme.js";
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,kBAAkB,GAMnB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,UAAU,EACV,SAAS,EACT,UAAU,EACV,IAAI,GACL,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
|