UNPKG

4.69 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _slate = require('slate');
8
9var _slateSchemaViolations = require('slate-schema-violations');
10
11var _immutable = require('immutable');
12
13var _utils = require('../utils');
14
15function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
16
17/**
18 * Create a schema definition with rules to normalize code blocks
19 */
20function schema(opts) {
21 var _blocks;
22
23 var baseSchema = {
24 blocks: (_blocks = {}, _defineProperty(_blocks, opts.containerType, {
25 nodes: [{ types: [opts.lineType] }],
26 normalize: function normalize(change, violation, context) {
27 switch (violation) {
28 case _slateSchemaViolations.CHILD_INVALID:
29 case _slateSchemaViolations.CHILD_TYPE_INVALID:
30 return onlyLine(opts, change, context);
31 default:
32 return undefined;
33 }
34 }
35 }), _defineProperty(_blocks, opts.lineType, {
36 nodes: [{ objects: ['text'], min: 1 }],
37 parent: { types: [opts.containerType] },
38 normalize: function normalize(change, violation, context) {
39 switch (violation) {
40 // This constant does not exist yet in
41 // official Slate, but exists in GitBook's
42 // fork. Until the PR is merged, we accept both
43 // https://github.com/ianstormtaylor/slate/pull/1842
44 case _slateSchemaViolations.PARENT_INVALID:
45 case _slateSchemaViolations.PARENT_TYPE_INVALID:
46 return noOrphanLine(opts, change, context);
47 default:
48 return undefined;
49 }
50 }
51 }), _blocks)
52 };
53
54 if (!opts.allowMarks) {
55 baseSchema.blocks[opts.lineType].marks = [];
56 }
57
58 return baseSchema;
59}
60
61/**
62 * Return a list of group of nodes matching the given filter.
63 */
64function getSuccessiveNodes(nodes, match) {
65 var nonLines = nodes.takeUntil(match);
66 var afterNonLines = nodes.skip(nonLines.size);
67 if (afterNonLines.isEmpty()) {
68 return (0, _immutable.List)();
69 }
70
71 var firstGroup = afterNonLines.takeWhile(match);
72 var restOfNodes = afterNonLines.skip(firstGroup.size);
73
74 return (0, _immutable.List)([firstGroup]).concat(getSuccessiveNodes(restOfNodes, match));
75}
76
77/**
78 * A rule that ensure code blocks only contain lines of code, and no marks
79 */
80function onlyLine(opts, change, context) {
81 var isNotLine = function isNotLine(n) {
82 return n.type !== opts.lineType;
83 };
84 var nonLineGroups = getSuccessiveNodes(context.node.nodes, isNotLine);
85
86 nonLineGroups.filter(function (group) {
87 return !group.isEmpty();
88 }).forEach(function (nonLineGroup) {
89 // Convert text to code lines
90 var text = nonLineGroup.map(function (n) {
91 return n.text;
92 }).join('');
93 var codeLines = (0, _utils.deserializeCode)(opts, text).nodes;
94
95 // Insert them in place of the invalid node
96 var first = nonLineGroup.first();
97 var parent = change.value.document.getParent(first.key);
98 var invalidNodeIndex = parent.nodes.indexOf(first);
99
100 codeLines.forEach(function (codeLine, index) {
101 change.insertNodeByKey(parent.key, invalidNodeIndex + index, codeLine, {
102 normalize: false
103 });
104 });
105
106 // Remove the block
107 nonLineGroup.forEach(function (n) {
108 return change.removeNodeByKey(n.key, { normalize: false });
109 });
110 });
111
112 return change;
113}
114
115/**
116 * A rule that ensure code lines are always children
117 * of a code block.
118 */
119function noOrphanLine(opts, change, context) {
120 var parent = context.parent;
121
122
123 var isLine = function isLine(n) {
124 return n.type === opts.lineType;
125 };
126
127 var linesGroup = getSuccessiveNodes(parent.nodes, isLine);
128
129 linesGroup.forEach(function (group) {
130 var container = _slate.Block.create({ type: opts.containerType, nodes: [] });
131 var firstLineIndex = parent.nodes.indexOf(group.first());
132
133 change.insertNodeByKey(parent.key, firstLineIndex, container, {
134 normalize: false
135 });
136
137 group.forEach(function (line, index) {
138 return change.moveNodeByKey(line.key, container.key, index, {
139 normalize: false
140 });
141 });
142 });
143}
144
145exports.default = schema;
\No newline at end of file