@dxos/react-ui-editor 0.4.10-main.0302e13 → 0.4.10-main.308cc0e
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/dist/lib/browser/index.mjs +599 -636
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts +1 -1
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -1
- package/package.json +23 -23
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -12
- package/src/extensions/markdown/decorate.ts +62 -90
- package/src/extensions/markdown/formatting.ts +35 -42
- package/src/extensions/markdown/highlight.ts +1 -3
- package/src/extensions/markdown/table.ts +6 -7
|
@@ -81,7 +81,6 @@ const horizontalRule = Decoration.replace({ widget: new HorizontalRuleWidget() }
|
|
|
81
81
|
const checkedTask = Decoration.replace({ widget: new CheckboxWidget(true) });
|
|
82
82
|
const uncheckedTask = Decoration.replace({ widget: new CheckboxWidget(false) });
|
|
83
83
|
|
|
84
|
-
// Check if cursor is inside text.
|
|
85
84
|
const editingRange = (state: EditorState, range: { from: number; to: number }, focus: boolean) => {
|
|
86
85
|
const {
|
|
87
86
|
readOnly,
|
|
@@ -104,103 +103,76 @@ const buildDecorations = (view: EditorView, options: DecorateOptions, focus: boo
|
|
|
104
103
|
from,
|
|
105
104
|
to,
|
|
106
105
|
enter: (node) => {
|
|
107
|
-
|
|
106
|
+
if (node.name === 'FencedCode') {
|
|
107
|
+
const editing = editingRange(state, node, focus);
|
|
108
108
|
// FencedCode > CodeMark > [CodeInfo] > CodeText > CodeMark
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
block.from,
|
|
122
|
-
block.from,
|
|
123
|
-
first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine,
|
|
124
|
-
);
|
|
125
|
-
if (!editing && (first || last)) {
|
|
126
|
-
atomicDeco.add(block.from, block.to, hide);
|
|
127
|
-
}
|
|
109
|
+
for (const block of view.viewportLineBlocks) {
|
|
110
|
+
if (block.to < node.from) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (block.from > node.to) {
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
const first = block.from <= node.from;
|
|
117
|
+
const last = block.to >= node.to && /^(\s>)*```$/.test(state.doc.sliceString(block.from, block.to));
|
|
118
|
+
deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
|
|
119
|
+
if (!editing && (first || last)) {
|
|
120
|
+
atomicDeco.add(block.from, block.to, hide);
|
|
128
121
|
}
|
|
129
|
-
return false;
|
|
130
122
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
123
|
+
return false;
|
|
124
|
+
} else if (node.name === 'Link') {
|
|
125
|
+
const marks = node.node.getChildren('LinkMark');
|
|
126
|
+
const urlNode = node.node.getChild('URL');
|
|
127
|
+
const editing = editingRange(state, node, focus);
|
|
128
|
+
if (urlNode && marks.length >= 2) {
|
|
129
|
+
const url = state.sliceDoc(urlNode.from, urlNode.to);
|
|
130
|
+
if (!editing) {
|
|
131
|
+
atomicDeco.add(node.from, marks[0].to, hide);
|
|
132
|
+
}
|
|
133
|
+
deco.add(
|
|
134
|
+
marks[0].to,
|
|
135
|
+
marks[1].from,
|
|
136
|
+
Decoration.mark({
|
|
137
|
+
tagName: 'a',
|
|
138
|
+
attributes: {
|
|
139
|
+
class: 'cm-link',
|
|
140
|
+
href: url,
|
|
141
|
+
rel: 'noreferrer',
|
|
142
|
+
target: '_blank',
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
145
|
+
);
|
|
146
|
+
if (!editing) {
|
|
147
|
+
atomicDeco.add(
|
|
143
148
|
marks[1].from,
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
href: url,
|
|
149
|
-
rel: 'noreferrer',
|
|
150
|
-
target: '_blank',
|
|
151
|
-
},
|
|
152
|
-
}),
|
|
149
|
+
node.to,
|
|
150
|
+
options.renderLinkButton
|
|
151
|
+
? Decoration.replace({ widget: new LinkButton(url, options.renderLinkButton) })
|
|
152
|
+
: hide,
|
|
153
153
|
);
|
|
154
|
-
if (!editing) {
|
|
155
|
-
atomicDeco.add(
|
|
156
|
-
marks[1].from,
|
|
157
|
-
node.to,
|
|
158
|
-
options.renderLinkButton
|
|
159
|
-
? Decoration.replace({ widget: new LinkButton(url, options.renderLinkButton) })
|
|
160
|
-
: hide,
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
break;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
case 'HeaderMark': {
|
|
168
|
-
const parent = node.node.parent!;
|
|
169
|
-
if (/^ATX/.test(parent.name) && !editingRange(state, state.doc.lineAt(node.from), focus)) {
|
|
170
|
-
const next = state.doc.sliceString(node.to, node.to + 1);
|
|
171
|
-
atomicDeco.add(node.from, node.to + (next === ' ' ? 1 : 0), hide);
|
|
172
154
|
}
|
|
173
|
-
break;
|
|
174
155
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
break;
|
|
156
|
+
} else if (node.name === 'HeaderMark') {
|
|
157
|
+
const parent = node.node.parent!;
|
|
158
|
+
if (/^ATX/.test(parent.name) && !editingRange(state, state.doc.lineAt(node.from), focus)) {
|
|
159
|
+
const next = state.doc.sliceString(node.to, node.to + 1);
|
|
160
|
+
atomicDeco.add(node.from, node.to + (next === ' ' ? 1 : 0), hide);
|
|
181
161
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === 'x';
|
|
186
|
-
atomicDeco.add(node.from - 2, node.from - 1, Decoration.mark({ class: 'cm-task' }));
|
|
187
|
-
atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
|
|
188
|
-
}
|
|
189
|
-
break;
|
|
162
|
+
} else if (node.name === 'HorizontalRule') {
|
|
163
|
+
if (!editingRange(state, node, focus)) {
|
|
164
|
+
deco.add(node.from, node.to, horizontalRule);
|
|
190
165
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
166
|
+
} else if (node.name === 'TaskMarker') {
|
|
167
|
+
// Check if cursor is inside text.
|
|
168
|
+
if (!editingRange(state, node, focus)) {
|
|
169
|
+
const checked = state.doc.sliceString(node.from + 1, node.to - 1) === 'x';
|
|
170
|
+
atomicDeco.add(node.from - 2, node.from - 1, Decoration.mark({ class: 'cm-task' }));
|
|
171
|
+
atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
|
|
196
172
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (!editingRange(state, node.node.parent!, focus)) {
|
|
201
|
-
atomicDeco.add(node.from, node.to, hide);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
173
|
+
} else if (MarksByParent.has(node.name)) {
|
|
174
|
+
if (!editingRange(state, node.node.parent!, focus)) {
|
|
175
|
+
atomicDeco.add(node.from, node.to, hide);
|
|
204
176
|
}
|
|
205
177
|
}
|
|
206
178
|
},
|
|
@@ -252,6 +224,8 @@ export const decorateMarkdown = (options: DecorateOptions = {}) => {
|
|
|
252
224
|
}
|
|
253
225
|
}
|
|
254
226
|
|
|
227
|
+
// TODO(burdon): BUG: If the cursor is at the end of a link at the end of a line,
|
|
228
|
+
// the cursor will float in space or be in the wrong position after the decoration is applied.
|
|
255
229
|
scheduleUpdate(view: EditorView) {
|
|
256
230
|
this.clearUpdate();
|
|
257
231
|
this.pendingUpdate = setTimeout(() => {
|
|
@@ -330,6 +304,4 @@ const formattingStyles = EditorView.baseTheme({
|
|
|
330
304
|
marginLeft: '4px',
|
|
331
305
|
marginRight: '4px',
|
|
332
306
|
},
|
|
333
|
-
|
|
334
|
-
// '& .cm-list-item > span:nth-child(2)': {},
|
|
335
307
|
});
|
|
@@ -83,8 +83,9 @@ export enum List {
|
|
|
83
83
|
// Headings
|
|
84
84
|
//
|
|
85
85
|
|
|
86
|
-
export const setHeading =
|
|
87
|
-
|
|
86
|
+
export const setHeading =
|
|
87
|
+
(level: number): StateCommand =>
|
|
88
|
+
({ state, dispatch }) => {
|
|
88
89
|
const {
|
|
89
90
|
selection: { ranges },
|
|
90
91
|
doc,
|
|
@@ -150,14 +151,14 @@ export const setHeading = (level: number): StateCommand => {
|
|
|
150
151
|
);
|
|
151
152
|
return true;
|
|
152
153
|
};
|
|
153
|
-
};
|
|
154
154
|
|
|
155
155
|
//
|
|
156
156
|
// Styles
|
|
157
157
|
//
|
|
158
158
|
|
|
159
|
-
export const setStyle =
|
|
160
|
-
|
|
159
|
+
export const setStyle =
|
|
160
|
+
(type: Inline, enable: boolean): StateCommand =>
|
|
161
|
+
({ state, dispatch }) => {
|
|
161
162
|
const marker = inlineMarkerText(type);
|
|
162
163
|
const changes = state.changeByRange((range) => {
|
|
163
164
|
// Special case for markers directly around the cursor, which will often not be parsed as valid styling.
|
|
@@ -321,14 +322,14 @@ export const setStyle = (type: Inline, enable: boolean): StateCommand => {
|
|
|
321
322
|
|
|
322
323
|
return true;
|
|
323
324
|
};
|
|
324
|
-
};
|
|
325
325
|
|
|
326
326
|
export const addStyle = (style: Inline): StateCommand => setStyle(style, true);
|
|
327
327
|
|
|
328
328
|
export const removeStyle = (style: Inline): StateCommand => setStyle(style, false);
|
|
329
329
|
|
|
330
|
-
export const toggleStyle =
|
|
331
|
-
|
|
330
|
+
export const toggleStyle =
|
|
331
|
+
(style: Inline): StateCommand =>
|
|
332
|
+
(arg) => {
|
|
332
333
|
const form = getFormatting(arg.state);
|
|
333
334
|
return setStyle(
|
|
334
335
|
style,
|
|
@@ -341,7 +342,6 @@ export const toggleStyle = (style: Inline): StateCommand => {
|
|
|
341
342
|
: !form.code,
|
|
342
343
|
)(arg);
|
|
343
344
|
};
|
|
344
|
-
};
|
|
345
345
|
|
|
346
346
|
export const toggleStrong = toggleStyle(Inline.Strong);
|
|
347
347
|
export const toggleEmphasis = toggleStyle(Inline.Emphasis);
|
|
@@ -469,9 +469,10 @@ export const removeLink: StateCommand = ({ state, dispatch }) => {
|
|
|
469
469
|
return true;
|
|
470
470
|
};
|
|
471
471
|
|
|
472
|
-
// Add link markup around the selection
|
|
473
|
-
export const addLink =
|
|
474
|
-
|
|
472
|
+
// Add link markup around the selection
|
|
473
|
+
export const addLink =
|
|
474
|
+
({ url, image }: { url?: string; image?: boolean } = {}): StateCommand =>
|
|
475
|
+
({ state, dispatch }) => {
|
|
475
476
|
const changes = state.changeByRange((range) => {
|
|
476
477
|
let { from, to } = range;
|
|
477
478
|
const cutStyles: SyntaxNode[] = [];
|
|
@@ -518,7 +519,7 @@ export const addLink = ({ url, image }: { url?: string; image?: boolean } = {}):
|
|
|
518
519
|
}
|
|
519
520
|
|
|
520
521
|
const changes: ChangeSpec[] = [];
|
|
521
|
-
// Some changes must be moved to end of change array so that they are applied in the right order
|
|
522
|
+
// Some changes must be moved to end of change array so that they are applied in the right order
|
|
522
523
|
const changesAfter: ChangeSpec[] = [];
|
|
523
524
|
// Clear existing links.
|
|
524
525
|
removeLinkInner(from, to, changesAfter, state);
|
|
@@ -550,34 +551,28 @@ export const addLink = ({ url, image }: { url?: string; image?: boolean } = {}):
|
|
|
550
551
|
range: EditorSelection.cursor(changeSet.mapPos(to, 1) - cursorOffset - (url ? url.length + 2 : 0)),
|
|
551
552
|
};
|
|
552
553
|
});
|
|
553
|
-
|
|
554
554
|
if (changes.changes.empty) {
|
|
555
555
|
return false;
|
|
556
556
|
}
|
|
557
557
|
|
|
558
|
-
dispatch(
|
|
559
|
-
state.update(changes, {
|
|
560
|
-
userEvent: 'format.link.add',
|
|
561
|
-
scrollIntoView: true,
|
|
562
|
-
}),
|
|
563
|
-
);
|
|
558
|
+
dispatch(state.update(changes, { userEvent: 'format.link.add', scrollIntoView: true }));
|
|
564
559
|
return true;
|
|
565
560
|
};
|
|
566
|
-
};
|
|
567
561
|
|
|
568
562
|
//
|
|
569
563
|
// Lists
|
|
570
564
|
//
|
|
571
565
|
|
|
572
|
-
export const addList =
|
|
573
|
-
|
|
566
|
+
export const addList =
|
|
567
|
+
(type: List): StateCommand =>
|
|
568
|
+
({ state, dispatch }) => {
|
|
574
569
|
let lastBlock = -1;
|
|
575
570
|
let counter = 1;
|
|
576
571
|
let first = true;
|
|
577
572
|
let parentColumn: number | null = null;
|
|
573
|
+
const blocks: { node: SyntaxNode; counter: number; parentColumn: number | null }[] = [];
|
|
578
574
|
|
|
579
575
|
// Scan the syntax tree to locate textblocks that can be wrapped.
|
|
580
|
-
const blocks: { node: SyntaxNode; counter: number; parentColumn: number | null }[] = [];
|
|
581
576
|
for (const { from, to } of state.selection.ranges) {
|
|
582
577
|
syntaxTree(state).iterate({
|
|
583
578
|
from,
|
|
@@ -609,7 +604,6 @@ export const addList = (type: List): StateCommand => {
|
|
|
609
604
|
if (node.from === lastBlock) {
|
|
610
605
|
return;
|
|
611
606
|
}
|
|
612
|
-
|
|
613
607
|
lastBlock = node.from;
|
|
614
608
|
blocks.push({ node: node.node, counter, parentColumn });
|
|
615
609
|
counter++;
|
|
@@ -644,6 +638,7 @@ export const addList = (type: List): StateCommand => {
|
|
|
644
638
|
scrollIntoView: true,
|
|
645
639
|
}),
|
|
646
640
|
);
|
|
641
|
+
|
|
647
642
|
return true;
|
|
648
643
|
}
|
|
649
644
|
|
|
@@ -685,7 +680,7 @@ export const addList = (type: List): StateCommand => {
|
|
|
685
680
|
}
|
|
686
681
|
|
|
687
682
|
changes.push({ from: nodeFrom, insert: mark });
|
|
688
|
-
// Add indentation for the other lines in this block
|
|
683
|
+
// Add indentation for the other lines in this block
|
|
689
684
|
while (line.to < node.to) {
|
|
690
685
|
line = state.doc.lineAt(line.to + 1);
|
|
691
686
|
const open = /^[\s>]*/.exec(line.text)![0].length;
|
|
@@ -705,7 +700,7 @@ export const addList = (type: List): StateCommand => {
|
|
|
705
700
|
renumberListItems(next.firstChild, last.counter + 1, changes, state.doc);
|
|
706
701
|
}
|
|
707
702
|
}
|
|
708
|
-
|
|
703
|
+
|
|
709
704
|
const changeSet = state.changes(changes);
|
|
710
705
|
dispatch(
|
|
711
706
|
state.update({
|
|
@@ -717,10 +712,10 @@ export const addList = (type: List): StateCommand => {
|
|
|
717
712
|
);
|
|
718
713
|
return true;
|
|
719
714
|
};
|
|
720
|
-
};
|
|
721
715
|
|
|
722
|
-
export const removeList =
|
|
723
|
-
|
|
716
|
+
export const removeList =
|
|
717
|
+
(type: List): StateCommand =>
|
|
718
|
+
({ state, dispatch }) => {
|
|
724
719
|
let lastBlock = -1;
|
|
725
720
|
const changes: ChangeSpec[] = [];
|
|
726
721
|
const stack: string[] = [];
|
|
@@ -776,16 +771,15 @@ export const removeList = (type: List): StateCommand => {
|
|
|
776
771
|
dispatch(state.update({ changes, userEvent: 'format.list.remove', scrollIntoView: true }));
|
|
777
772
|
return true;
|
|
778
773
|
};
|
|
779
|
-
};
|
|
780
774
|
|
|
781
|
-
export const toggleList =
|
|
782
|
-
|
|
775
|
+
export const toggleList =
|
|
776
|
+
(type: List): StateCommand =>
|
|
777
|
+
(target) => {
|
|
783
778
|
const formatting = getFormatting(target.state);
|
|
784
779
|
const active =
|
|
785
780
|
formatting.listStyle === (type === List.Bullet ? 'bullet' : type === List.Ordered ? 'ordered' : 'task');
|
|
786
781
|
return (active ? removeList(type) : addList(type))(target);
|
|
787
782
|
};
|
|
788
|
-
};
|
|
789
783
|
|
|
790
784
|
const renumberListItems = (item: SyntaxNode | null, counter: number, changes: ChangeSpec[], doc: Text) => {
|
|
791
785
|
for (; item; item = item.nextSibling) {
|
|
@@ -806,8 +800,9 @@ const renumberListItems = (item: SyntaxNode | null, counter: number, changes: Ch
|
|
|
806
800
|
// Block quotes
|
|
807
801
|
//
|
|
808
802
|
|
|
809
|
-
export const setBlockquote =
|
|
810
|
-
|
|
803
|
+
export const setBlockquote =
|
|
804
|
+
(enable: boolean): StateCommand =>
|
|
805
|
+
({ state, dispatch }) => {
|
|
811
806
|
const lines: Line[] = [];
|
|
812
807
|
let lastBlock = -1;
|
|
813
808
|
for (const { from, to } of state.selection.ranges) {
|
|
@@ -879,7 +874,6 @@ export const setBlockquote = (enable: boolean): StateCommand => {
|
|
|
879
874
|
);
|
|
880
875
|
return true;
|
|
881
876
|
};
|
|
882
|
-
};
|
|
883
877
|
|
|
884
878
|
export const addBlockquote = setBlockquote(true);
|
|
885
879
|
|
|
@@ -950,10 +944,9 @@ export const addCodeblock: StateCommand = (target) => {
|
|
|
950
944
|
};
|
|
951
945
|
|
|
952
946
|
export const removeCodeblock: StateCommand = ({ state, dispatch }) => {
|
|
953
|
-
let lastBlock = -1;
|
|
954
|
-
|
|
955
|
-
// Find all code blocks, remove their markup.
|
|
956
947
|
const changes: ChangeSpec[] = [];
|
|
948
|
+
let lastBlock = -1;
|
|
949
|
+
// Find all code blocks, remove their markup
|
|
957
950
|
for (const { from, to } of state.selection.ranges) {
|
|
958
951
|
syntaxTree(state).iterate({
|
|
959
952
|
from,
|
|
@@ -972,7 +965,7 @@ export const removeCodeblock: StateCommand = ({ state, dispatch }) => {
|
|
|
972
965
|
});
|
|
973
966
|
}
|
|
974
967
|
} else {
|
|
975
|
-
// Indented code block
|
|
968
|
+
// Indented code block
|
|
976
969
|
const column = node.from - firstLine.from;
|
|
977
970
|
for (let line = firstLine; ; line = state.doc.line(line.number + 1)) {
|
|
978
971
|
changes.push({ from: line.from + column - 4, to: line.from + column });
|
|
@@ -1057,7 +1050,7 @@ const Textblocks: { [name: string]: NonNullable<Formatting['blockType']> } = {
|
|
|
1057
1050
|
};
|
|
1058
1051
|
|
|
1059
1052
|
/**
|
|
1060
|
-
* Query
|
|
1053
|
+
* Query an editor state for the active formatting at the selection.
|
|
1061
1054
|
*/
|
|
1062
1055
|
export const getFormatting = (state: EditorState): Formatting => {
|
|
1063
1056
|
// These will track the formatting we've seen so far.
|
|
@@ -183,9 +183,7 @@ export const markdownHighlightStyle = (readonly?: boolean) => {
|
|
|
183
183
|
],
|
|
184
184
|
{
|
|
185
185
|
scope: markdownLanguage,
|
|
186
|
-
all: {
|
|
187
|
-
fontFamily: getToken('fontFamily.body', []).join(','),
|
|
188
|
-
},
|
|
186
|
+
all: { fontFamily: getToken('fontFamily.body', []).join(',') },
|
|
189
187
|
},
|
|
190
188
|
);
|
|
191
189
|
};
|
|
@@ -15,6 +15,7 @@ import { Decoration, EditorView, WidgetType } from '@codemirror/view';
|
|
|
15
15
|
|
|
16
16
|
// TODO(burdon): Snippet to create basic table.
|
|
17
17
|
// https://codemirror.net/docs/ref/#autocomplete.snippet
|
|
18
|
+
|
|
18
19
|
// TODO(burdon): Advanced formatting (left/right/center).
|
|
19
20
|
// TODO(burdon): Editor to auto balance columns.
|
|
20
21
|
|
|
@@ -81,21 +82,19 @@ const update = (state: EditorState, options: TableOptions) => {
|
|
|
81
82
|
});
|
|
82
83
|
|
|
83
84
|
tables.forEach((table) => {
|
|
84
|
-
const
|
|
85
|
-
if (
|
|
85
|
+
const hide = state.readOnly || cursor < table.from || cursor > table.to;
|
|
86
|
+
if (hide) {
|
|
86
87
|
builder.add(
|
|
87
88
|
table.from,
|
|
88
89
|
table.to,
|
|
89
90
|
Decoration.replace({
|
|
90
|
-
block: true,
|
|
91
91
|
widget: new TableWidget(table),
|
|
92
92
|
}),
|
|
93
93
|
);
|
|
94
|
-
} else {
|
|
95
|
-
// Add class for styling.
|
|
96
|
-
// TODO(burdon): Apply to each line?
|
|
97
|
-
builder.add(table.from, table.to, Decoration.mark({ class: 'cm-table' }));
|
|
98
94
|
}
|
|
95
|
+
|
|
96
|
+
// Add class for styling.
|
|
97
|
+
builder.add(table.from, table.to, Decoration.mark({ class: 'cm-table' }));
|
|
99
98
|
});
|
|
100
99
|
|
|
101
100
|
return builder.finish();
|