@gravity-ui/markdown-editor 13.19.0 → 13.21.0
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/build/cjs/extensions/markdown/CodeBlock/commands.d.ts +4 -0
- package/build/cjs/extensions/markdown/CodeBlock/commands.js +15 -2
- package/build/cjs/extensions/markdown/CodeBlock/const.d.ts +2 -0
- package/build/cjs/extensions/markdown/CodeBlock/const.js +2 -1
- package/build/cjs/extensions/markdown/CodeBlock/index.js +7 -18
- package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/const.d.ts +8 -3
- package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/const.js +7 -1
- package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/index.d.ts +2 -0
- package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/index.js +37 -1
- package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/md-plugin.d.ts +2 -0
- package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/md-plugin.js +79 -0
- package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/parser.js +24 -4
- package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js +66 -1
- package/build/cjs/extensions/yfm/YfmTabs/YfmTabsSpecs/serializer.js +28 -0
- package/build/cjs/extensions/yfm/YfmTabs/index.js +2 -0
- package/build/cjs/extensions/yfm/YfmTabs/views.d.ts +2 -0
- package/build/cjs/extensions/yfm/YfmTabs/views.js +15 -3
- package/build/cjs/markup/codemirror/create.js +4 -0
- package/build/cjs/version.js +1 -1
- package/build/esm/extensions/markdown/CodeBlock/commands.d.ts +4 -0
- package/build/esm/extensions/markdown/CodeBlock/commands.js +14 -2
- package/build/esm/extensions/markdown/CodeBlock/const.d.ts +2 -0
- package/build/esm/extensions/markdown/CodeBlock/const.js +1 -0
- package/build/esm/extensions/markdown/CodeBlock/index.js +8 -19
- package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/const.d.ts +8 -3
- package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/const.js +7 -1
- package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/index.d.ts +2 -0
- package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/index.js +37 -1
- package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/md-plugin.d.ts +2 -0
- package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/md-plugin.js +75 -0
- package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/parser.js +24 -4
- package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/schema.js +66 -1
- package/build/esm/extensions/yfm/YfmTabs/YfmTabsSpecs/serializer.js +28 -0
- package/build/esm/extensions/yfm/YfmTabs/index.js +3 -1
- package/build/esm/extensions/yfm/YfmTabs/views.d.ts +2 -0
- package/build/esm/extensions/yfm/YfmTabs/views.js +12 -2
- package/build/esm/markup/codemirror/create.js +5 -1
- package/build/esm/version.js +1 -1
- package/package.json +2 -2
|
@@ -1,2 +1,6 @@
|
|
|
1
|
+
import { newlineInCode } from 'prosemirror-commands';
|
|
1
2
|
import type { Command } from 'prosemirror-state';
|
|
3
|
+
import type { ExtensionDeps } from '../../../core';
|
|
4
|
+
export { newlineInCode };
|
|
2
5
|
export declare const resetCodeblock: Command;
|
|
6
|
+
export declare const setCodeBlockType: ({ serializer }: ExtensionDeps) => Command;
|
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resetCodeblock = void 0;
|
|
3
|
+
exports.setCodeBlockType = exports.resetCodeblock = exports.newlineInCode = void 0;
|
|
4
|
+
const prosemirror_commands_1 = require("prosemirror-commands");
|
|
5
|
+
Object.defineProperty(exports, "newlineInCode", { enumerable: true, get: function () { return prosemirror_commands_1.newlineInCode; } });
|
|
4
6
|
const BaseSchema_1 = require("../../base/BaseSchema");
|
|
5
7
|
const const_1 = require("./const");
|
|
6
8
|
const resetCodeblock = (state, dispatch, view) => {
|
|
7
9
|
const { selection } = state;
|
|
8
10
|
if (selection.empty &&
|
|
9
|
-
selection.$from.parent.type === (0, const_1.
|
|
11
|
+
selection.$from.parent.type === (0, const_1.codeBlockType)(state.schema) &&
|
|
10
12
|
(view === null || view === void 0 ? void 0 : view.endOfTextblock('backward', state))) {
|
|
11
13
|
return (0, BaseSchema_1.toParagraph)(state, dispatch, view);
|
|
12
14
|
}
|
|
13
15
|
return false;
|
|
14
16
|
};
|
|
15
17
|
exports.resetCodeblock = resetCodeblock;
|
|
18
|
+
const setCodeBlockType = ({ serializer }) => (state, dispatch) => {
|
|
19
|
+
const nodeType = (0, const_1.codeBlockType)(state.schema);
|
|
20
|
+
if (!(0, prosemirror_commands_1.setBlockType)(nodeType)(state))
|
|
21
|
+
return false;
|
|
22
|
+
if (dispatch) {
|
|
23
|
+
const markup = serializer.serialize(state.selection.content().content);
|
|
24
|
+
dispatch(state.tr.replaceSelectionWith(nodeType.createAndFill({}, markup ? state.schema.text(markup) : null)));
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
};
|
|
28
|
+
exports.setCodeBlockType = setCodeBlockType;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { codeBlockType } from './CodeBlockSpecs';
|
|
1
2
|
export { codeBlockNodeName, codeBlockLangAttr, CodeBlockNodeAttr as CodeBlockAttr, } from './CodeBlockSpecs';
|
|
2
3
|
export declare const cbAction = "toCodeBlock";
|
|
3
4
|
/** @deprecated Use `codeBlockType` instead */
|
|
4
5
|
export declare const cbType: (schema: import("prosemirror-model").Schema<any, any>) => import("prosemirror-model").NodeType;
|
|
6
|
+
export { codeBlockType };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.cbType = exports.cbAction = exports.CodeBlockAttr = exports.codeBlockLangAttr = exports.codeBlockNodeName = void 0;
|
|
3
|
+
exports.codeBlockType = exports.cbType = exports.cbAction = exports.CodeBlockAttr = exports.codeBlockLangAttr = exports.codeBlockNodeName = void 0;
|
|
4
4
|
const CodeBlockSpecs_1 = require("./CodeBlockSpecs");
|
|
5
|
+
Object.defineProperty(exports, "codeBlockType", { enumerable: true, get: function () { return CodeBlockSpecs_1.codeBlockType; } });
|
|
5
6
|
var CodeBlockSpecs_2 = require("./CodeBlockSpecs");
|
|
6
7
|
Object.defineProperty(exports, "codeBlockNodeName", { enumerable: true, get: function () { return CodeBlockSpecs_2.codeBlockNodeName; } });
|
|
7
8
|
Object.defineProperty(exports, "codeBlockLangAttr", { enumerable: true, get: function () { return CodeBlockSpecs_2.codeBlockLangAttr; } });
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CodeBlock = exports.codeBlockType = exports.codeBlockLangAttr = exports.CodeBlockNodeAttr = exports.codeBlockNodeName = exports.resetCodeblock = void 0;
|
|
4
|
-
const prosemirror_commands_1 = require("prosemirror-commands");
|
|
5
|
-
const prosemirror_model_1 = require("prosemirror-model");
|
|
6
4
|
const prosemirror_utils_1 = require("prosemirror-utils");
|
|
7
5
|
const lodash_1 = require("../../../lodash");
|
|
8
6
|
const inputrules_1 = require("../../../utils/inputrules");
|
|
@@ -24,28 +22,19 @@ const CodeBlock = (builder, opts) => {
|
|
|
24
22
|
builder.use(CodeBlockSpecs_1.CodeBlockSpecs, opts);
|
|
25
23
|
builder.addKeymap((deps) => {
|
|
26
24
|
const { codeBlockKey } = opts;
|
|
27
|
-
const bindings = { Enter:
|
|
25
|
+
const bindings = { Enter: commands_1.newlineInCode, Backspace: commands_1.resetCodeblock };
|
|
28
26
|
if (codeBlockKey) {
|
|
29
|
-
bindings[codeBlockKey] = (0, keymap_1.withLogAction)('code_block', (0,
|
|
27
|
+
bindings[codeBlockKey] = (0, keymap_1.withLogAction)('code_block', (0, commands_1.setCodeBlockType)(deps));
|
|
30
28
|
}
|
|
31
29
|
return bindings;
|
|
32
30
|
});
|
|
33
|
-
builder.addInputRules(({ schema }) => ({ rules: [codeBlockRule((0, const_1.
|
|
34
|
-
builder.addAction(const_1.cbAction, (
|
|
35
|
-
const cb = (0, const_1.
|
|
36
|
-
const cmd = (state, dispatch) => {
|
|
37
|
-
if (!(0, prosemirror_commands_1.setBlockType)(cb)(state))
|
|
38
|
-
return false;
|
|
39
|
-
if (dispatch) {
|
|
40
|
-
const markup = serializer.serialize(prosemirror_model_1.Fragment.from(state.selection.content().content));
|
|
41
|
-
dispatch(state.tr.replaceSelectionWith(cb.createAndFill({}, markup ? state.schema.text(markup) : null)));
|
|
42
|
-
}
|
|
43
|
-
return true;
|
|
44
|
-
};
|
|
31
|
+
builder.addInputRules(({ schema }) => ({ rules: [codeBlockRule((0, const_1.codeBlockType)(schema))] }));
|
|
32
|
+
builder.addAction(const_1.cbAction, (deps) => {
|
|
33
|
+
const cb = (0, const_1.codeBlockType)(deps.schema);
|
|
45
34
|
return {
|
|
46
35
|
isActive: (state) => (0, prosemirror_utils_1.hasParentNodeOfType)(cb)(state.selection),
|
|
47
|
-
isEnable:
|
|
48
|
-
run:
|
|
36
|
+
isEnable: (0, commands_1.setCodeBlockType)(deps),
|
|
37
|
+
run: (0, commands_1.setCodeBlockType)(deps),
|
|
49
38
|
};
|
|
50
39
|
});
|
|
51
40
|
builder.addPlugin(codeBlockPastePlugin_1.codeBlockPastePlugin, builder.Priority.High);
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
export declare enum TabsNode {
|
|
2
|
+
TabPanel = "yfm_tab_panel",
|
|
2
3
|
Tab = "yfm_tab",
|
|
3
4
|
TabsList = "yfm_tabs_list",
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
Tabs = "yfm_tabs",
|
|
6
|
+
RadioTabs = "yfm_radio_tabs",
|
|
7
|
+
RadioTab = "yfm_radio_tab",
|
|
8
|
+
RadioTabInput = "yfm_radio_tab_input",
|
|
9
|
+
RadioTabLabel = "yfm_radio_tab_label"
|
|
6
10
|
}
|
|
7
11
|
export declare enum TabsAttrs {
|
|
8
12
|
class = "class",
|
|
@@ -21,7 +25,8 @@ export declare enum TabAttrs {
|
|
|
21
25
|
tabindex = "tabindex",
|
|
22
26
|
dataDiplodocKey = "data-diplodoc-key",
|
|
23
27
|
dataDiplodocid = "data-diplodoc-id",
|
|
24
|
-
dataDiplodocIsActive = "data-diplodoc-is-active"
|
|
28
|
+
dataDiplodocIsActive = "data-diplodoc-is-active",
|
|
29
|
+
dataDiplodocVerticalTab = "data-diplodoc-vertical-tab"
|
|
25
30
|
}
|
|
26
31
|
export declare enum TabPanelAttrs {
|
|
27
32
|
id = "id",
|
|
@@ -3,10 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TabPanelAttrs = exports.TabAttrs = exports.TabsListAttrs = exports.TabsAttrs = exports.TabsNode = void 0;
|
|
4
4
|
var TabsNode;
|
|
5
5
|
(function (TabsNode) {
|
|
6
|
+
// tabs panel is common for tabs and radio tabs
|
|
7
|
+
TabsNode["TabPanel"] = "yfm_tab_panel";
|
|
6
8
|
TabsNode["Tab"] = "yfm_tab";
|
|
7
9
|
TabsNode["TabsList"] = "yfm_tabs_list";
|
|
8
|
-
TabsNode["TabPanel"] = "yfm_tab_panel";
|
|
9
10
|
TabsNode["Tabs"] = "yfm_tabs";
|
|
11
|
+
TabsNode["RadioTabs"] = "yfm_radio_tabs";
|
|
12
|
+
TabsNode["RadioTab"] = "yfm_radio_tab";
|
|
13
|
+
TabsNode["RadioTabInput"] = "yfm_radio_tab_input";
|
|
14
|
+
TabsNode["RadioTabLabel"] = "yfm_radio_tab_label";
|
|
10
15
|
})(TabsNode = exports.TabsNode || (exports.TabsNode = {}));
|
|
11
16
|
var TabsAttrs;
|
|
12
17
|
(function (TabsAttrs) {
|
|
@@ -29,6 +34,7 @@ var TabAttrs;
|
|
|
29
34
|
TabAttrs["dataDiplodocKey"] = "data-diplodoc-key";
|
|
30
35
|
TabAttrs["dataDiplodocid"] = "data-diplodoc-id";
|
|
31
36
|
TabAttrs["dataDiplodocIsActive"] = "data-diplodoc-is-active";
|
|
37
|
+
TabAttrs["dataDiplodocVerticalTab"] = "data-diplodoc-vertical-tab";
|
|
32
38
|
})(TabAttrs = exports.TabAttrs || (exports.TabAttrs = {}));
|
|
33
39
|
var TabPanelAttrs;
|
|
34
40
|
(function (TabPanelAttrs) {
|
|
@@ -14,5 +14,7 @@ export declare type YfmTabsSpecsOptions = {
|
|
|
14
14
|
tabsListView?: ExtensionNodeSpec['view'];
|
|
15
15
|
tabPanelView?: ExtensionNodeSpec['view'];
|
|
16
16
|
tabsView?: ExtensionNodeSpec['view'];
|
|
17
|
+
vtabView?: ExtensionNodeSpec['view'];
|
|
18
|
+
vtabInputView?: ExtensionNodeSpec['view'];
|
|
17
19
|
};
|
|
18
20
|
export declare const YfmTabsSpecs: ExtensionAuto<YfmTabsSpecsOptions>;
|
|
@@ -6,6 +6,7 @@ const log_1 = tslib_1.__importDefault(require("@diplodoc/transform/lib/log"));
|
|
|
6
6
|
const tabs_1 = tslib_1.__importDefault(require("@diplodoc/transform/lib/plugins/tabs"));
|
|
7
7
|
const schema_1 = require("../../../../utils/schema");
|
|
8
8
|
const const_1 = require("./const");
|
|
9
|
+
const md_plugin_1 = require("./md-plugin");
|
|
9
10
|
const parser_1 = require("./parser");
|
|
10
11
|
const schema_2 = require("./schema");
|
|
11
12
|
const serializer_1 = require("./serializer");
|
|
@@ -18,7 +19,7 @@ exports.tabsListType = (0, schema_1.nodeTypeFactory)(const_1.TabsNode.TabsList);
|
|
|
18
19
|
const YfmTabsSpecs = (builder, opts) => {
|
|
19
20
|
const schemaSpecs = (0, schema_2.getSchemaSpecs)(opts);
|
|
20
21
|
builder
|
|
21
|
-
.configureMd((md) => md.use(tabs_1.default, { log: log_1.default }))
|
|
22
|
+
.configureMd((md) => md.use(tabs_1.default, { log: log_1.default }).use(md_plugin_1.tabsPostPlugin))
|
|
22
23
|
.addNode(const_1.TabsNode.Tab, () => ({
|
|
23
24
|
spec: schemaSpecs[const_1.TabsNode.Tab],
|
|
24
25
|
toMd: serializer_1.serializerTokens[const_1.TabsNode.Tab],
|
|
@@ -55,5 +56,40 @@ const YfmTabsSpecs = (builder, opts) => {
|
|
|
55
56
|
},
|
|
56
57
|
view: opts.tabsView,
|
|
57
58
|
}));
|
|
59
|
+
builder
|
|
60
|
+
.addNode(const_1.TabsNode.RadioTabs, () => ({
|
|
61
|
+
spec: schemaSpecs[const_1.TabsNode.RadioTabs],
|
|
62
|
+
toMd: serializer_1.serializerTokens[const_1.TabsNode.RadioTabs],
|
|
63
|
+
fromMd: {
|
|
64
|
+
tokenSpec: parser_1.parserTokens[const_1.TabsNode.RadioTabs],
|
|
65
|
+
tokenName: 'r-tabs',
|
|
66
|
+
},
|
|
67
|
+
}))
|
|
68
|
+
.addNode(const_1.TabsNode.RadioTab, () => ({
|
|
69
|
+
spec: schemaSpecs[const_1.TabsNode.RadioTab],
|
|
70
|
+
toMd: serializer_1.serializerTokens[const_1.TabsNode.RadioTab],
|
|
71
|
+
fromMd: {
|
|
72
|
+
tokenSpec: parser_1.parserTokens[const_1.TabsNode.RadioTab],
|
|
73
|
+
tokenName: 'r-tab',
|
|
74
|
+
},
|
|
75
|
+
view: opts.vtabView,
|
|
76
|
+
}))
|
|
77
|
+
.addNode(const_1.TabsNode.RadioTabInput, () => ({
|
|
78
|
+
spec: schemaSpecs[const_1.TabsNode.RadioTabInput],
|
|
79
|
+
toMd: serializer_1.serializerTokens[const_1.TabsNode.RadioTabInput],
|
|
80
|
+
fromMd: {
|
|
81
|
+
tokenSpec: parser_1.parserTokens[const_1.TabsNode.RadioTabInput],
|
|
82
|
+
tokenName: 'r-tab-input',
|
|
83
|
+
},
|
|
84
|
+
view: opts.vtabInputView,
|
|
85
|
+
}))
|
|
86
|
+
.addNode(const_1.TabsNode.RadioTabLabel, () => ({
|
|
87
|
+
spec: schemaSpecs[const_1.TabsNode.RadioTabLabel],
|
|
88
|
+
toMd: serializer_1.serializerTokens[const_1.TabsNode.RadioTabLabel],
|
|
89
|
+
fromMd: {
|
|
90
|
+
tokenSpec: parser_1.parserTokens[const_1.TabsNode.RadioTabLabel],
|
|
91
|
+
tokenName: 'r-tab-label',
|
|
92
|
+
},
|
|
93
|
+
}));
|
|
58
94
|
};
|
|
59
95
|
exports.YfmTabsSpecs = YfmTabsSpecs;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.tabsPostPlugin = void 0;
|
|
4
|
+
const prefix = 'r-';
|
|
5
|
+
// prefix is added to token types of radio tabs tokens in order to use other nodes in prosemirror
|
|
6
|
+
const tabsPostPlugin = (md) => {
|
|
7
|
+
md.core.ruler.push('me_tabs_after', (state) => {
|
|
8
|
+
var _a;
|
|
9
|
+
const stack = [];
|
|
10
|
+
const tabCloseIndexes = [];
|
|
11
|
+
for (const token of state.tokens) {
|
|
12
|
+
switch (token.type) {
|
|
13
|
+
case 'tabs_open': {
|
|
14
|
+
const vertical = (_a = token.attrGet('class')) === null || _a === void 0 ? void 0 : _a.includes('yfm-tabs-vertical');
|
|
15
|
+
stack.push({ vertical });
|
|
16
|
+
if (vertical)
|
|
17
|
+
token.type = prefix + token.type;
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
case 'tabs_close': {
|
|
21
|
+
const item = stack.pop();
|
|
22
|
+
if (item === null || item === void 0 ? void 0 : item.vertical)
|
|
23
|
+
token.type = prefix + token.type;
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
case 'tab_open': {
|
|
27
|
+
const item = stack.at(-1);
|
|
28
|
+
if (item === null || item === void 0 ? void 0 : item.vertical) {
|
|
29
|
+
// --> TODO: remove after updating to tabs-extension v^3.4.0
|
|
30
|
+
const isInput = token.tag === 'input';
|
|
31
|
+
if (isInput)
|
|
32
|
+
token.type = 'tab-input';
|
|
33
|
+
// <--
|
|
34
|
+
token.type = prefix + token.type;
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
case 'tab_close': {
|
|
39
|
+
const item = stack.at(-1);
|
|
40
|
+
if (item === null || item === void 0 ? void 0 : item.vertical) {
|
|
41
|
+
token.type = prefix + token.type;
|
|
42
|
+
// --> TODO: remove after updating to tabs-extension v^3.4.0
|
|
43
|
+
tabCloseIndexes.push(state.tokens.indexOf(token));
|
|
44
|
+
// <--
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
case 'tab-input':
|
|
49
|
+
case 'tab-label_open':
|
|
50
|
+
case 'tab-label_close': {
|
|
51
|
+
const item = stack.at(-1);
|
|
52
|
+
if (item === null || item === void 0 ? void 0 : item.vertical) {
|
|
53
|
+
token.type = prefix + token.type;
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
// --> TODO: remove after updating to tabs-extension v^3.4.0
|
|
58
|
+
case 'label_open': {
|
|
59
|
+
const tokenIndex = state.tokens.indexOf(token);
|
|
60
|
+
const prevToken = tokenIndex > 0 && state.tokens.at(tokenIndex - 1);
|
|
61
|
+
if (prevToken && prevToken.type === 'r-tab-input') {
|
|
62
|
+
token.type = prefix + 'tab-' + token.type;
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
// <--
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// --> TODO: remove after updating to tabs-extension v^3.4.0
|
|
70
|
+
for (const index of tabCloseIndexes.reverse()) {
|
|
71
|
+
if (index === -1)
|
|
72
|
+
continue;
|
|
73
|
+
const labelCloseToken = new state.Token(prefix + 'tab-label_close', 'label', -1);
|
|
74
|
+
state.tokens.splice(index, 0, labelCloseToken);
|
|
75
|
+
}
|
|
76
|
+
// <--
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
exports.tabsPostPlugin = tabsPostPlugin;
|
|
@@ -4,13 +4,13 @@ exports.parserTokens = void 0;
|
|
|
4
4
|
const const_1 = require("./const");
|
|
5
5
|
const attrsFromEntries = (token) => (token.attrs ? Object.fromEntries(token.attrs) : {});
|
|
6
6
|
exports.parserTokens = {
|
|
7
|
-
[const_1.TabsNode.
|
|
8
|
-
name: const_1.TabsNode.
|
|
7
|
+
[const_1.TabsNode.TabPanel]: {
|
|
8
|
+
name: const_1.TabsNode.TabPanel,
|
|
9
9
|
type: 'block',
|
|
10
10
|
getAttrs: attrsFromEntries,
|
|
11
11
|
},
|
|
12
|
-
[const_1.TabsNode.
|
|
13
|
-
name: const_1.TabsNode.
|
|
12
|
+
[const_1.TabsNode.Tab]: {
|
|
13
|
+
name: const_1.TabsNode.Tab,
|
|
14
14
|
type: 'block',
|
|
15
15
|
getAttrs: attrsFromEntries,
|
|
16
16
|
},
|
|
@@ -24,4 +24,24 @@ exports.parserTokens = {
|
|
|
24
24
|
type: 'block',
|
|
25
25
|
getAttrs: attrsFromEntries,
|
|
26
26
|
},
|
|
27
|
+
[const_1.TabsNode.RadioTabs]: {
|
|
28
|
+
name: const_1.TabsNode.RadioTabs,
|
|
29
|
+
type: 'block',
|
|
30
|
+
getAttrs: attrsFromEntries,
|
|
31
|
+
},
|
|
32
|
+
[const_1.TabsNode.RadioTab]: {
|
|
33
|
+
name: const_1.TabsNode.RadioTab,
|
|
34
|
+
type: 'block',
|
|
35
|
+
getAttrs: attrsFromEntries,
|
|
36
|
+
},
|
|
37
|
+
[const_1.TabsNode.RadioTabInput]: {
|
|
38
|
+
name: const_1.TabsNode.RadioTabInput,
|
|
39
|
+
type: 'node',
|
|
40
|
+
getAttrs: attrsFromEntries,
|
|
41
|
+
},
|
|
42
|
+
[const_1.TabsNode.RadioTabLabel]: {
|
|
43
|
+
name: const_1.TabsNode.RadioTabLabel,
|
|
44
|
+
type: 'block',
|
|
45
|
+
getAttrs: attrsFromEntries,
|
|
46
|
+
},
|
|
27
47
|
};
|
|
@@ -4,9 +4,10 @@ exports.getSchemaSpecs = void 0;
|
|
|
4
4
|
const const_1 = require("./const");
|
|
5
5
|
const DEFAULT_PLACEHOLDERS = {
|
|
6
6
|
TabTitle: 'Tab title',
|
|
7
|
+
RadioTabLabelTitle: 'Radio title',
|
|
7
8
|
};
|
|
8
9
|
const getSchemaSpecs = (opts, placeholder) => {
|
|
9
|
-
var _a, _b;
|
|
10
|
+
var _a, _b, _c;
|
|
10
11
|
return ({
|
|
11
12
|
[const_1.TabsNode.Tab]: {
|
|
12
13
|
attrs: {
|
|
@@ -82,6 +83,70 @@ const getSchemaSpecs = (opts, placeholder) => {
|
|
|
82
83
|
allowSelection: false,
|
|
83
84
|
complex: 'inner',
|
|
84
85
|
},
|
|
86
|
+
[const_1.TabsNode.RadioTabs]: {
|
|
87
|
+
attrs: {
|
|
88
|
+
[const_1.TabsAttrs.class]: { default: 'yfm-tabs yfm-tabs-vertical' },
|
|
89
|
+
[const_1.TabsAttrs.dataDiplodocGroup]: { default: 'unknown' },
|
|
90
|
+
},
|
|
91
|
+
content: `(${const_1.TabsNode.RadioTab} ${const_1.TabsNode.TabPanel})+`,
|
|
92
|
+
group: 'block',
|
|
93
|
+
toDOM(node) {
|
|
94
|
+
return ['div', node.attrs, 0];
|
|
95
|
+
},
|
|
96
|
+
complex: 'root',
|
|
97
|
+
},
|
|
98
|
+
[const_1.TabsNode.RadioTab]: {
|
|
99
|
+
attrs: {
|
|
100
|
+
[const_1.TabAttrs.id]: { default: null },
|
|
101
|
+
[const_1.TabAttrs.class]: { default: 'yfm-tab yfm-vertical-tab' },
|
|
102
|
+
[const_1.TabAttrs.role]: { default: 'unknown' },
|
|
103
|
+
[const_1.TabAttrs.ariaControls]: { default: 'unknown' },
|
|
104
|
+
[const_1.TabAttrs.ariaSelected]: { default: 'unknown' },
|
|
105
|
+
[const_1.TabAttrs.tabindex]: { default: 'unknown' },
|
|
106
|
+
[const_1.TabAttrs.dataDiplodocKey]: { default: 'unknown' },
|
|
107
|
+
[const_1.TabAttrs.dataDiplodocid]: { default: 'unknown' },
|
|
108
|
+
[const_1.TabAttrs.dataDiplodocIsActive]: { default: 'false' },
|
|
109
|
+
[const_1.TabAttrs.dataDiplodocVerticalTab]: { default: 'true' },
|
|
110
|
+
},
|
|
111
|
+
content: `${const_1.TabsNode.RadioTabInput} ${const_1.TabsNode.RadioTabLabel}`,
|
|
112
|
+
group: 'block',
|
|
113
|
+
toDOM(node) {
|
|
114
|
+
return ['div', node.attrs, 0];
|
|
115
|
+
},
|
|
116
|
+
selectable: false,
|
|
117
|
+
allowSelection: false,
|
|
118
|
+
complex: 'inner',
|
|
119
|
+
},
|
|
120
|
+
[const_1.TabsNode.RadioTabInput]: {
|
|
121
|
+
attrs: {
|
|
122
|
+
[const_1.TabAttrs.class]: { default: 'radio' },
|
|
123
|
+
type: { default: 'radio' },
|
|
124
|
+
checked: { default: null },
|
|
125
|
+
},
|
|
126
|
+
group: 'block',
|
|
127
|
+
toDOM(node) {
|
|
128
|
+
return ['input', node.attrs];
|
|
129
|
+
},
|
|
130
|
+
selectable: false,
|
|
131
|
+
allowSelection: false,
|
|
132
|
+
complex: 'leaf',
|
|
133
|
+
},
|
|
134
|
+
[const_1.TabsNode.RadioTabLabel]: {
|
|
135
|
+
attrs: {},
|
|
136
|
+
marks: '',
|
|
137
|
+
content: 'text*',
|
|
138
|
+
group: 'block',
|
|
139
|
+
toDOM(node) {
|
|
140
|
+
return ['label', node.attrs, 0];
|
|
141
|
+
},
|
|
142
|
+
placeholder: {
|
|
143
|
+
content: (_c = placeholder === null || placeholder === void 0 ? void 0 : placeholder[const_1.TabsNode.RadioTab]) !== null && _c !== void 0 ? _c : DEFAULT_PLACEHOLDERS.RadioTabLabelTitle,
|
|
144
|
+
alwaysVisible: true,
|
|
145
|
+
},
|
|
146
|
+
selectable: false,
|
|
147
|
+
allowSelection: false,
|
|
148
|
+
complex: 'leaf',
|
|
149
|
+
},
|
|
85
150
|
});
|
|
86
151
|
};
|
|
87
152
|
exports.getSchemaSpecs = getSchemaSpecs;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.serializerTokens = void 0;
|
|
4
|
+
const nodes_1 = require("../../../../utils/nodes");
|
|
4
5
|
const placeholder_1 = require("../../../../utils/placeholder");
|
|
5
6
|
const const_1 = require("./const");
|
|
6
7
|
exports.serializerTokens = {
|
|
@@ -32,4 +33,31 @@ exports.serializerTokens = {
|
|
|
32
33
|
[const_1.TabsNode.TabsList]: (state, node) => {
|
|
33
34
|
state.renderList(node, ' ', () => (node.attrs.bullet || '-') + ' ');
|
|
34
35
|
},
|
|
36
|
+
[const_1.TabsNode.RadioTabs]: (state, node) => {
|
|
37
|
+
state.write('{% list tabs radio %}');
|
|
38
|
+
state.write('\n');
|
|
39
|
+
state.write('\n');
|
|
40
|
+
const children = (0, nodes_1.getChildrenOfNode)(node);
|
|
41
|
+
for (let i = 0; i < children.length; i++) {
|
|
42
|
+
const child = children[i];
|
|
43
|
+
if (child.node.type.name !== const_1.TabsNode.RadioTab)
|
|
44
|
+
continue;
|
|
45
|
+
state.write('- ' + (child.node.textContent || (0, placeholder_1.getPlaceholderContent)(child.node.lastChild)));
|
|
46
|
+
state.write('\n');
|
|
47
|
+
state.write('\n');
|
|
48
|
+
const nextChild = children[i + 1];
|
|
49
|
+
if (nextChild.node.type.name !== const_1.TabsNode.TabPanel)
|
|
50
|
+
continue;
|
|
51
|
+
state.renderList(nextChild.node, ' ', () => ' ');
|
|
52
|
+
}
|
|
53
|
+
state.write('{% endlist %}');
|
|
54
|
+
state.closeBlock(node);
|
|
55
|
+
},
|
|
56
|
+
[const_1.TabsNode.RadioTab]: (state, node) => {
|
|
57
|
+
state.renderInline(node);
|
|
58
|
+
},
|
|
59
|
+
[const_1.TabsNode.RadioTabInput]: () => { },
|
|
60
|
+
[const_1.TabsNode.RadioTabLabel]: (state, node) => {
|
|
61
|
+
state.renderInline(node);
|
|
62
|
+
},
|
|
35
63
|
};
|
|
@@ -17,6 +17,8 @@ const YfmTabs = (builder) => {
|
|
|
17
17
|
builder.use(YfmTabsSpecs_1.YfmTabsSpecs, {
|
|
18
18
|
tabView: () => views_1.tabView,
|
|
19
19
|
tabPanelView: () => views_1.tabPanelView,
|
|
20
|
+
vtabView: () => views_1.vtabView,
|
|
21
|
+
vtabInputView: () => views_1.vtabInputView,
|
|
20
22
|
});
|
|
21
23
|
builder.addKeymap(() => ({
|
|
22
24
|
Backspace: (0, prosemirror_commands_1.chainCommands)(plugins_1.removeTabWhenCursorAtTheStartOfTab, plugins_1.joinBackwardToOpenTab),
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import { NodeViewConstructor } from 'prosemirror-view';
|
|
2
2
|
export declare const tabView: NodeViewConstructor;
|
|
3
3
|
export declare const tabPanelView: NodeViewConstructor;
|
|
4
|
+
export declare const vtabView: NodeViewConstructor;
|
|
5
|
+
export declare const vtabInputView: NodeViewConstructor;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.tabPanelView = exports.tabView = void 0;
|
|
3
|
+
exports.vtabInputView = exports.vtabView = exports.tabPanelView = exports.tabView = void 0;
|
|
4
4
|
const prosemirror_utils_1 = require("prosemirror-utils");
|
|
5
5
|
const classname_1 = require("../../../classname");
|
|
6
6
|
const icons_1 = require("./icons");
|
|
@@ -12,7 +12,7 @@ const ignoreMutation = (node, view, getPos) => (mutation) => {
|
|
|
12
12
|
mutation.type === 'attributes' &&
|
|
13
13
|
mutation.attributeName) {
|
|
14
14
|
const newAttr = mutation.target.getAttribute(mutation.attributeName);
|
|
15
|
-
view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, Object.assign(Object.assign({}, node.attrs), { [mutation.attributeName]:
|
|
15
|
+
view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, Object.assign(Object.assign({}, node.attrs), { [mutation.attributeName]: newAttr })));
|
|
16
16
|
return true;
|
|
17
17
|
}
|
|
18
18
|
return false;
|
|
@@ -74,7 +74,19 @@ const tabView = (node, view, getPos) => {
|
|
|
74
74
|
exports.tabView = tabView;
|
|
75
75
|
// @ts-expect-error
|
|
76
76
|
const tabPanelView = (node, view, getPos) => ({
|
|
77
|
-
//
|
|
77
|
+
// FIXME: ignore mutation and don't rerender node when yfm.js switch tab
|
|
78
78
|
ignoreMutation: ignoreMutation(node, view, getPos),
|
|
79
79
|
});
|
|
80
80
|
exports.tabPanelView = tabPanelView;
|
|
81
|
+
// @ts-expect-error
|
|
82
|
+
const vtabView = (node, view, getPos) => ({
|
|
83
|
+
// FIXME: ignore mutation and don't rerender node when yfm.js switch tab
|
|
84
|
+
ignoreMutation: ignoreMutation(node, view, getPos),
|
|
85
|
+
});
|
|
86
|
+
exports.vtabView = vtabView;
|
|
87
|
+
// @ts-expect-error
|
|
88
|
+
const vtabInputView = (node, view, getPos) => ({
|
|
89
|
+
// FIXME: ignore mutation and don't rerender node when yfm.js switch tab
|
|
90
|
+
ignoreMutation: ignoreMutation(node, view, getPos),
|
|
91
|
+
});
|
|
92
|
+
exports.vtabInputView = vtabInputView;
|
|
@@ -54,6 +54,10 @@ function createCodemirror(params) {
|
|
|
54
54
|
},
|
|
55
55
|
},
|
|
56
56
|
{ key: 'Tab', preventDefault: true, run: commands_1.insertTab },
|
|
57
|
+
{
|
|
58
|
+
key: 'Enter',
|
|
59
|
+
shift: commands_1.insertNewlineKeepIndent,
|
|
60
|
+
},
|
|
57
61
|
commands_1.indentWithTab,
|
|
58
62
|
...commands_1.defaultKeymap,
|
|
59
63
|
...(disabledExtensions.history ? [] : commands_1.historyKeymap),
|
package/build/cjs/version.js
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VERSION = void 0;
|
|
4
4
|
/** During build process, the current version will be injected here */
|
|
5
|
-
exports.VERSION = typeof '13.
|
|
5
|
+
exports.VERSION = typeof '13.21.0' !== 'undefined' ? '13.21.0' : 'unknown';
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
+
import { newlineInCode } from 'prosemirror-commands';
|
|
1
2
|
import type { Command } from 'prosemirror-state';
|
|
3
|
+
import type { ExtensionDeps } from '../../../core';
|
|
4
|
+
export { newlineInCode };
|
|
2
5
|
export declare const resetCodeblock: Command;
|
|
6
|
+
export declare const setCodeBlockType: ({ serializer }: ExtensionDeps) => Command;
|
|
@@ -1,11 +1,23 @@
|
|
|
1
|
+
import { newlineInCode, setBlockType } from 'prosemirror-commands';
|
|
1
2
|
import { toParagraph } from '../../base/BaseSchema';
|
|
2
|
-
import {
|
|
3
|
+
import { codeBlockType } from './const';
|
|
4
|
+
export { newlineInCode };
|
|
3
5
|
export const resetCodeblock = (state, dispatch, view) => {
|
|
4
6
|
const { selection } = state;
|
|
5
7
|
if (selection.empty &&
|
|
6
|
-
selection.$from.parent.type ===
|
|
8
|
+
selection.$from.parent.type === codeBlockType(state.schema) &&
|
|
7
9
|
(view === null || view === void 0 ? void 0 : view.endOfTextblock('backward', state))) {
|
|
8
10
|
return toParagraph(state, dispatch, view);
|
|
9
11
|
}
|
|
10
12
|
return false;
|
|
11
13
|
};
|
|
14
|
+
export const setCodeBlockType = ({ serializer }) => (state, dispatch) => {
|
|
15
|
+
const nodeType = codeBlockType(state.schema);
|
|
16
|
+
if (!setBlockType(nodeType)(state))
|
|
17
|
+
return false;
|
|
18
|
+
if (dispatch) {
|
|
19
|
+
const markup = serializer.serialize(state.selection.content().content);
|
|
20
|
+
dispatch(state.tr.replaceSelectionWith(nodeType.createAndFill({}, markup ? state.schema.text(markup) : null)));
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { codeBlockType } from './CodeBlockSpecs';
|
|
1
2
|
export { codeBlockNodeName, codeBlockLangAttr, CodeBlockNodeAttr as CodeBlockAttr, } from './CodeBlockSpecs';
|
|
2
3
|
export declare const cbAction = "toCodeBlock";
|
|
3
4
|
/** @deprecated Use `codeBlockType` instead */
|
|
4
5
|
export declare const cbType: (schema: import("prosemirror-model").Schema<any, any>) => import("prosemirror-model").NodeType;
|
|
6
|
+
export { codeBlockType };
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { newlineInCode, setBlockType } from 'prosemirror-commands';
|
|
2
|
-
import { Fragment } from 'prosemirror-model';
|
|
3
1
|
import { hasParentNodeOfType } from 'prosemirror-utils';
|
|
4
2
|
import { isFunction } from '../../../lodash';
|
|
5
3
|
import { textblockTypeInputRule } from '../../../utils/inputrules';
|
|
6
4
|
import { withLogAction } from '../../../utils/keymap';
|
|
7
5
|
import { CodeBlockHighlight } from './CodeBlockHighlight/CodeBlockHighlight';
|
|
8
6
|
import { CodeBlockSpecs } from './CodeBlockSpecs';
|
|
9
|
-
import { resetCodeblock } from './commands';
|
|
10
|
-
import { cbAction,
|
|
7
|
+
import { newlineInCode, resetCodeblock, setCodeBlockType } from './commands';
|
|
8
|
+
import { cbAction, codeBlockType } from './const';
|
|
11
9
|
import { codeBlockPastePlugin } from './plugins/codeBlockPastePlugin';
|
|
12
10
|
export { resetCodeblock } from './commands';
|
|
13
11
|
export { codeBlockNodeName, CodeBlockNodeAttr, codeBlockLangAttr, codeBlockType, } from './CodeBlockSpecs';
|
|
@@ -18,26 +16,17 @@ export const CodeBlock = (builder, opts) => {
|
|
|
18
16
|
const { codeBlockKey } = opts;
|
|
19
17
|
const bindings = { Enter: newlineInCode, Backspace: resetCodeblock };
|
|
20
18
|
if (codeBlockKey) {
|
|
21
|
-
bindings[codeBlockKey] = withLogAction('code_block',
|
|
19
|
+
bindings[codeBlockKey] = withLogAction('code_block', setCodeBlockType(deps));
|
|
22
20
|
}
|
|
23
21
|
return bindings;
|
|
24
22
|
});
|
|
25
|
-
builder.addInputRules(({ schema }) => ({ rules: [codeBlockRule(
|
|
26
|
-
builder.addAction(cbAction, (
|
|
27
|
-
const cb =
|
|
28
|
-
const cmd = (state, dispatch) => {
|
|
29
|
-
if (!setBlockType(cb)(state))
|
|
30
|
-
return false;
|
|
31
|
-
if (dispatch) {
|
|
32
|
-
const markup = serializer.serialize(Fragment.from(state.selection.content().content));
|
|
33
|
-
dispatch(state.tr.replaceSelectionWith(cb.createAndFill({}, markup ? state.schema.text(markup) : null)));
|
|
34
|
-
}
|
|
35
|
-
return true;
|
|
36
|
-
};
|
|
23
|
+
builder.addInputRules(({ schema }) => ({ rules: [codeBlockRule(codeBlockType(schema))] }));
|
|
24
|
+
builder.addAction(cbAction, (deps) => {
|
|
25
|
+
const cb = codeBlockType(deps.schema);
|
|
37
26
|
return {
|
|
38
27
|
isActive: (state) => hasParentNodeOfType(cb)(state.selection),
|
|
39
|
-
isEnable:
|
|
40
|
-
run:
|
|
28
|
+
isEnable: setCodeBlockType(deps),
|
|
29
|
+
run: setCodeBlockType(deps),
|
|
41
30
|
};
|
|
42
31
|
});
|
|
43
32
|
builder.addPlugin(codeBlockPastePlugin, builder.Priority.High);
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
export declare enum TabsNode {
|
|
2
|
+
TabPanel = "yfm_tab_panel",
|
|
2
3
|
Tab = "yfm_tab",
|
|
3
4
|
TabsList = "yfm_tabs_list",
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
Tabs = "yfm_tabs",
|
|
6
|
+
RadioTabs = "yfm_radio_tabs",
|
|
7
|
+
RadioTab = "yfm_radio_tab",
|
|
8
|
+
RadioTabInput = "yfm_radio_tab_input",
|
|
9
|
+
RadioTabLabel = "yfm_radio_tab_label"
|
|
6
10
|
}
|
|
7
11
|
export declare enum TabsAttrs {
|
|
8
12
|
class = "class",
|
|
@@ -21,7 +25,8 @@ export declare enum TabAttrs {
|
|
|
21
25
|
tabindex = "tabindex",
|
|
22
26
|
dataDiplodocKey = "data-diplodoc-key",
|
|
23
27
|
dataDiplodocid = "data-diplodoc-id",
|
|
24
|
-
dataDiplodocIsActive = "data-diplodoc-is-active"
|
|
28
|
+
dataDiplodocIsActive = "data-diplodoc-is-active",
|
|
29
|
+
dataDiplodocVerticalTab = "data-diplodoc-vertical-tab"
|
|
25
30
|
}
|
|
26
31
|
export declare enum TabPanelAttrs {
|
|
27
32
|
id = "id",
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
export var TabsNode;
|
|
2
2
|
(function (TabsNode) {
|
|
3
|
+
// tabs panel is common for tabs and radio tabs
|
|
4
|
+
TabsNode["TabPanel"] = "yfm_tab_panel";
|
|
3
5
|
TabsNode["Tab"] = "yfm_tab";
|
|
4
6
|
TabsNode["TabsList"] = "yfm_tabs_list";
|
|
5
|
-
TabsNode["TabPanel"] = "yfm_tab_panel";
|
|
6
7
|
TabsNode["Tabs"] = "yfm_tabs";
|
|
8
|
+
TabsNode["RadioTabs"] = "yfm_radio_tabs";
|
|
9
|
+
TabsNode["RadioTab"] = "yfm_radio_tab";
|
|
10
|
+
TabsNode["RadioTabInput"] = "yfm_radio_tab_input";
|
|
11
|
+
TabsNode["RadioTabLabel"] = "yfm_radio_tab_label";
|
|
7
12
|
})(TabsNode || (TabsNode = {}));
|
|
8
13
|
export var TabsAttrs;
|
|
9
14
|
(function (TabsAttrs) {
|
|
@@ -26,6 +31,7 @@ export var TabAttrs;
|
|
|
26
31
|
TabAttrs["dataDiplodocKey"] = "data-diplodoc-key";
|
|
27
32
|
TabAttrs["dataDiplodocid"] = "data-diplodoc-id";
|
|
28
33
|
TabAttrs["dataDiplodocIsActive"] = "data-diplodoc-is-active";
|
|
34
|
+
TabAttrs["dataDiplodocVerticalTab"] = "data-diplodoc-vertical-tab";
|
|
29
35
|
})(TabAttrs || (TabAttrs = {}));
|
|
30
36
|
export var TabPanelAttrs;
|
|
31
37
|
(function (TabPanelAttrs) {
|
|
@@ -14,5 +14,7 @@ export declare type YfmTabsSpecsOptions = {
|
|
|
14
14
|
tabsListView?: ExtensionNodeSpec['view'];
|
|
15
15
|
tabPanelView?: ExtensionNodeSpec['view'];
|
|
16
16
|
tabsView?: ExtensionNodeSpec['view'];
|
|
17
|
+
vtabView?: ExtensionNodeSpec['view'];
|
|
18
|
+
vtabInputView?: ExtensionNodeSpec['view'];
|
|
17
19
|
};
|
|
18
20
|
export declare const YfmTabsSpecs: ExtensionAuto<YfmTabsSpecsOptions>;
|
|
@@ -2,6 +2,7 @@ import log from '@diplodoc/transform/lib/log';
|
|
|
2
2
|
import yfmPlugin from '@diplodoc/transform/lib/plugins/tabs';
|
|
3
3
|
import { nodeTypeFactory } from '../../../../utils/schema';
|
|
4
4
|
import { TabsNode } from './const';
|
|
5
|
+
import { tabsPostPlugin } from './md-plugin';
|
|
5
6
|
import { parserTokens } from './parser';
|
|
6
7
|
import { getSchemaSpecs } from './schema';
|
|
7
8
|
import { serializerTokens } from './serializer';
|
|
@@ -13,7 +14,7 @@ export const tabsListType = nodeTypeFactory(TabsNode.TabsList);
|
|
|
13
14
|
export const YfmTabsSpecs = (builder, opts) => {
|
|
14
15
|
const schemaSpecs = getSchemaSpecs(opts);
|
|
15
16
|
builder
|
|
16
|
-
.configureMd((md) => md.use(yfmPlugin, { log }))
|
|
17
|
+
.configureMd((md) => md.use(yfmPlugin, { log }).use(tabsPostPlugin))
|
|
17
18
|
.addNode(TabsNode.Tab, () => ({
|
|
18
19
|
spec: schemaSpecs[TabsNode.Tab],
|
|
19
20
|
toMd: serializerTokens[TabsNode.Tab],
|
|
@@ -50,4 +51,39 @@ export const YfmTabsSpecs = (builder, opts) => {
|
|
|
50
51
|
},
|
|
51
52
|
view: opts.tabsView,
|
|
52
53
|
}));
|
|
54
|
+
builder
|
|
55
|
+
.addNode(TabsNode.RadioTabs, () => ({
|
|
56
|
+
spec: schemaSpecs[TabsNode.RadioTabs],
|
|
57
|
+
toMd: serializerTokens[TabsNode.RadioTabs],
|
|
58
|
+
fromMd: {
|
|
59
|
+
tokenSpec: parserTokens[TabsNode.RadioTabs],
|
|
60
|
+
tokenName: 'r-tabs',
|
|
61
|
+
},
|
|
62
|
+
}))
|
|
63
|
+
.addNode(TabsNode.RadioTab, () => ({
|
|
64
|
+
spec: schemaSpecs[TabsNode.RadioTab],
|
|
65
|
+
toMd: serializerTokens[TabsNode.RadioTab],
|
|
66
|
+
fromMd: {
|
|
67
|
+
tokenSpec: parserTokens[TabsNode.RadioTab],
|
|
68
|
+
tokenName: 'r-tab',
|
|
69
|
+
},
|
|
70
|
+
view: opts.vtabView,
|
|
71
|
+
}))
|
|
72
|
+
.addNode(TabsNode.RadioTabInput, () => ({
|
|
73
|
+
spec: schemaSpecs[TabsNode.RadioTabInput],
|
|
74
|
+
toMd: serializerTokens[TabsNode.RadioTabInput],
|
|
75
|
+
fromMd: {
|
|
76
|
+
tokenSpec: parserTokens[TabsNode.RadioTabInput],
|
|
77
|
+
tokenName: 'r-tab-input',
|
|
78
|
+
},
|
|
79
|
+
view: opts.vtabInputView,
|
|
80
|
+
}))
|
|
81
|
+
.addNode(TabsNode.RadioTabLabel, () => ({
|
|
82
|
+
spec: schemaSpecs[TabsNode.RadioTabLabel],
|
|
83
|
+
toMd: serializerTokens[TabsNode.RadioTabLabel],
|
|
84
|
+
fromMd: {
|
|
85
|
+
tokenSpec: parserTokens[TabsNode.RadioTabLabel],
|
|
86
|
+
tokenName: 'r-tab-label',
|
|
87
|
+
},
|
|
88
|
+
}));
|
|
53
89
|
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const prefix = 'r-';
|
|
2
|
+
// prefix is added to token types of radio tabs tokens in order to use other nodes in prosemirror
|
|
3
|
+
export const tabsPostPlugin = (md) => {
|
|
4
|
+
md.core.ruler.push('me_tabs_after', (state) => {
|
|
5
|
+
var _a;
|
|
6
|
+
const stack = [];
|
|
7
|
+
const tabCloseIndexes = [];
|
|
8
|
+
for (const token of state.tokens) {
|
|
9
|
+
switch (token.type) {
|
|
10
|
+
case 'tabs_open': {
|
|
11
|
+
const vertical = (_a = token.attrGet('class')) === null || _a === void 0 ? void 0 : _a.includes('yfm-tabs-vertical');
|
|
12
|
+
stack.push({ vertical });
|
|
13
|
+
if (vertical)
|
|
14
|
+
token.type = prefix + token.type;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
case 'tabs_close': {
|
|
18
|
+
const item = stack.pop();
|
|
19
|
+
if (item === null || item === void 0 ? void 0 : item.vertical)
|
|
20
|
+
token.type = prefix + token.type;
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
case 'tab_open': {
|
|
24
|
+
const item = stack.at(-1);
|
|
25
|
+
if (item === null || item === void 0 ? void 0 : item.vertical) {
|
|
26
|
+
// --> TODO: remove after updating to tabs-extension v^3.4.0
|
|
27
|
+
const isInput = token.tag === 'input';
|
|
28
|
+
if (isInput)
|
|
29
|
+
token.type = 'tab-input';
|
|
30
|
+
// <--
|
|
31
|
+
token.type = prefix + token.type;
|
|
32
|
+
}
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
case 'tab_close': {
|
|
36
|
+
const item = stack.at(-1);
|
|
37
|
+
if (item === null || item === void 0 ? void 0 : item.vertical) {
|
|
38
|
+
token.type = prefix + token.type;
|
|
39
|
+
// --> TODO: remove after updating to tabs-extension v^3.4.0
|
|
40
|
+
tabCloseIndexes.push(state.tokens.indexOf(token));
|
|
41
|
+
// <--
|
|
42
|
+
}
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case 'tab-input':
|
|
46
|
+
case 'tab-label_open':
|
|
47
|
+
case 'tab-label_close': {
|
|
48
|
+
const item = stack.at(-1);
|
|
49
|
+
if (item === null || item === void 0 ? void 0 : item.vertical) {
|
|
50
|
+
token.type = prefix + token.type;
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
// --> TODO: remove after updating to tabs-extension v^3.4.0
|
|
55
|
+
case 'label_open': {
|
|
56
|
+
const tokenIndex = state.tokens.indexOf(token);
|
|
57
|
+
const prevToken = tokenIndex > 0 && state.tokens.at(tokenIndex - 1);
|
|
58
|
+
if (prevToken && prevToken.type === 'r-tab-input') {
|
|
59
|
+
token.type = prefix + 'tab-' + token.type;
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
// <--
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// --> TODO: remove after updating to tabs-extension v^3.4.0
|
|
67
|
+
for (const index of tabCloseIndexes.reverse()) {
|
|
68
|
+
if (index === -1)
|
|
69
|
+
continue;
|
|
70
|
+
const labelCloseToken = new state.Token(prefix + 'tab-label_close', 'label', -1);
|
|
71
|
+
state.tokens.splice(index, 0, labelCloseToken);
|
|
72
|
+
}
|
|
73
|
+
// <--
|
|
74
|
+
});
|
|
75
|
+
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { TabsNode } from './const';
|
|
2
2
|
const attrsFromEntries = (token) => (token.attrs ? Object.fromEntries(token.attrs) : {});
|
|
3
3
|
export const parserTokens = {
|
|
4
|
-
[TabsNode.
|
|
5
|
-
name: TabsNode.
|
|
4
|
+
[TabsNode.TabPanel]: {
|
|
5
|
+
name: TabsNode.TabPanel,
|
|
6
6
|
type: 'block',
|
|
7
7
|
getAttrs: attrsFromEntries,
|
|
8
8
|
},
|
|
9
|
-
[TabsNode.
|
|
10
|
-
name: TabsNode.
|
|
9
|
+
[TabsNode.Tab]: {
|
|
10
|
+
name: TabsNode.Tab,
|
|
11
11
|
type: 'block',
|
|
12
12
|
getAttrs: attrsFromEntries,
|
|
13
13
|
},
|
|
@@ -21,4 +21,24 @@ export const parserTokens = {
|
|
|
21
21
|
type: 'block',
|
|
22
22
|
getAttrs: attrsFromEntries,
|
|
23
23
|
},
|
|
24
|
+
[TabsNode.RadioTabs]: {
|
|
25
|
+
name: TabsNode.RadioTabs,
|
|
26
|
+
type: 'block',
|
|
27
|
+
getAttrs: attrsFromEntries,
|
|
28
|
+
},
|
|
29
|
+
[TabsNode.RadioTab]: {
|
|
30
|
+
name: TabsNode.RadioTab,
|
|
31
|
+
type: 'block',
|
|
32
|
+
getAttrs: attrsFromEntries,
|
|
33
|
+
},
|
|
34
|
+
[TabsNode.RadioTabInput]: {
|
|
35
|
+
name: TabsNode.RadioTabInput,
|
|
36
|
+
type: 'node',
|
|
37
|
+
getAttrs: attrsFromEntries,
|
|
38
|
+
},
|
|
39
|
+
[TabsNode.RadioTabLabel]: {
|
|
40
|
+
name: TabsNode.RadioTabLabel,
|
|
41
|
+
type: 'block',
|
|
42
|
+
getAttrs: attrsFromEntries,
|
|
43
|
+
},
|
|
24
44
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { TabAttrs, TabPanelAttrs, TabsAttrs, TabsListAttrs, TabsNode } from './const';
|
|
2
2
|
const DEFAULT_PLACEHOLDERS = {
|
|
3
3
|
TabTitle: 'Tab title',
|
|
4
|
+
RadioTabLabelTitle: 'Radio title',
|
|
4
5
|
};
|
|
5
6
|
export const getSchemaSpecs = (opts, placeholder) => {
|
|
6
|
-
var _a, _b;
|
|
7
|
+
var _a, _b, _c;
|
|
7
8
|
return ({
|
|
8
9
|
[TabsNode.Tab]: {
|
|
9
10
|
attrs: {
|
|
@@ -79,5 +80,69 @@ export const getSchemaSpecs = (opts, placeholder) => {
|
|
|
79
80
|
allowSelection: false,
|
|
80
81
|
complex: 'inner',
|
|
81
82
|
},
|
|
83
|
+
[TabsNode.RadioTabs]: {
|
|
84
|
+
attrs: {
|
|
85
|
+
[TabsAttrs.class]: { default: 'yfm-tabs yfm-tabs-vertical' },
|
|
86
|
+
[TabsAttrs.dataDiplodocGroup]: { default: 'unknown' },
|
|
87
|
+
},
|
|
88
|
+
content: `(${TabsNode.RadioTab} ${TabsNode.TabPanel})+`,
|
|
89
|
+
group: 'block',
|
|
90
|
+
toDOM(node) {
|
|
91
|
+
return ['div', node.attrs, 0];
|
|
92
|
+
},
|
|
93
|
+
complex: 'root',
|
|
94
|
+
},
|
|
95
|
+
[TabsNode.RadioTab]: {
|
|
96
|
+
attrs: {
|
|
97
|
+
[TabAttrs.id]: { default: null },
|
|
98
|
+
[TabAttrs.class]: { default: 'yfm-tab yfm-vertical-tab' },
|
|
99
|
+
[TabAttrs.role]: { default: 'unknown' },
|
|
100
|
+
[TabAttrs.ariaControls]: { default: 'unknown' },
|
|
101
|
+
[TabAttrs.ariaSelected]: { default: 'unknown' },
|
|
102
|
+
[TabAttrs.tabindex]: { default: 'unknown' },
|
|
103
|
+
[TabAttrs.dataDiplodocKey]: { default: 'unknown' },
|
|
104
|
+
[TabAttrs.dataDiplodocid]: { default: 'unknown' },
|
|
105
|
+
[TabAttrs.dataDiplodocIsActive]: { default: 'false' },
|
|
106
|
+
[TabAttrs.dataDiplodocVerticalTab]: { default: 'true' },
|
|
107
|
+
},
|
|
108
|
+
content: `${TabsNode.RadioTabInput} ${TabsNode.RadioTabLabel}`,
|
|
109
|
+
group: 'block',
|
|
110
|
+
toDOM(node) {
|
|
111
|
+
return ['div', node.attrs, 0];
|
|
112
|
+
},
|
|
113
|
+
selectable: false,
|
|
114
|
+
allowSelection: false,
|
|
115
|
+
complex: 'inner',
|
|
116
|
+
},
|
|
117
|
+
[TabsNode.RadioTabInput]: {
|
|
118
|
+
attrs: {
|
|
119
|
+
[TabAttrs.class]: { default: 'radio' },
|
|
120
|
+
type: { default: 'radio' },
|
|
121
|
+
checked: { default: null },
|
|
122
|
+
},
|
|
123
|
+
group: 'block',
|
|
124
|
+
toDOM(node) {
|
|
125
|
+
return ['input', node.attrs];
|
|
126
|
+
},
|
|
127
|
+
selectable: false,
|
|
128
|
+
allowSelection: false,
|
|
129
|
+
complex: 'leaf',
|
|
130
|
+
},
|
|
131
|
+
[TabsNode.RadioTabLabel]: {
|
|
132
|
+
attrs: {},
|
|
133
|
+
marks: '',
|
|
134
|
+
content: 'text*',
|
|
135
|
+
group: 'block',
|
|
136
|
+
toDOM(node) {
|
|
137
|
+
return ['label', node.attrs, 0];
|
|
138
|
+
},
|
|
139
|
+
placeholder: {
|
|
140
|
+
content: (_c = placeholder === null || placeholder === void 0 ? void 0 : placeholder[TabsNode.RadioTab]) !== null && _c !== void 0 ? _c : DEFAULT_PLACEHOLDERS.RadioTabLabelTitle,
|
|
141
|
+
alwaysVisible: true,
|
|
142
|
+
},
|
|
143
|
+
selectable: false,
|
|
144
|
+
allowSelection: false,
|
|
145
|
+
complex: 'leaf',
|
|
146
|
+
},
|
|
82
147
|
});
|
|
83
148
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getChildrenOfNode } from '../../../../utils/nodes';
|
|
1
2
|
import { getPlaceholderContent } from '../../../../utils/placeholder';
|
|
2
3
|
import { TabsNode } from './const';
|
|
3
4
|
export const serializerTokens = {
|
|
@@ -29,4 +30,31 @@ export const serializerTokens = {
|
|
|
29
30
|
[TabsNode.TabsList]: (state, node) => {
|
|
30
31
|
state.renderList(node, ' ', () => (node.attrs.bullet || '-') + ' ');
|
|
31
32
|
},
|
|
33
|
+
[TabsNode.RadioTabs]: (state, node) => {
|
|
34
|
+
state.write('{% list tabs radio %}');
|
|
35
|
+
state.write('\n');
|
|
36
|
+
state.write('\n');
|
|
37
|
+
const children = getChildrenOfNode(node);
|
|
38
|
+
for (let i = 0; i < children.length; i++) {
|
|
39
|
+
const child = children[i];
|
|
40
|
+
if (child.node.type.name !== TabsNode.RadioTab)
|
|
41
|
+
continue;
|
|
42
|
+
state.write('- ' + (child.node.textContent || getPlaceholderContent(child.node.lastChild)));
|
|
43
|
+
state.write('\n');
|
|
44
|
+
state.write('\n');
|
|
45
|
+
const nextChild = children[i + 1];
|
|
46
|
+
if (nextChild.node.type.name !== TabsNode.TabPanel)
|
|
47
|
+
continue;
|
|
48
|
+
state.renderList(nextChild.node, ' ', () => ' ');
|
|
49
|
+
}
|
|
50
|
+
state.write('{% endlist %}');
|
|
51
|
+
state.closeBlock(node);
|
|
52
|
+
},
|
|
53
|
+
[TabsNode.RadioTab]: (state, node) => {
|
|
54
|
+
state.renderInline(node);
|
|
55
|
+
},
|
|
56
|
+
[TabsNode.RadioTabInput]: () => { },
|
|
57
|
+
[TabsNode.RadioTabLabel]: (state, node) => {
|
|
58
|
+
state.renderInline(node);
|
|
59
|
+
},
|
|
32
60
|
};
|
|
@@ -2,13 +2,15 @@ import { chainCommands } from 'prosemirror-commands';
|
|
|
2
2
|
import { YfmTabsSpecs } from './YfmTabsSpecs';
|
|
3
3
|
import { createYfmTabs } from './actions';
|
|
4
4
|
import { dragAutoSwitch, joinBackwardToOpenTab, liftEmptyBlockFromTabPanel, removeTabWhenCursorAtTheStartOfTab, tabEnter, tabPanelArrowDown, } from './plugins';
|
|
5
|
-
import { tabPanelView, tabView } from './views';
|
|
5
|
+
import { tabPanelView, tabView, vtabInputView, vtabView } from './views';
|
|
6
6
|
export { TabsNode, tabType, tabsType, tabsListType, tabPanelType } from './YfmTabsSpecs';
|
|
7
7
|
const actionName = 'toYfmTabs';
|
|
8
8
|
export const YfmTabs = (builder) => {
|
|
9
9
|
builder.use(YfmTabsSpecs, {
|
|
10
10
|
tabView: () => tabView,
|
|
11
11
|
tabPanelView: () => tabPanelView,
|
|
12
|
+
vtabView: () => vtabView,
|
|
13
|
+
vtabInputView: () => vtabInputView,
|
|
12
14
|
});
|
|
13
15
|
builder.addKeymap(() => ({
|
|
14
16
|
Backspace: chainCommands(removeTabWhenCursorAtTheStartOfTab, joinBackwardToOpenTab),
|
|
@@ -2,3 +2,5 @@ import { NodeViewConstructor } from 'prosemirror-view';
|
|
|
2
2
|
import './index.css';
|
|
3
3
|
export declare const tabView: NodeViewConstructor;
|
|
4
4
|
export declare const tabPanelView: NodeViewConstructor;
|
|
5
|
+
export declare const vtabView: NodeViewConstructor;
|
|
6
|
+
export declare const vtabInputView: NodeViewConstructor;
|
|
@@ -10,7 +10,7 @@ const ignoreMutation = (node, view, getPos) => (mutation) => {
|
|
|
10
10
|
mutation.type === 'attributes' &&
|
|
11
11
|
mutation.attributeName) {
|
|
12
12
|
const newAttr = mutation.target.getAttribute(mutation.attributeName);
|
|
13
|
-
view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, Object.assign(Object.assign({}, node.attrs), { [mutation.attributeName]:
|
|
13
|
+
view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, Object.assign(Object.assign({}, node.attrs), { [mutation.attributeName]: newAttr })));
|
|
14
14
|
return true;
|
|
15
15
|
}
|
|
16
16
|
return false;
|
|
@@ -71,6 +71,16 @@ export const tabView = (node, view, getPos) => {
|
|
|
71
71
|
};
|
|
72
72
|
// @ts-expect-error
|
|
73
73
|
export const tabPanelView = (node, view, getPos) => ({
|
|
74
|
-
//
|
|
74
|
+
// FIXME: ignore mutation and don't rerender node when yfm.js switch tab
|
|
75
|
+
ignoreMutation: ignoreMutation(node, view, getPos),
|
|
76
|
+
});
|
|
77
|
+
// @ts-expect-error
|
|
78
|
+
export const vtabView = (node, view, getPos) => ({
|
|
79
|
+
// FIXME: ignore mutation and don't rerender node when yfm.js switch tab
|
|
80
|
+
ignoreMutation: ignoreMutation(node, view, getPos),
|
|
81
|
+
});
|
|
82
|
+
// @ts-expect-error
|
|
83
|
+
export const vtabInputView = (node, view, getPos) => ({
|
|
84
|
+
// FIXME: ignore mutation and don't rerender node when yfm.js switch tab
|
|
75
85
|
ignoreMutation: ignoreMutation(node, view, getPos),
|
|
76
86
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { autocompletion } from '@codemirror/autocomplete';
|
|
2
|
-
import { defaultKeymap, history, historyKeymap, indentWithTab, insertTab, } from '@codemirror/commands';
|
|
2
|
+
import { defaultKeymap, history, historyKeymap, indentWithTab, insertNewlineKeepIndent, insertTab, } from '@codemirror/commands';
|
|
3
3
|
import { syntaxHighlighting } from '@codemirror/language';
|
|
4
4
|
import { EditorView, keymap, placeholder } from '@codemirror/view';
|
|
5
5
|
import { ActionName } from '../../bundle/config/action-names';
|
|
@@ -51,6 +51,10 @@ export function createCodemirror(params) {
|
|
|
51
51
|
},
|
|
52
52
|
},
|
|
53
53
|
{ key: 'Tab', preventDefault: true, run: insertTab },
|
|
54
|
+
{
|
|
55
|
+
key: 'Enter',
|
|
56
|
+
shift: insertNewlineKeepIndent,
|
|
57
|
+
},
|
|
54
58
|
indentWithTab,
|
|
55
59
|
...defaultKeymap,
|
|
56
60
|
...(disabledExtensions.history ? [] : historyKeymap),
|
package/build/esm/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** During build process, the current version will be injected here */
|
|
2
|
-
export const VERSION = typeof '13.
|
|
2
|
+
export const VERSION = typeof '13.21.0' !== 'undefined' ? '13.21.0' : 'unknown';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/markdown-editor",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.21.0",
|
|
4
4
|
"description": "Markdown wysiwyg and markup editor",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
"@codemirror/language": "6.10.1",
|
|
166
166
|
"@codemirror/search": "6.5.6",
|
|
167
167
|
"@codemirror/state": "6.4.1",
|
|
168
|
-
"@codemirror/view": "6.
|
|
168
|
+
"@codemirror/view": "6.28.0",
|
|
169
169
|
"@gravity-ui/i18n": "^1.1.0",
|
|
170
170
|
"@gravity-ui/icons": "^2.10.0",
|
|
171
171
|
"@lezer/highlight": "1.2.0",
|