Skip to content

Commit 6566d78

Browse files
authored
feat!: content node for yfm note (#161)
1 parent d36c302 commit 6566d78

File tree

10 files changed

+145
-22
lines changed

10 files changed

+145
-22
lines changed

package-lock.json

Lines changed: 83 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
"tslib": "^2.3.1"
6666
},
6767
"devDependencies": {
68-
"@diplodoc/transform": "4.2.1",
68+
"@diplodoc/transform": "4.5.0",
6969
"@gravity-ui/components": "2.0.0",
7070
"@gravity-ui/eslint-config": "1.0.2",
7171
"@gravity-ui/prettier-config": "1.0.1",
@@ -111,7 +111,7 @@
111111
"typescript": "^4.5.2"
112112
},
113113
"peerDependencies": {
114-
"@diplodoc/transform": "^4.0.0",
114+
"@diplodoc/transform": "^4.5.0",
115115
"@gravity-ui/components": "^2.0.0",
116116
"@gravity-ui/uikit": "^5.0.0",
117117
"lodash": "^4.17.20",

src/extensions/yfm/YfmNote/YfmNote.test.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const {schema, parser, serializer} = new ExtensionsManager({
2525
.use(ImageSpecs),
2626
}).buildDeps();
2727

28-
const {doc, p, i, bq, img, note, noteTitle} = builders(schema, {
28+
const {doc, p, i, bq, img, note, noteTitle, noteContent} = builders(schema, {
2929
doc: {nodeType: BaseNode.Doc},
3030
p: {nodeType: BaseNode.Paragraph},
3131
i: {markType: italicMarkName},
@@ -37,7 +37,8 @@ const {doc, p, i, bq, img, note, noteTitle} = builders(schema, {
3737
[NoteAttrs.Class]: 'yfm-note yfm-accent-info',
3838
},
3939
noteTitle: {nodeType: NoteNode.NoteTitle},
40-
}) as PMTestBuilderResult<'doc' | 'p' | 'bq' | 'img' | 'note' | 'noteTitle', 'i'>;
40+
noteContent: {nodeType: NoteNode.NoteContent},
41+
}) as PMTestBuilderResult<'doc' | 'p' | 'bq' | 'img' | 'note' | 'noteTitle' | 'noteContent', 'i'>;
4142

4243
const {same} = createMarkupChecker({parser, serializer});
4344

@@ -53,7 +54,10 @@ note content 2
5354
{% endnote %}
5455
`.trim();
5556

56-
same(markup, doc(note(noteTitle('note title'), p('note content'), p('note content 2'))));
57+
same(
58+
markup,
59+
doc(note(noteTitle('note title'), noteContent(p('note content'), p('note content 2')))),
60+
);
5761
});
5862

5963
it('should parse nested yfm-notes', () => {
@@ -71,7 +75,12 @@ note content
7175

7276
same(
7377
markup,
74-
doc(note(noteTitle('note title'), note(noteTitle('note title 2'), p('note content')))),
78+
doc(
79+
note(
80+
noteTitle('note title'),
81+
noteContent(note(noteTitle('note title 2'), noteContent(p('note content')))),
82+
),
83+
),
7584
);
7685
});
7786

@@ -84,7 +93,7 @@ note content
8493
> {% endnote %}
8594
`.trim();
8695

87-
same(markup, doc(bq(note(noteTitle('note title'), p('note content')))));
96+
same(markup, doc(bq(note(noteTitle('note title'), noteContent(p('note content'))))));
8897
});
8998

9099
it('should parse yfm-note with inline markup in note title', () => {
@@ -96,7 +105,7 @@ note content
96105
{% endnote %}
97106
`.trim();
98107

99-
same(markup, doc(note(noteTitle(i('note italic title')), p('note content'))));
108+
same(markup, doc(note(noteTitle(i('note italic title')), noteContent(p('note content')))));
100109
});
101110

102111
it('should parse yfm-note with inline node in note title', () => {
@@ -118,7 +127,7 @@ note content
118127
[ImageAttr.Alt]: 'img',
119128
}),
120129
),
121-
p('note content'),
130+
noteContent(p('note content')),
122131
),
123132
),
124133
);
@@ -132,7 +141,7 @@ note content
132141
'<p class="yfm-note-title">YfmNote title</p>' +
133142
'<p>YfmNote content</p>' +
134143
'</div></div>',
135-
doc(note(noteTitle('YfmNote title'), p('YfmNote content'))),
144+
doc(note(noteTitle('YfmNote title'), noteContent(p('YfmNote content')))),
136145
);
137146
});
138147
});

src/extensions/yfm/YfmNote/YfmNoteSpecs/const.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export enum NoteNode {
22
Note = 'yfm_note',
33
NoteTitle = 'yfm_note_title',
4+
NoteContent = 'yfm_note_content',
45
}
56

67
export enum NoteAttrs {

src/extensions/yfm/YfmNote/YfmNoteSpecs/fromYfm.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ export const fromYfm: Record<NoteNode, ParserToken> = {
88
getAttrs: (token) => (token.attrs ? Object.fromEntries(token.attrs) : {}),
99
},
1010
[NoteNode.NoteTitle]: {name: NoteNode.NoteTitle, type: 'block'},
11+
[NoteNode.NoteContent]: {name: NoteNode.NoteContent, type: 'block'},
1112
};

src/extensions/yfm/YfmNote/YfmNoteSpecs/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,12 @@ export const YfmNoteSpecs: ExtensionAuto<YfmNoteSpecsOptions> = (builder, opts)
3636
fromYfm: {
3737
tokenSpec: fromYfm[NoteNode.NoteTitle],
3838
},
39+
}))
40+
.addNode(NoteNode.NoteContent, () => ({
41+
spec: spec[NoteNode.NoteContent],
42+
toYfm: toYfm[NoteNode.NoteContent],
43+
fromYfm: {
44+
tokenSpec: fromYfm[NoteNode.NoteContent],
45+
},
3946
}));
4047
};

src/extensions/yfm/YfmNote/YfmNoteSpecs/spec.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {NoteAttrs, NoteNode} from './const';
44
import {PlaceholderOptions} from '../../../../utils/placeholder';
55

66
const DEFAULT_TITLE_PLACEHOLDER = 'Note';
7+
const DEFAULT_CONTENT_PLACEHOLDER = 'Note content';
78

89
export const getSpec = (
910
opts?: YfmNoteSpecsOptions,
@@ -14,7 +15,7 @@ export const getSpec = (
1415
[NoteAttrs.Class]: {default: 'yfm-note yfm-accent-info'},
1516
[NoteAttrs.Type]: {default: 'info'},
1617
},
17-
content: `${NoteNode.NoteTitle} block+`,
18+
content: `${NoteNode.NoteTitle} ${NoteNode.NoteContent}`,
1819
group: 'block yfm-note',
1920
parseDOM: [
2021
{
@@ -57,4 +58,24 @@ export const getSpec = (
5758
},
5859
complex: 'leaf',
5960
},
61+
[NoteNode.NoteContent]: {
62+
content: '(block | paragraph)+',
63+
group: 'block yfm-note',
64+
parseDOM: [
65+
{
66+
tag: 'div.yfm-note-content',
67+
priority: 100,
68+
},
69+
],
70+
toDOM() {
71+
return ['div', {class: 'yfm-note-content'}, 0];
72+
},
73+
selectable: false,
74+
allowSelection: false,
75+
placeholder: {
76+
content: placeholder?.[NoteNode.NoteContent] ?? DEFAULT_CONTENT_PLACEHOLDER,
77+
alwaysVisible: true,
78+
},
79+
complex: 'leaf',
80+
},
6081
});

src/extensions/yfm/YfmNote/YfmNoteSpecs/toYfm.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {isNodeEmpty} from '../../../../utils/nodes';
12
import type {SerializerNodeToken} from '../../../../core';
23
import {getPlaceholderContent} from '../../../../utils/placeholder';
34
import {NoteAttrs, NoteNode} from './const';
@@ -23,4 +24,9 @@ export const toYfm: Record<NoteNode, SerializerNodeToken> = {
2324
state.write('\n');
2425
state.closeBlock();
2526
},
27+
28+
[NoteNode.NoteContent]: (state, node) => {
29+
if (!isNodeEmpty(node)) state.renderInline(node);
30+
else state.write(getPlaceholderContent(node) + '\n\n');
31+
},
2632
};

src/extensions/yfm/YfmNote/YfmNoteSpecs/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ import {NoteNode} from './const';
33

44
export const noteType = nodeTypeFactory(NoteNode.Note);
55
export const noteTitleType = nodeTypeFactory(NoteNode.NoteTitle);
6+
export const noteContentType = nodeTypeFactory(NoteNode.NoteContent);

src/extensions/yfm/YfmNote/actions/toYfmNote.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {Command, EditorState} from 'prosemirror-state';
33
import {findParentNodeOfType, hasParentNodeOfType} from 'prosemirror-utils';
44
import type {ActionSpec} from '../../../../core';
55
import {NoteAttrs} from '../const';
6-
import {noteTitleType, noteType} from '../utils';
6+
import {noteContentType, noteTitleType, noteType} from '../utils';
77

88
export function isInsideYfmNote(state: EditorState) {
99
return hasParentNodeOfType(noteType(state.schema))(state.selection);
@@ -17,7 +17,10 @@ const createYfmNoteNode = (schema: Schema) => (type: YfmNoteType, content: Node
1717
[NoteAttrs.Class]: `yfm-note yfm-accent-${type}`,
1818
[NoteAttrs.Type]: type,
1919
},
20-
[noteTitleType(schema).createAndFill()!].concat(content),
20+
[
21+
noteTitleType(schema).createAndFill()!,
22+
noteContentType(schema).createAndFill({}, content)!,
23+
],
2124
);
2225
};
2326

0 commit comments

Comments
 (0)