@block-kit/react 1.0.9 → 1.0.11
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/es/index.d.ts +1 -1
- package/dist/es/index.js +1 -1
- package/dist/es/model/block.js +4 -5
- package/dist/es/model/leaf.js +6 -0
- package/dist/es/model/line.js +7 -18
- package/dist/es/model/portal.js +1 -1
- package/dist/es/preset/isolate.d.ts +1 -1
- package/dist/es/preset/isolate.js +40 -3
- package/dist/es/preset/text.js +2 -14
- package/dist/es/utils/dirty-dom.d.ts +14 -0
- package/dist/es/utils/dirty-dom.js +46 -0
- package/dist/es/utils/event.d.ts +6 -2
- package/dist/es/utils/event.js +7 -5
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +3 -3
- package/dist/lib/model/block.js +5 -6
- package/dist/lib/model/leaf.js +6 -0
- package/dist/lib/model/line.js +8 -19
- package/dist/lib/model/portal.js +2 -2
- package/dist/lib/preset/isolate.d.ts +1 -1
- package/dist/lib/preset/isolate.js +40 -3
- package/dist/lib/preset/text.js +2 -14
- package/dist/lib/utils/dirty-dom.d.ts +14 -0
- package/dist/lib/utils/dirty-dom.js +51 -0
- package/dist/lib/utils/event.d.ts +6 -2
- package/dist/lib/utils/event.js +7 -5
- package/package.json +7 -7
- package/dist/es/utils/is.d.ts +0 -2
- package/dist/es/utils/is.js +0 -12
- package/dist/lib/utils/is.d.ts +0 -2
- package/dist/lib/utils/is.js +0 -16
- /package/dist/es/utils/{dom.d.ts → mount-dom.d.ts} +0 -0
- /package/dist/es/utils/{dom.js → mount-dom.js} +0 -0
- /package/dist/es/utils/{wrapper.d.ts → wrapper-node.d.ts} +0 -0
- /package/dist/es/utils/{wrapper.js → wrapper-node.js} +0 -0
- /package/dist/lib/utils/{dom.d.ts → mount-dom.d.ts} +0 -0
- /package/dist/lib/utils/{dom.js → mount-dom.js} +0 -0
- /package/dist/lib/utils/{wrapper.d.ts → wrapper-node.d.ts} +0 -0
- /package/dist/lib/utils/{wrapper.js → wrapper-node.js} +0 -0
package/dist/es/index.d.ts
CHANGED
|
@@ -15,5 +15,5 @@ export { Isolate } from "./preset/isolate";
|
|
|
15
15
|
export { Text } from "./preset/text";
|
|
16
16
|
export { Void } from "./preset/void";
|
|
17
17
|
export { ZeroSpace } from "./preset/zero";
|
|
18
|
-
export { MountNode } from "./utils/dom";
|
|
19
18
|
export { preventNativeEvent, preventReactEvent } from "./utils/event";
|
|
19
|
+
export { MountNode } from "./utils/mount-dom";
|
package/dist/es/index.js
CHANGED
|
@@ -14,5 +14,5 @@ export { Isolate } from "./preset/isolate";
|
|
|
14
14
|
export { Text } from "./preset/text";
|
|
15
15
|
export { Void } from "./preset/void";
|
|
16
16
|
export { ZeroSpace } from "./preset/zero";
|
|
17
|
-
export { MountNode } from "./utils/dom";
|
|
18
17
|
export { preventNativeEvent, preventReactEvent } from "./utils/event";
|
|
18
|
+
export { MountNode } from "./utils/mount-dom";
|
package/dist/es/model/block.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { BLOCK_ID_KEY, BLOCK_KEY, EDITOR_EVENT, EDITOR_STATE, PLACEHOLDER_KEY, } from "@block-kit/core";
|
|
2
|
+
import { BLOCK_ID_KEY, BLOCK_KEY, EDITOR_EVENT, EDITOR_STATE, isEmptyLine, PLACEHOLDER_KEY, } from "@block-kit/core";
|
|
3
3
|
import { useMemoFn } from "@block-kit/utils/dist/es/hooks";
|
|
4
4
|
import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
5
|
import { EDITOR_TO_WRAP_LINE_KEYS, EDITOR_TO_WRAP_LINE_PLUGINS } from "../plugin/modules/wrap";
|
|
6
|
-
import { isStrictEmptyLine } from "../utils/is";
|
|
7
6
|
import { JSX_TO_STATE } from "../utils/weak-map";
|
|
8
|
-
import { getWrapSymbol } from "../utils/wrapper";
|
|
7
|
+
import { getWrapSymbol } from "../utils/wrapper-node";
|
|
9
8
|
import { LineModel } from "./line";
|
|
10
9
|
/**
|
|
11
10
|
* Block Model
|
|
@@ -92,7 +91,7 @@ const BlockView = props => {
|
|
|
92
91
|
});
|
|
93
92
|
}, [editor, lines]);
|
|
94
93
|
/**
|
|
95
|
-
*
|
|
94
|
+
* 将行节点包装组合 O(N)
|
|
96
95
|
*/
|
|
97
96
|
const children = useMemo(() => {
|
|
98
97
|
const wrapped = [];
|
|
@@ -140,7 +139,7 @@ const BlockView = props => {
|
|
|
140
139
|
}
|
|
141
140
|
return wrapped;
|
|
142
141
|
}, [editor, elements]);
|
|
143
|
-
return (_jsxs("div", { [BLOCK_KEY]: true, [BLOCK_ID_KEY]: state.key, ref: setModel, children: [props.placeholder && lines.length === 1 &&
|
|
142
|
+
return (_jsxs("div", { [BLOCK_KEY]: true, [BLOCK_ID_KEY]: state.key, ref: setModel, children: [props.placeholder && lines.length === 1 && isEmptyLine(lines[0], true) && (_jsx("div", { [PLACEHOLDER_KEY]: true, style: {
|
|
144
143
|
position: "absolute",
|
|
145
144
|
opacity: "0.3",
|
|
146
145
|
userSelect: "none",
|
package/dist/es/model/leaf.js
CHANGED
|
@@ -9,11 +9,17 @@ import { LEAF_TO_TEXT as LT } from "../utils/weak-map";
|
|
|
9
9
|
*/
|
|
10
10
|
const LeafView = props => {
|
|
11
11
|
const { editor, leafState } = props;
|
|
12
|
+
/**
|
|
13
|
+
* 设置叶子 DOM 节点
|
|
14
|
+
*/
|
|
12
15
|
const setModel = (ref) => {
|
|
13
16
|
if (ref) {
|
|
14
17
|
editor.model.setLeafModel(ref, leafState);
|
|
15
18
|
}
|
|
16
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* 处理叶子节点的渲染
|
|
22
|
+
*/
|
|
17
23
|
const runtime = useMemo(() => {
|
|
18
24
|
const text = leafState.getText();
|
|
19
25
|
const context = {
|
package/dist/es/model/line.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { NODE_KEY, PLUGIN_TYPE } from "@block-kit/core";
|
|
3
3
|
import { EOL, EOL_OP } from "@block-kit/delta";
|
|
4
|
-
import { cs
|
|
4
|
+
import { cs } from "@block-kit/utils";
|
|
5
5
|
import { useUpdateLayoutEffect } from "@block-kit/utils/dist/es/hooks";
|
|
6
6
|
import React, { useMemo } from "react";
|
|
7
7
|
import { EDITOR_TO_WRAP_LEAF_KEYS, EDITOR_TO_WRAP_LEAF_PLUGINS } from "../plugin/modules/wrap";
|
|
8
|
+
import { updateDirtyLeaf, updateDirtyText } from "../utils/dirty-dom";
|
|
8
9
|
import { JSX_TO_STATE, LEAF_TO_TEXT } from "../utils/weak-map";
|
|
9
|
-
import { getWrapSymbol } from "../utils/wrapper";
|
|
10
|
+
import { getWrapSymbol } from "../utils/wrapper-node";
|
|
10
11
|
import { EOLModel } from "./eol";
|
|
11
12
|
import { LeafModel } from "./leaf";
|
|
12
13
|
/**
|
|
@@ -30,22 +31,10 @@ const LineView = props => {
|
|
|
30
31
|
useUpdateLayoutEffect(() => {
|
|
31
32
|
const leaves = lineState.getLeaves();
|
|
32
33
|
for (const leaf of leaves) {
|
|
33
|
-
const dom = LEAF_TO_TEXT.get(leaf);
|
|
34
|
-
if (!dom)
|
|
35
|
-
continue;
|
|
36
|
-
const text = leaf.getText();
|
|
37
34
|
// 避免 React 非受控与 IME 造成的 DOM 内容问题
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const nodes = dom.childNodes;
|
|
42
|
-
for (let i = 1; i < nodes.length; ++i) {
|
|
43
|
-
const node = nodes[i];
|
|
44
|
-
node && node.remove();
|
|
45
|
-
}
|
|
46
|
-
if (isDOMText(dom.firstChild)) {
|
|
47
|
-
dom.firstChild.nodeValue = text;
|
|
48
|
-
}
|
|
35
|
+
updateDirtyLeaf(editor, leaf);
|
|
36
|
+
const dom = LEAF_TO_TEXT.get(leaf);
|
|
37
|
+
dom && updateDirtyText(dom, leaf.getText());
|
|
49
38
|
}
|
|
50
39
|
}, [lineState]);
|
|
51
40
|
/**
|
|
@@ -88,7 +77,7 @@ const LineView = props => {
|
|
|
88
77
|
return nodes;
|
|
89
78
|
}, [editor, lineState]);
|
|
90
79
|
/**
|
|
91
|
-
*
|
|
80
|
+
* 将行内叶子节点包装组合 O(N)
|
|
92
81
|
*/
|
|
93
82
|
const children = useMemo(() => {
|
|
94
83
|
const wrapped = [];
|
package/dist/es/model/portal.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import React, { Fragment, useState } from "react";
|
|
3
|
-
import { EDITOR_TO_PORTAL } from "../utils/dom";
|
|
3
|
+
import { EDITOR_TO_PORTAL } from "../utils/mount-dom";
|
|
4
4
|
const PortalView = props => {
|
|
5
5
|
const [portals, setPortals] = useState({});
|
|
6
6
|
EDITOR_TO_PORTAL.set(props.editor, setPortals);
|
|
@@ -1,10 +1,47 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { EDITOR_EVENT, ISOLATED_KEY } from "@block-kit/core";
|
|
3
|
+
import { stopNativeEvent } from "@block-kit/utils";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
3
5
|
/**
|
|
4
6
|
* 独立节点嵌入 HOC
|
|
5
|
-
* - 独立区域
|
|
7
|
+
* - 独立区域 完全隔离相关事件
|
|
6
8
|
* @param props
|
|
7
9
|
*/
|
|
8
10
|
export const Isolate = props => {
|
|
9
|
-
|
|
11
|
+
const [ref, setRef] = useState(null);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const el = ref;
|
|
14
|
+
if (!el)
|
|
15
|
+
return void 0;
|
|
16
|
+
const { BEFORE_INPUT, MOUSE_DOWN, COPY, KEY_DOWN, PASTE, CUT, INPUT, FOCUS, BLUR, CLICK, COMPOSITION_END, COMPOSITION_START, COMPOSITION_UPDATE, } = EDITOR_EVENT;
|
|
17
|
+
el.addEventListener(CLICK, stopNativeEvent);
|
|
18
|
+
el.addEventListener(MOUSE_DOWN, stopNativeEvent);
|
|
19
|
+
el.addEventListener(CUT, stopNativeEvent);
|
|
20
|
+
el.addEventListener(COPY, stopNativeEvent);
|
|
21
|
+
el.addEventListener(PASTE, stopNativeEvent);
|
|
22
|
+
el.addEventListener(FOCUS, stopNativeEvent);
|
|
23
|
+
el.addEventListener(BLUR, stopNativeEvent);
|
|
24
|
+
el.addEventListener(KEY_DOWN, stopNativeEvent);
|
|
25
|
+
el.addEventListener(INPUT, stopNativeEvent);
|
|
26
|
+
el.addEventListener(BEFORE_INPUT, stopNativeEvent);
|
|
27
|
+
el.addEventListener(COMPOSITION_START, stopNativeEvent);
|
|
28
|
+
el.addEventListener(COMPOSITION_UPDATE, stopNativeEvent);
|
|
29
|
+
el.addEventListener(COMPOSITION_END, stopNativeEvent);
|
|
30
|
+
return () => {
|
|
31
|
+
el.removeEventListener(CLICK, stopNativeEvent);
|
|
32
|
+
el.removeEventListener(MOUSE_DOWN, stopNativeEvent);
|
|
33
|
+
el.removeEventListener(CUT, stopNativeEvent);
|
|
34
|
+
el.removeEventListener(COPY, stopNativeEvent);
|
|
35
|
+
el.removeEventListener(PASTE, stopNativeEvent);
|
|
36
|
+
el.removeEventListener(FOCUS, stopNativeEvent);
|
|
37
|
+
el.removeEventListener(BLUR, stopNativeEvent);
|
|
38
|
+
el.removeEventListener(KEY_DOWN, stopNativeEvent);
|
|
39
|
+
el.removeEventListener(INPUT, stopNativeEvent);
|
|
40
|
+
el.removeEventListener(BEFORE_INPUT, stopNativeEvent);
|
|
41
|
+
el.removeEventListener(COMPOSITION_START, stopNativeEvent);
|
|
42
|
+
el.removeEventListener(COMPOSITION_UPDATE, stopNativeEvent);
|
|
43
|
+
el.removeEventListener(COMPOSITION_END, stopNativeEvent);
|
|
44
|
+
};
|
|
45
|
+
}, [ref]);
|
|
46
|
+
return (_jsx("span", { ref: setRef, [ISOLATED_KEY]: true, className: props.className, style: props.style, contentEditable: false, children: props.children }));
|
|
10
47
|
};
|
package/dist/es/preset/text.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { LEAF_STRING } from "@block-kit/core";
|
|
3
|
-
import {
|
|
3
|
+
import { updateDirtyText } from "../utils/dirty-dom";
|
|
4
4
|
/**
|
|
5
5
|
* 文本节点
|
|
6
6
|
* @param props
|
|
@@ -10,19 +10,7 @@ export const Text = props => {
|
|
|
10
10
|
// 处理外部引用的 ref
|
|
11
11
|
props.onRef && props.onRef(dom);
|
|
12
12
|
// COMPAT: 避免 React 非受控与 IME 造成的 DOM 内容问题
|
|
13
|
-
|
|
14
|
-
return void 0;
|
|
15
|
-
const nodes = dom.childNodes;
|
|
16
|
-
// If the text content is inconsistent due to the modification of the input
|
|
17
|
-
// it needs to be corrected
|
|
18
|
-
for (let i = 1; i < nodes.length; ++i) {
|
|
19
|
-
const node = nodes[i];
|
|
20
|
-
node && node.remove();
|
|
21
|
-
}
|
|
22
|
-
// Guaranteed to have only one text child
|
|
23
|
-
if (isDOMText(dom.firstChild)) {
|
|
24
|
-
dom.firstChild.nodeValue = props.children;
|
|
25
|
-
}
|
|
13
|
+
dom && updateDirtyText(dom, props.children);
|
|
26
14
|
};
|
|
27
15
|
return (_jsx("span", { ref: onRef, [LEAF_STRING]: true, children: props.children }));
|
|
28
16
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LeafState } from "@block-kit/core";
|
|
2
|
+
import type { Editor } from "@block-kit/core";
|
|
3
|
+
/**
|
|
4
|
+
* 纯文本节点的检查更新
|
|
5
|
+
* @param dom DOM 节点
|
|
6
|
+
* @param text 目标文本
|
|
7
|
+
*/
|
|
8
|
+
export declare const updateDirtyText: (dom: HTMLElement, text: string) => boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Leaf 节点的检查更新
|
|
11
|
+
* @param editor
|
|
12
|
+
* @param leaf
|
|
13
|
+
*/
|
|
14
|
+
export declare const updateDirtyLeaf: (editor: Editor, leaf: LeafState) => boolean;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { isDOMText } from "@block-kit/utils";
|
|
2
|
+
/**
|
|
3
|
+
* 纯文本节点的检查更新
|
|
4
|
+
* @param dom DOM 节点
|
|
5
|
+
* @param text 目标文本
|
|
6
|
+
*/
|
|
7
|
+
export const updateDirtyText = (dom, text) => {
|
|
8
|
+
if (text === dom.textContent)
|
|
9
|
+
return false;
|
|
10
|
+
const nodes = dom.childNodes;
|
|
11
|
+
// 文本节点内部仅应该存在一个文本节点, 需要移除额外节点
|
|
12
|
+
for (let i = 1; i < nodes.length; ++i) {
|
|
13
|
+
const node = nodes[i];
|
|
14
|
+
node && node.remove();
|
|
15
|
+
}
|
|
16
|
+
// 如果文本内容不一致, 则是由于输入的脏 DOM, 需要纠正内容
|
|
17
|
+
// Case1: [inline-code][caret][text] IME 会导致模型/文本差异
|
|
18
|
+
if (isDOMText(dom.firstChild)) {
|
|
19
|
+
dom.firstChild.nodeValue = text;
|
|
20
|
+
}
|
|
21
|
+
if (process.env.NODE_ENV === "development") {
|
|
22
|
+
console.log("Correct Text Node", dom);
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Leaf 节点的检查更新
|
|
28
|
+
* @param editor
|
|
29
|
+
* @param leaf
|
|
30
|
+
*/
|
|
31
|
+
export const updateDirtyLeaf = (editor, leaf) => {
|
|
32
|
+
const dom = editor.model.getLeafNode(leaf);
|
|
33
|
+
const nodes = dom && dom.childNodes;
|
|
34
|
+
if (!nodes || nodes.length <= 1)
|
|
35
|
+
return false;
|
|
36
|
+
// data-leaf 节点内部仅应该存在非文本节点, 文本类型单节点, 嵌入类型双节点
|
|
37
|
+
// Case1: a 标签内的 IME 输入会导致同级的额外文本节点类型插入
|
|
38
|
+
for (let i = 0; i < nodes.length; ++i) {
|
|
39
|
+
const node = nodes[i];
|
|
40
|
+
isDOMText(node) && node.remove();
|
|
41
|
+
if (process.env.NODE_ENV === "development" && isDOMText(node)) {
|
|
42
|
+
console.log("Remove Leaf Child", dom, node);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
};
|
package/dist/es/utils/event.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
export declare const preventNativeEvent: (
|
|
2
|
-
|
|
1
|
+
export declare const preventNativeEvent: (event: {
|
|
2
|
+
preventDefault: Event["preventDefault"];
|
|
3
|
+
stopPropagation: Event["stopPropagation"];
|
|
4
|
+
stopImmediatePropagation?: Event["stopImmediatePropagation"];
|
|
5
|
+
}) => void;
|
|
6
|
+
export declare const preventReactEvent: (event: React.SyntheticEvent) => void;
|
package/dist/es/utils/event.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export const preventNativeEvent = (
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export const preventNativeEvent = (event) => {
|
|
2
|
+
event.preventDefault();
|
|
3
|
+
event.stopPropagation();
|
|
4
|
+
event.stopImmediatePropagation && event.stopImmediatePropagation();
|
|
4
5
|
};
|
|
5
|
-
export const preventReactEvent = (
|
|
6
|
-
preventNativeEvent(
|
|
6
|
+
export const preventReactEvent = (event) => {
|
|
7
|
+
preventNativeEvent(event);
|
|
8
|
+
preventNativeEvent(event.nativeEvent);
|
|
7
9
|
};
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -15,5 +15,5 @@ export { Isolate } from "./preset/isolate";
|
|
|
15
15
|
export { Text } from "./preset/text";
|
|
16
16
|
export { Void } from "./preset/void";
|
|
17
17
|
export { ZeroSpace } from "./preset/zero";
|
|
18
|
-
export { MountNode } from "./utils/dom";
|
|
19
18
|
export { preventNativeEvent, preventReactEvent } from "./utils/event";
|
|
19
|
+
export { MountNode } from "./utils/mount-dom";
|
package/dist/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.MountNode = exports.preventReactEvent = exports.preventNativeEvent = exports.ZeroSpace = exports.Void = exports.Text = exports.Isolate = exports.Embed = exports.Editable = exports.BlockKit = exports.InjectWrapKeys = exports.Priority = exports.EditorPlugin = exports.LineModel = exports.LeafModel = exports.EOLModel = exports.BlockModel = exports.useReadonly = exports.ReadonlyContext = exports.useEditorStatic = exports.BlockKitContext = void 0;
|
|
4
4
|
var use_editor_1 = require("./hooks/use-editor");
|
|
5
5
|
Object.defineProperty(exports, "BlockKitContext", { enumerable: true, get: function () { return use_editor_1.BlockKitContext; } });
|
|
6
6
|
Object.defineProperty(exports, "useEditorStatic", { enumerable: true, get: function () { return use_editor_1.useEditorStatic; } });
|
|
@@ -35,8 +35,8 @@ var void_1 = require("./preset/void");
|
|
|
35
35
|
Object.defineProperty(exports, "Void", { enumerable: true, get: function () { return void_1.Void; } });
|
|
36
36
|
var zero_1 = require("./preset/zero");
|
|
37
37
|
Object.defineProperty(exports, "ZeroSpace", { enumerable: true, get: function () { return zero_1.ZeroSpace; } });
|
|
38
|
-
var dom_1 = require("./utils/dom");
|
|
39
|
-
Object.defineProperty(exports, "MountNode", { enumerable: true, get: function () { return dom_1.MountNode; } });
|
|
40
38
|
var event_1 = require("./utils/event");
|
|
41
39
|
Object.defineProperty(exports, "preventNativeEvent", { enumerable: true, get: function () { return event_1.preventNativeEvent; } });
|
|
42
40
|
Object.defineProperty(exports, "preventReactEvent", { enumerable: true, get: function () { return event_1.preventReactEvent; } });
|
|
41
|
+
var mount_dom_1 = require("./utils/mount-dom");
|
|
42
|
+
Object.defineProperty(exports, "MountNode", { enumerable: true, get: function () { return mount_dom_1.MountNode; } });
|
package/dist/lib/model/block.js
CHANGED
|
@@ -29,9 +29,8 @@ const core_1 = require("@block-kit/core");
|
|
|
29
29
|
const hooks_1 = require("@block-kit/utils/dist/es/hooks");
|
|
30
30
|
const react_1 = __importStar(require("react"));
|
|
31
31
|
const wrap_1 = require("../plugin/modules/wrap");
|
|
32
|
-
const is_1 = require("../utils/is");
|
|
33
32
|
const weak_map_1 = require("../utils/weak-map");
|
|
34
|
-
const
|
|
33
|
+
const wrapper_node_1 = require("../utils/wrapper-node");
|
|
35
34
|
const line_1 = require("./line");
|
|
36
35
|
/**
|
|
37
36
|
* Block Model
|
|
@@ -118,7 +117,7 @@ const BlockView = props => {
|
|
|
118
117
|
});
|
|
119
118
|
}, [editor, lines]);
|
|
120
119
|
/**
|
|
121
|
-
*
|
|
120
|
+
* 将行节点包装组合 O(N)
|
|
122
121
|
*/
|
|
123
122
|
const children = (0, react_1.useMemo)(() => {
|
|
124
123
|
const wrapped = [];
|
|
@@ -129,7 +128,7 @@ const BlockView = props => {
|
|
|
129
128
|
const len = elements.length;
|
|
130
129
|
for (let i = 0; i < len; ++i) {
|
|
131
130
|
const element = elements[i];
|
|
132
|
-
const symbol = (0,
|
|
131
|
+
const symbol = (0, wrapper_node_1.getWrapSymbol)(keys, element);
|
|
133
132
|
const line = weak_map_1.JSX_TO_STATE.get(element);
|
|
134
133
|
if (!element || !line || !symbol) {
|
|
135
134
|
wrapped.push(element);
|
|
@@ -139,7 +138,7 @@ const BlockView = props => {
|
|
|
139
138
|
const nodes = [element];
|
|
140
139
|
for (let k = i + 1; k < len; ++k) {
|
|
141
140
|
const next = elements[k];
|
|
142
|
-
const nextSymbol = (0,
|
|
141
|
+
const nextSymbol = (0, wrapper_node_1.getWrapSymbol)(keys, next);
|
|
143
142
|
if (!next || !nextSymbol || nextSymbol !== symbol) {
|
|
144
143
|
// 回退到上一个值, 以便下次循环时重新检查
|
|
145
144
|
i = k - 1;
|
|
@@ -166,7 +165,7 @@ const BlockView = props => {
|
|
|
166
165
|
}
|
|
167
166
|
return wrapped;
|
|
168
167
|
}, [editor, elements]);
|
|
169
|
-
return ((0, jsx_runtime_1.jsxs)("div", { [core_1.BLOCK_KEY]: true, [core_1.BLOCK_ID_KEY]: state.key, ref: setModel, children: [props.placeholder && lines.length === 1 && (0,
|
|
168
|
+
return ((0, jsx_runtime_1.jsxs)("div", { [core_1.BLOCK_KEY]: true, [core_1.BLOCK_ID_KEY]: state.key, ref: setModel, children: [props.placeholder && lines.length === 1 && (0, core_1.isEmptyLine)(lines[0], true) && ((0, jsx_runtime_1.jsx)("div", { [core_1.PLACEHOLDER_KEY]: true, style: {
|
|
170
169
|
position: "absolute",
|
|
171
170
|
opacity: "0.3",
|
|
172
171
|
userSelect: "none",
|
package/dist/lib/model/leaf.js
CHANGED
|
@@ -35,11 +35,17 @@ const weak_map_1 = require("../utils/weak-map");
|
|
|
35
35
|
*/
|
|
36
36
|
const LeafView = props => {
|
|
37
37
|
const { editor, leafState } = props;
|
|
38
|
+
/**
|
|
39
|
+
* 设置叶子 DOM 节点
|
|
40
|
+
*/
|
|
38
41
|
const setModel = (ref) => {
|
|
39
42
|
if (ref) {
|
|
40
43
|
editor.model.setLeafModel(ref, leafState);
|
|
41
44
|
}
|
|
42
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* 处理叶子节点的渲染
|
|
48
|
+
*/
|
|
43
49
|
const runtime = (0, react_1.useMemo)(() => {
|
|
44
50
|
const text = leafState.getText();
|
|
45
51
|
const context = {
|
package/dist/lib/model/line.js
CHANGED
|
@@ -31,8 +31,9 @@ const utils_1 = require("@block-kit/utils");
|
|
|
31
31
|
const hooks_1 = require("@block-kit/utils/dist/es/hooks");
|
|
32
32
|
const react_1 = __importStar(require("react"));
|
|
33
33
|
const wrap_1 = require("../plugin/modules/wrap");
|
|
34
|
+
const dirty_dom_1 = require("../utils/dirty-dom");
|
|
34
35
|
const weak_map_1 = require("../utils/weak-map");
|
|
35
|
-
const
|
|
36
|
+
const wrapper_node_1 = require("../utils/wrapper-node");
|
|
36
37
|
const eol_1 = require("./eol");
|
|
37
38
|
const leaf_1 = require("./leaf");
|
|
38
39
|
/**
|
|
@@ -56,22 +57,10 @@ const LineView = props => {
|
|
|
56
57
|
(0, hooks_1.useUpdateLayoutEffect)(() => {
|
|
57
58
|
const leaves = lineState.getLeaves();
|
|
58
59
|
for (const leaf of leaves) {
|
|
59
|
-
const dom = weak_map_1.LEAF_TO_TEXT.get(leaf);
|
|
60
|
-
if (!dom)
|
|
61
|
-
continue;
|
|
62
|
-
const text = leaf.getText();
|
|
63
60
|
// 避免 React 非受控与 IME 造成的 DOM 内容问题
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const nodes = dom.childNodes;
|
|
68
|
-
for (let i = 1; i < nodes.length; ++i) {
|
|
69
|
-
const node = nodes[i];
|
|
70
|
-
node && node.remove();
|
|
71
|
-
}
|
|
72
|
-
if ((0, utils_1.isDOMText)(dom.firstChild)) {
|
|
73
|
-
dom.firstChild.nodeValue = text;
|
|
74
|
-
}
|
|
61
|
+
(0, dirty_dom_1.updateDirtyLeaf)(editor, leaf);
|
|
62
|
+
const dom = weak_map_1.LEAF_TO_TEXT.get(leaf);
|
|
63
|
+
dom && (0, dirty_dom_1.updateDirtyText)(dom, leaf.getText());
|
|
75
64
|
}
|
|
76
65
|
}, [lineState]);
|
|
77
66
|
/**
|
|
@@ -114,7 +103,7 @@ const LineView = props => {
|
|
|
114
103
|
return nodes;
|
|
115
104
|
}, [editor, lineState]);
|
|
116
105
|
/**
|
|
117
|
-
*
|
|
106
|
+
* 将行内叶子节点包装组合 O(N)
|
|
118
107
|
*/
|
|
119
108
|
const children = (0, react_1.useMemo)(() => {
|
|
120
109
|
const wrapped = [];
|
|
@@ -125,7 +114,7 @@ const LineView = props => {
|
|
|
125
114
|
const len = elements.length;
|
|
126
115
|
for (let i = 0; i < len; ++i) {
|
|
127
116
|
const element = elements[i];
|
|
128
|
-
const symbol = (0,
|
|
117
|
+
const symbol = (0, wrapper_node_1.getWrapSymbol)(keys, element);
|
|
129
118
|
const leaf = weak_map_1.JSX_TO_STATE.get(element);
|
|
130
119
|
if (!element || !leaf || !symbol) {
|
|
131
120
|
wrapped.push(element);
|
|
@@ -135,7 +124,7 @@ const LineView = props => {
|
|
|
135
124
|
const nodes = [element];
|
|
136
125
|
for (let k = i + 1; k < len; ++k) {
|
|
137
126
|
const next = elements[k];
|
|
138
|
-
const nextSymbol = (0,
|
|
127
|
+
const nextSymbol = (0, wrapper_node_1.getWrapSymbol)(keys, next);
|
|
139
128
|
if (!next || !nextSymbol || nextSymbol !== symbol) {
|
|
140
129
|
// 回退到上一个值, 以便下次循环时重新检查
|
|
141
130
|
i = k - 1;
|
package/dist/lib/model/portal.js
CHANGED
|
@@ -26,10 +26,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.PortalModel = void 0;
|
|
27
27
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
28
28
|
const react_1 = __importStar(require("react"));
|
|
29
|
-
const
|
|
29
|
+
const mount_dom_1 = require("../utils/mount-dom");
|
|
30
30
|
const PortalView = props => {
|
|
31
31
|
const [portals, setPortals] = (0, react_1.useState)({});
|
|
32
|
-
|
|
32
|
+
mount_dom_1.EDITOR_TO_PORTAL.set(props.editor, setPortals);
|
|
33
33
|
return ((0, jsx_runtime_1.jsx)(react_1.Fragment, { children: Object.entries(portals).map(([key, node]) => ((0, jsx_runtime_1.jsx)(react_1.Fragment, { children: node }, key))) }));
|
|
34
34
|
};
|
|
35
35
|
exports.PortalModel = react_1.default.memo(PortalView);
|
|
@@ -2,13 +2,50 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Isolate = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const
|
|
5
|
+
const core_1 = require("@block-kit/core");
|
|
6
|
+
const utils_1 = require("@block-kit/utils");
|
|
7
|
+
const react_1 = require("react");
|
|
6
8
|
/**
|
|
7
9
|
* 独立节点嵌入 HOC
|
|
8
|
-
* - 独立区域
|
|
10
|
+
* - 独立区域 完全隔离相关事件
|
|
9
11
|
* @param props
|
|
10
12
|
*/
|
|
11
13
|
const Isolate = props => {
|
|
12
|
-
|
|
14
|
+
const [ref, setRef] = (0, react_1.useState)(null);
|
|
15
|
+
(0, react_1.useEffect)(() => {
|
|
16
|
+
const el = ref;
|
|
17
|
+
if (!el)
|
|
18
|
+
return void 0;
|
|
19
|
+
const { BEFORE_INPUT, MOUSE_DOWN, COPY, KEY_DOWN, PASTE, CUT, INPUT, FOCUS, BLUR, CLICK, COMPOSITION_END, COMPOSITION_START, COMPOSITION_UPDATE, } = core_1.EDITOR_EVENT;
|
|
20
|
+
el.addEventListener(CLICK, utils_1.stopNativeEvent);
|
|
21
|
+
el.addEventListener(MOUSE_DOWN, utils_1.stopNativeEvent);
|
|
22
|
+
el.addEventListener(CUT, utils_1.stopNativeEvent);
|
|
23
|
+
el.addEventListener(COPY, utils_1.stopNativeEvent);
|
|
24
|
+
el.addEventListener(PASTE, utils_1.stopNativeEvent);
|
|
25
|
+
el.addEventListener(FOCUS, utils_1.stopNativeEvent);
|
|
26
|
+
el.addEventListener(BLUR, utils_1.stopNativeEvent);
|
|
27
|
+
el.addEventListener(KEY_DOWN, utils_1.stopNativeEvent);
|
|
28
|
+
el.addEventListener(INPUT, utils_1.stopNativeEvent);
|
|
29
|
+
el.addEventListener(BEFORE_INPUT, utils_1.stopNativeEvent);
|
|
30
|
+
el.addEventListener(COMPOSITION_START, utils_1.stopNativeEvent);
|
|
31
|
+
el.addEventListener(COMPOSITION_UPDATE, utils_1.stopNativeEvent);
|
|
32
|
+
el.addEventListener(COMPOSITION_END, utils_1.stopNativeEvent);
|
|
33
|
+
return () => {
|
|
34
|
+
el.removeEventListener(CLICK, utils_1.stopNativeEvent);
|
|
35
|
+
el.removeEventListener(MOUSE_DOWN, utils_1.stopNativeEvent);
|
|
36
|
+
el.removeEventListener(CUT, utils_1.stopNativeEvent);
|
|
37
|
+
el.removeEventListener(COPY, utils_1.stopNativeEvent);
|
|
38
|
+
el.removeEventListener(PASTE, utils_1.stopNativeEvent);
|
|
39
|
+
el.removeEventListener(FOCUS, utils_1.stopNativeEvent);
|
|
40
|
+
el.removeEventListener(BLUR, utils_1.stopNativeEvent);
|
|
41
|
+
el.removeEventListener(KEY_DOWN, utils_1.stopNativeEvent);
|
|
42
|
+
el.removeEventListener(INPUT, utils_1.stopNativeEvent);
|
|
43
|
+
el.removeEventListener(BEFORE_INPUT, utils_1.stopNativeEvent);
|
|
44
|
+
el.removeEventListener(COMPOSITION_START, utils_1.stopNativeEvent);
|
|
45
|
+
el.removeEventListener(COMPOSITION_UPDATE, utils_1.stopNativeEvent);
|
|
46
|
+
el.removeEventListener(COMPOSITION_END, utils_1.stopNativeEvent);
|
|
47
|
+
};
|
|
48
|
+
}, [ref]);
|
|
49
|
+
return ((0, jsx_runtime_1.jsx)("span", { ref: setRef, [core_1.ISOLATED_KEY]: true, className: props.className, style: props.style, contentEditable: false, children: props.children }));
|
|
13
50
|
};
|
|
14
51
|
exports.Isolate = Isolate;
|
package/dist/lib/preset/text.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Text = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const core_1 = require("@block-kit/core");
|
|
6
|
-
const
|
|
6
|
+
const dirty_dom_1 = require("../utils/dirty-dom");
|
|
7
7
|
/**
|
|
8
8
|
* 文本节点
|
|
9
9
|
* @param props
|
|
@@ -13,19 +13,7 @@ const Text = props => {
|
|
|
13
13
|
// 处理外部引用的 ref
|
|
14
14
|
props.onRef && props.onRef(dom);
|
|
15
15
|
// COMPAT: 避免 React 非受控与 IME 造成的 DOM 内容问题
|
|
16
|
-
|
|
17
|
-
return void 0;
|
|
18
|
-
const nodes = dom.childNodes;
|
|
19
|
-
// If the text content is inconsistent due to the modification of the input
|
|
20
|
-
// it needs to be corrected
|
|
21
|
-
for (let i = 1; i < nodes.length; ++i) {
|
|
22
|
-
const node = nodes[i];
|
|
23
|
-
node && node.remove();
|
|
24
|
-
}
|
|
25
|
-
// Guaranteed to have only one text child
|
|
26
|
-
if ((0, utils_1.isDOMText)(dom.firstChild)) {
|
|
27
|
-
dom.firstChild.nodeValue = props.children;
|
|
28
|
-
}
|
|
16
|
+
dom && (0, dirty_dom_1.updateDirtyText)(dom, props.children);
|
|
29
17
|
};
|
|
30
18
|
return ((0, jsx_runtime_1.jsx)("span", { ref: onRef, [core_1.LEAF_STRING]: true, children: props.children }));
|
|
31
19
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LeafState } from "@block-kit/core";
|
|
2
|
+
import type { Editor } from "@block-kit/core";
|
|
3
|
+
/**
|
|
4
|
+
* 纯文本节点的检查更新
|
|
5
|
+
* @param dom DOM 节点
|
|
6
|
+
* @param text 目标文本
|
|
7
|
+
*/
|
|
8
|
+
export declare const updateDirtyText: (dom: HTMLElement, text: string) => boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Leaf 节点的检查更新
|
|
11
|
+
* @param editor
|
|
12
|
+
* @param leaf
|
|
13
|
+
*/
|
|
14
|
+
export declare const updateDirtyLeaf: (editor: Editor, leaf: LeafState) => boolean;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateDirtyLeaf = exports.updateDirtyText = void 0;
|
|
4
|
+
const utils_1 = require("@block-kit/utils");
|
|
5
|
+
/**
|
|
6
|
+
* 纯文本节点的检查更新
|
|
7
|
+
* @param dom DOM 节点
|
|
8
|
+
* @param text 目标文本
|
|
9
|
+
*/
|
|
10
|
+
const updateDirtyText = (dom, text) => {
|
|
11
|
+
if (text === dom.textContent)
|
|
12
|
+
return false;
|
|
13
|
+
const nodes = dom.childNodes;
|
|
14
|
+
// 文本节点内部仅应该存在一个文本节点, 需要移除额外节点
|
|
15
|
+
for (let i = 1; i < nodes.length; ++i) {
|
|
16
|
+
const node = nodes[i];
|
|
17
|
+
node && node.remove();
|
|
18
|
+
}
|
|
19
|
+
// 如果文本内容不一致, 则是由于输入的脏 DOM, 需要纠正内容
|
|
20
|
+
// Case1: [inline-code][caret][text] IME 会导致模型/文本差异
|
|
21
|
+
if ((0, utils_1.isDOMText)(dom.firstChild)) {
|
|
22
|
+
dom.firstChild.nodeValue = text;
|
|
23
|
+
}
|
|
24
|
+
if (process.env.NODE_ENV === "development") {
|
|
25
|
+
console.log("Correct Text Node", dom);
|
|
26
|
+
}
|
|
27
|
+
return true;
|
|
28
|
+
};
|
|
29
|
+
exports.updateDirtyText = updateDirtyText;
|
|
30
|
+
/**
|
|
31
|
+
* Leaf 节点的检查更新
|
|
32
|
+
* @param editor
|
|
33
|
+
* @param leaf
|
|
34
|
+
*/
|
|
35
|
+
const updateDirtyLeaf = (editor, leaf) => {
|
|
36
|
+
const dom = editor.model.getLeafNode(leaf);
|
|
37
|
+
const nodes = dom && dom.childNodes;
|
|
38
|
+
if (!nodes || nodes.length <= 1)
|
|
39
|
+
return false;
|
|
40
|
+
// data-leaf 节点内部仅应该存在非文本节点, 文本类型单节点, 嵌入类型双节点
|
|
41
|
+
// Case1: a 标签内的 IME 输入会导致同级的额外文本节点类型插入
|
|
42
|
+
for (let i = 0; i < nodes.length; ++i) {
|
|
43
|
+
const node = nodes[i];
|
|
44
|
+
(0, utils_1.isDOMText)(node) && node.remove();
|
|
45
|
+
if (process.env.NODE_ENV === "development" && (0, utils_1.isDOMText)(node)) {
|
|
46
|
+
console.log("Remove Leaf Child", dom, node);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
};
|
|
51
|
+
exports.updateDirtyLeaf = updateDirtyLeaf;
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
export declare const preventNativeEvent: (
|
|
2
|
-
|
|
1
|
+
export declare const preventNativeEvent: (event: {
|
|
2
|
+
preventDefault: Event["preventDefault"];
|
|
3
|
+
stopPropagation: Event["stopPropagation"];
|
|
4
|
+
stopImmediatePropagation?: Event["stopImmediatePropagation"];
|
|
5
|
+
}) => void;
|
|
6
|
+
export declare const preventReactEvent: (event: React.SyntheticEvent) => void;
|
package/dist/lib/utils/event.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.preventReactEvent = exports.preventNativeEvent = void 0;
|
|
4
|
-
const preventNativeEvent = (
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const preventNativeEvent = (event) => {
|
|
5
|
+
event.preventDefault();
|
|
6
|
+
event.stopPropagation();
|
|
7
|
+
event.stopImmediatePropagation && event.stopImmediatePropagation();
|
|
7
8
|
};
|
|
8
9
|
exports.preventNativeEvent = preventNativeEvent;
|
|
9
|
-
const preventReactEvent = (
|
|
10
|
-
(0, exports.preventNativeEvent)(
|
|
10
|
+
const preventReactEvent = (event) => {
|
|
11
|
+
(0, exports.preventNativeEvent)(event);
|
|
12
|
+
(0, exports.preventNativeEvent)(event.nativeEvent);
|
|
11
13
|
};
|
|
12
14
|
exports.preventReactEvent = preventReactEvent;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@block-kit/react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/lib/index.js",
|
|
6
6
|
"types": "./dist/es/index.d.ts",
|
|
@@ -28,20 +28,20 @@
|
|
|
28
28
|
],
|
|
29
29
|
"repository": {
|
|
30
30
|
"type": "git",
|
|
31
|
-
"url": "git+https://github.com/
|
|
31
|
+
"url": "git+https://github.com/WindRunnerMax/BlockKit.git"
|
|
32
32
|
},
|
|
33
|
-
"homepage": "https://github.com/
|
|
33
|
+
"homepage": "https://github.com/WindRunnerMax/BlockKit",
|
|
34
34
|
"bugs": {
|
|
35
|
-
"url": "https://github.com/
|
|
35
|
+
"url": "https://github.com/WindRunnerMax/BlockKit/issues"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"react": ">=16",
|
|
39
39
|
"react-dom": ">=16"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@block-kit/core": "1.0.
|
|
43
|
-
"@block-kit/delta": "1.0.
|
|
44
|
-
"@block-kit/utils": "1.0.
|
|
42
|
+
"@block-kit/core": "1.0.11",
|
|
43
|
+
"@block-kit/delta": "1.0.11",
|
|
44
|
+
"@block-kit/utils": "1.0.11"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/react": "17.0.2",
|
package/dist/es/utils/is.d.ts
DELETED
package/dist/es/utils/is.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export const isStrictEmptyLine = (line) => {
|
|
2
|
-
const leaves = line.getLeaves();
|
|
3
|
-
if (!leaves.length) {
|
|
4
|
-
return true;
|
|
5
|
-
}
|
|
6
|
-
if (leaves.length === 1 &&
|
|
7
|
-
leaves[0].eol &&
|
|
8
|
-
(!leaves[0].op.attributes || !Object.keys(leaves[0].op.attributes).length)) {
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
return false;
|
|
12
|
-
};
|
package/dist/lib/utils/is.d.ts
DELETED
package/dist/lib/utils/is.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isStrictEmptyLine = void 0;
|
|
4
|
-
const isStrictEmptyLine = (line) => {
|
|
5
|
-
const leaves = line.getLeaves();
|
|
6
|
-
if (!leaves.length) {
|
|
7
|
-
return true;
|
|
8
|
-
}
|
|
9
|
-
if (leaves.length === 1 &&
|
|
10
|
-
leaves[0].eol &&
|
|
11
|
-
(!leaves[0].op.attributes || !Object.keys(leaves[0].op.attributes).length)) {
|
|
12
|
-
return true;
|
|
13
|
-
}
|
|
14
|
-
return false;
|
|
15
|
-
};
|
|
16
|
-
exports.isStrictEmptyLine = isStrictEmptyLine;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|