@tiptap/core 2.0.0-beta.153 → 2.0.0-beta.157
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/tiptap-core.cjs.js +219 -151
- package/dist/tiptap-core.cjs.js.map +1 -1
- package/dist/tiptap-core.esm.js +219 -151
- package/dist/tiptap-core.esm.js.map +1 -1
- package/dist/tiptap-core.umd.js +219 -151
- package/dist/tiptap-core.umd.js.map +1 -1
- package/package.json +3 -3
- package/src/commands/clearNodes.ts +13 -8
- package/src/commands/setNode.ts +9 -6
- package/src/commands/toggleList.ts +10 -0
- package/src/extensions/keymap.ts +70 -0
package/dist/tiptap-core.umd.js
CHANGED
|
@@ -228,23 +228,27 @@
|
|
|
228
228
|
const clearNodes = () => ({ state, tr, dispatch }) => {
|
|
229
229
|
const { selection } = tr;
|
|
230
230
|
const { ranges } = selection;
|
|
231
|
-
|
|
232
|
-
|
|
231
|
+
if (!dispatch) {
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
ranges.forEach(({ $from, $to }) => {
|
|
235
|
+
state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
|
|
233
236
|
if (node.type.isText) {
|
|
234
237
|
return;
|
|
235
238
|
}
|
|
236
|
-
const
|
|
237
|
-
const $
|
|
238
|
-
const
|
|
239
|
+
const { doc, mapping } = tr;
|
|
240
|
+
const $mappedFrom = doc.resolve(mapping.map(pos));
|
|
241
|
+
const $mappedTo = doc.resolve(mapping.map(pos + node.nodeSize));
|
|
242
|
+
const nodeRange = $mappedFrom.blockRange($mappedTo);
|
|
239
243
|
if (!nodeRange) {
|
|
240
244
|
return;
|
|
241
245
|
}
|
|
242
246
|
const targetLiftDepth = prosemirrorTransform.liftTarget(nodeRange);
|
|
243
|
-
if (node.type.isTextblock
|
|
244
|
-
const { defaultType } = $
|
|
247
|
+
if (node.type.isTextblock) {
|
|
248
|
+
const { defaultType } = $mappedFrom.parent.contentMatchAt($mappedFrom.index());
|
|
245
249
|
tr.setNodeMarkup(nodeRange.start, defaultType);
|
|
246
250
|
}
|
|
247
|
-
if (
|
|
251
|
+
if (targetLiftDepth || targetLiftDepth === 0) {
|
|
248
252
|
tr.lift(nodeRange, targetLiftDepth);
|
|
249
253
|
}
|
|
250
254
|
});
|
|
@@ -1104,12 +1108,15 @@
|
|
|
1104
1108
|
console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.');
|
|
1105
1109
|
return false;
|
|
1106
1110
|
}
|
|
1107
|
-
const canSetBlock = prosemirrorCommands.setBlockType(type, attributes)(state);
|
|
1108
|
-
if (canSetBlock) {
|
|
1109
|
-
return prosemirrorCommands.setBlockType(type, attributes)(state, dispatch);
|
|
1110
|
-
}
|
|
1111
1111
|
return chain()
|
|
1112
|
-
|
|
1112
|
+
// try to convert node to default node if needed
|
|
1113
|
+
.command(({ commands }) => {
|
|
1114
|
+
const canSetBlock = prosemirrorCommands.setBlockType(type, attributes)(state);
|
|
1115
|
+
if (canSetBlock) {
|
|
1116
|
+
return true;
|
|
1117
|
+
}
|
|
1118
|
+
return commands.clearNodes();
|
|
1119
|
+
})
|
|
1113
1120
|
.command(({ state: updatedState }) => {
|
|
1114
1121
|
return prosemirrorCommands.setBlockType(type, attributes)(updatedState, dispatch);
|
|
1115
1122
|
})
|
|
@@ -1413,6 +1420,9 @@
|
|
|
1413
1420
|
return true;
|
|
1414
1421
|
}
|
|
1415
1422
|
const before = tr.doc.resolve(Math.max(0, list.pos - 1)).before(list.depth);
|
|
1423
|
+
if (before === undefined) {
|
|
1424
|
+
return true;
|
|
1425
|
+
}
|
|
1416
1426
|
const nodeBefore = tr.doc.nodeAt(before);
|
|
1417
1427
|
const canJoinBackwards = list.node.type === (nodeBefore === null || nodeBefore === void 0 ? void 0 : nodeBefore.type)
|
|
1418
1428
|
&& prosemirrorTransform.canJoin(tr.doc, list.pos);
|
|
@@ -1428,6 +1438,9 @@
|
|
|
1428
1438
|
return true;
|
|
1429
1439
|
}
|
|
1430
1440
|
const after = tr.doc.resolve(list.start).after(list.depth);
|
|
1441
|
+
if (after === undefined) {
|
|
1442
|
+
return true;
|
|
1443
|
+
}
|
|
1431
1444
|
const nodeAfter = tr.doc.nodeAt(after);
|
|
1432
1445
|
const canJoinForwards = list.node.type === (nodeAfter === null || nodeAfter === void 0 ? void 0 : nodeAfter.type)
|
|
1433
1446
|
&& prosemirrorTransform.canJoin(tr.doc, after);
|
|
@@ -1854,144 +1867,6 @@
|
|
|
1854
1867
|
},
|
|
1855
1868
|
});
|
|
1856
1869
|
|
|
1857
|
-
const Keymap = Extension.create({
|
|
1858
|
-
name: 'keymap',
|
|
1859
|
-
addKeyboardShortcuts() {
|
|
1860
|
-
const handleBackspace = () => this.editor.commands.first(({ commands }) => [
|
|
1861
|
-
() => commands.undoInputRule(),
|
|
1862
|
-
() => commands.deleteSelection(),
|
|
1863
|
-
() => commands.joinBackward(),
|
|
1864
|
-
() => commands.selectNodeBackward(),
|
|
1865
|
-
]);
|
|
1866
|
-
const handleDelete = () => this.editor.commands.first(({ commands }) => [
|
|
1867
|
-
() => commands.deleteSelection(),
|
|
1868
|
-
() => commands.joinForward(),
|
|
1869
|
-
() => commands.selectNodeForward(),
|
|
1870
|
-
]);
|
|
1871
|
-
return {
|
|
1872
|
-
Enter: () => this.editor.commands.first(({ commands }) => [
|
|
1873
|
-
() => commands.newlineInCode(),
|
|
1874
|
-
() => commands.createParagraphNear(),
|
|
1875
|
-
() => commands.liftEmptyBlock(),
|
|
1876
|
-
() => commands.splitBlock(),
|
|
1877
|
-
]),
|
|
1878
|
-
'Mod-Enter': () => this.editor.commands.exitCode(),
|
|
1879
|
-
Backspace: handleBackspace,
|
|
1880
|
-
'Mod-Backspace': handleBackspace,
|
|
1881
|
-
'Shift-Backspace': handleBackspace,
|
|
1882
|
-
Delete: handleDelete,
|
|
1883
|
-
'Mod-Delete': handleDelete,
|
|
1884
|
-
'Mod-a': () => this.editor.commands.selectAll(),
|
|
1885
|
-
};
|
|
1886
|
-
},
|
|
1887
|
-
});
|
|
1888
|
-
|
|
1889
|
-
const Tabindex = Extension.create({
|
|
1890
|
-
name: 'tabindex',
|
|
1891
|
-
addProseMirrorPlugins() {
|
|
1892
|
-
return [
|
|
1893
|
-
new prosemirrorState.Plugin({
|
|
1894
|
-
key: new prosemirrorState.PluginKey('tabindex'),
|
|
1895
|
-
props: {
|
|
1896
|
-
attributes: {
|
|
1897
|
-
tabindex: '0',
|
|
1898
|
-
},
|
|
1899
|
-
},
|
|
1900
|
-
}),
|
|
1901
|
-
];
|
|
1902
|
-
},
|
|
1903
|
-
});
|
|
1904
|
-
|
|
1905
|
-
var extensions = /*#__PURE__*/Object.freeze({
|
|
1906
|
-
__proto__: null,
|
|
1907
|
-
ClipboardTextSerializer: ClipboardTextSerializer,
|
|
1908
|
-
Commands: Commands,
|
|
1909
|
-
Editable: Editable,
|
|
1910
|
-
FocusEvents: FocusEvents,
|
|
1911
|
-
Keymap: Keymap,
|
|
1912
|
-
Tabindex: Tabindex
|
|
1913
|
-
});
|
|
1914
|
-
|
|
1915
|
-
function getNodeAttributes(state, typeOrName) {
|
|
1916
|
-
const type = getNodeType(typeOrName, state.schema);
|
|
1917
|
-
const { from, to } = state.selection;
|
|
1918
|
-
const nodes = [];
|
|
1919
|
-
state.doc.nodesBetween(from, to, node => {
|
|
1920
|
-
nodes.push(node);
|
|
1921
|
-
});
|
|
1922
|
-
const node = nodes
|
|
1923
|
-
.reverse()
|
|
1924
|
-
.find(nodeItem => nodeItem.type.name === type.name);
|
|
1925
|
-
if (!node) {
|
|
1926
|
-
return {};
|
|
1927
|
-
}
|
|
1928
|
-
return { ...node.attrs };
|
|
1929
|
-
}
|
|
1930
|
-
|
|
1931
|
-
function getAttributes(state, typeOrName) {
|
|
1932
|
-
const schemaType = getSchemaTypeNameByName(typeof typeOrName === 'string'
|
|
1933
|
-
? typeOrName
|
|
1934
|
-
: typeOrName.name, state.schema);
|
|
1935
|
-
if (schemaType === 'node') {
|
|
1936
|
-
return getNodeAttributes(state, typeOrName);
|
|
1937
|
-
}
|
|
1938
|
-
if (schemaType === 'mark') {
|
|
1939
|
-
return getMarkAttributes(state, typeOrName);
|
|
1940
|
-
}
|
|
1941
|
-
return {};
|
|
1942
|
-
}
|
|
1943
|
-
|
|
1944
|
-
function isActive(state, name, attributes = {}) {
|
|
1945
|
-
if (!name) {
|
|
1946
|
-
return isNodeActive(state, null, attributes) || isMarkActive(state, null, attributes);
|
|
1947
|
-
}
|
|
1948
|
-
const schemaType = getSchemaTypeNameByName(name, state.schema);
|
|
1949
|
-
if (schemaType === 'node') {
|
|
1950
|
-
return isNodeActive(state, name, attributes);
|
|
1951
|
-
}
|
|
1952
|
-
if (schemaType === 'mark') {
|
|
1953
|
-
return isMarkActive(state, name, attributes);
|
|
1954
|
-
}
|
|
1955
|
-
return false;
|
|
1956
|
-
}
|
|
1957
|
-
|
|
1958
|
-
function getHTMLFromFragment(fragment, schema) {
|
|
1959
|
-
const documentFragment = prosemirrorModel.DOMSerializer
|
|
1960
|
-
.fromSchema(schema)
|
|
1961
|
-
.serializeFragment(fragment);
|
|
1962
|
-
const temporaryDocument = document.implementation.createHTMLDocument();
|
|
1963
|
-
const container = temporaryDocument.createElement('div');
|
|
1964
|
-
container.appendChild(documentFragment);
|
|
1965
|
-
return container.innerHTML;
|
|
1966
|
-
}
|
|
1967
|
-
|
|
1968
|
-
function getText(node, options) {
|
|
1969
|
-
const range = {
|
|
1970
|
-
from: 0,
|
|
1971
|
-
to: node.content.size,
|
|
1972
|
-
};
|
|
1973
|
-
return getTextBetween(node, range, options);
|
|
1974
|
-
}
|
|
1975
|
-
|
|
1976
|
-
function isNodeEmpty(node) {
|
|
1977
|
-
var _a;
|
|
1978
|
-
const defaultContent = (_a = node.type.createAndFill()) === null || _a === void 0 ? void 0 : _a.toJSON();
|
|
1979
|
-
const content = node.toJSON();
|
|
1980
|
-
return JSON.stringify(defaultContent) === JSON.stringify(content);
|
|
1981
|
-
}
|
|
1982
|
-
|
|
1983
|
-
function createStyleTag(style) {
|
|
1984
|
-
const tipTapStyleTag = document.querySelector('style[data-tiptap-style]');
|
|
1985
|
-
if (tipTapStyleTag !== null) {
|
|
1986
|
-
return tipTapStyleTag;
|
|
1987
|
-
}
|
|
1988
|
-
const styleNode = document.createElement('style');
|
|
1989
|
-
styleNode.setAttribute('data-tiptap-style', '');
|
|
1990
|
-
styleNode.innerHTML = style;
|
|
1991
|
-
document.getElementsByTagName('head')[0].appendChild(styleNode);
|
|
1992
|
-
return styleNode;
|
|
1993
|
-
}
|
|
1994
|
-
|
|
1995
1870
|
function createChainableState(config) {
|
|
1996
1871
|
const { state, transaction } = config;
|
|
1997
1872
|
let { selection } = transaction;
|
|
@@ -2134,6 +2009,199 @@
|
|
|
2134
2009
|
}
|
|
2135
2010
|
}
|
|
2136
2011
|
|
|
2012
|
+
const Keymap = Extension.create({
|
|
2013
|
+
name: 'keymap',
|
|
2014
|
+
addKeyboardShortcuts() {
|
|
2015
|
+
const handleBackspace = () => this.editor.commands.first(({ commands }) => [
|
|
2016
|
+
() => commands.undoInputRule(),
|
|
2017
|
+
// maybe convert first text block node to default node
|
|
2018
|
+
() => commands.command(({ tr }) => {
|
|
2019
|
+
const { selection, doc } = tr;
|
|
2020
|
+
const { empty, $anchor } = selection;
|
|
2021
|
+
const { pos, parent } = $anchor;
|
|
2022
|
+
const isAtStart = prosemirrorState.Selection.atStart(doc).from === pos;
|
|
2023
|
+
if (!empty
|
|
2024
|
+
|| !isAtStart
|
|
2025
|
+
|| !parent.type.isTextblock
|
|
2026
|
+
|| parent.textContent.length) {
|
|
2027
|
+
return false;
|
|
2028
|
+
}
|
|
2029
|
+
return commands.clearNodes();
|
|
2030
|
+
}),
|
|
2031
|
+
() => commands.deleteSelection(),
|
|
2032
|
+
() => commands.joinBackward(),
|
|
2033
|
+
() => commands.selectNodeBackward(),
|
|
2034
|
+
]);
|
|
2035
|
+
const handleDelete = () => this.editor.commands.first(({ commands }) => [
|
|
2036
|
+
() => commands.deleteSelection(),
|
|
2037
|
+
() => commands.joinForward(),
|
|
2038
|
+
() => commands.selectNodeForward(),
|
|
2039
|
+
]);
|
|
2040
|
+
return {
|
|
2041
|
+
Enter: () => this.editor.commands.first(({ commands }) => [
|
|
2042
|
+
() => commands.newlineInCode(),
|
|
2043
|
+
() => commands.createParagraphNear(),
|
|
2044
|
+
() => commands.liftEmptyBlock(),
|
|
2045
|
+
() => commands.splitBlock(),
|
|
2046
|
+
]),
|
|
2047
|
+
'Mod-Enter': () => this.editor.commands.exitCode(),
|
|
2048
|
+
Backspace: handleBackspace,
|
|
2049
|
+
'Mod-Backspace': handleBackspace,
|
|
2050
|
+
'Shift-Backspace': handleBackspace,
|
|
2051
|
+
Delete: handleDelete,
|
|
2052
|
+
'Mod-Delete': handleDelete,
|
|
2053
|
+
'Mod-a': () => this.editor.commands.selectAll(),
|
|
2054
|
+
};
|
|
2055
|
+
},
|
|
2056
|
+
addProseMirrorPlugins() {
|
|
2057
|
+
return [
|
|
2058
|
+
// With this plugin we check if the whole document was selected and deleted.
|
|
2059
|
+
// In this case we will additionally call `clearNodes()` to convert e.g. a heading
|
|
2060
|
+
// to a paragraph if necessary.
|
|
2061
|
+
// This is an alternative to ProseMirror's `AllSelection`, which doesn’t work well
|
|
2062
|
+
// with many other commands.
|
|
2063
|
+
new prosemirrorState.Plugin({
|
|
2064
|
+
key: new prosemirrorState.PluginKey('clearDocument'),
|
|
2065
|
+
appendTransaction: (transactions, oldState, newState) => {
|
|
2066
|
+
const docChanges = transactions.some(transaction => transaction.docChanged)
|
|
2067
|
+
&& !oldState.doc.eq(newState.doc);
|
|
2068
|
+
if (!docChanges) {
|
|
2069
|
+
return;
|
|
2070
|
+
}
|
|
2071
|
+
const { empty, from, to } = oldState.selection;
|
|
2072
|
+
const allFrom = prosemirrorState.Selection.atStart(oldState.doc).from;
|
|
2073
|
+
const allEnd = prosemirrorState.Selection.atEnd(oldState.doc).to;
|
|
2074
|
+
const allWasSelected = from === allFrom && to === allEnd;
|
|
2075
|
+
const isEmpty = newState.doc.textBetween(0, newState.doc.content.size, ' ', ' ').length === 0;
|
|
2076
|
+
if (empty || !allWasSelected || !isEmpty) {
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
const tr = newState.tr;
|
|
2080
|
+
const state = createChainableState({
|
|
2081
|
+
state: newState,
|
|
2082
|
+
transaction: tr,
|
|
2083
|
+
});
|
|
2084
|
+
const { commands } = new CommandManager({
|
|
2085
|
+
editor: this.editor,
|
|
2086
|
+
state,
|
|
2087
|
+
});
|
|
2088
|
+
commands.clearNodes();
|
|
2089
|
+
if (!tr.steps.length) {
|
|
2090
|
+
return;
|
|
2091
|
+
}
|
|
2092
|
+
return tr;
|
|
2093
|
+
},
|
|
2094
|
+
}),
|
|
2095
|
+
];
|
|
2096
|
+
},
|
|
2097
|
+
});
|
|
2098
|
+
|
|
2099
|
+
const Tabindex = Extension.create({
|
|
2100
|
+
name: 'tabindex',
|
|
2101
|
+
addProseMirrorPlugins() {
|
|
2102
|
+
return [
|
|
2103
|
+
new prosemirrorState.Plugin({
|
|
2104
|
+
key: new prosemirrorState.PluginKey('tabindex'),
|
|
2105
|
+
props: {
|
|
2106
|
+
attributes: {
|
|
2107
|
+
tabindex: '0',
|
|
2108
|
+
},
|
|
2109
|
+
},
|
|
2110
|
+
}),
|
|
2111
|
+
];
|
|
2112
|
+
},
|
|
2113
|
+
});
|
|
2114
|
+
|
|
2115
|
+
var extensions = /*#__PURE__*/Object.freeze({
|
|
2116
|
+
__proto__: null,
|
|
2117
|
+
ClipboardTextSerializer: ClipboardTextSerializer,
|
|
2118
|
+
Commands: Commands,
|
|
2119
|
+
Editable: Editable,
|
|
2120
|
+
FocusEvents: FocusEvents,
|
|
2121
|
+
Keymap: Keymap,
|
|
2122
|
+
Tabindex: Tabindex
|
|
2123
|
+
});
|
|
2124
|
+
|
|
2125
|
+
function getNodeAttributes(state, typeOrName) {
|
|
2126
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
2127
|
+
const { from, to } = state.selection;
|
|
2128
|
+
const nodes = [];
|
|
2129
|
+
state.doc.nodesBetween(from, to, node => {
|
|
2130
|
+
nodes.push(node);
|
|
2131
|
+
});
|
|
2132
|
+
const node = nodes
|
|
2133
|
+
.reverse()
|
|
2134
|
+
.find(nodeItem => nodeItem.type.name === type.name);
|
|
2135
|
+
if (!node) {
|
|
2136
|
+
return {};
|
|
2137
|
+
}
|
|
2138
|
+
return { ...node.attrs };
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
function getAttributes(state, typeOrName) {
|
|
2142
|
+
const schemaType = getSchemaTypeNameByName(typeof typeOrName === 'string'
|
|
2143
|
+
? typeOrName
|
|
2144
|
+
: typeOrName.name, state.schema);
|
|
2145
|
+
if (schemaType === 'node') {
|
|
2146
|
+
return getNodeAttributes(state, typeOrName);
|
|
2147
|
+
}
|
|
2148
|
+
if (schemaType === 'mark') {
|
|
2149
|
+
return getMarkAttributes(state, typeOrName);
|
|
2150
|
+
}
|
|
2151
|
+
return {};
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
function isActive(state, name, attributes = {}) {
|
|
2155
|
+
if (!name) {
|
|
2156
|
+
return isNodeActive(state, null, attributes) || isMarkActive(state, null, attributes);
|
|
2157
|
+
}
|
|
2158
|
+
const schemaType = getSchemaTypeNameByName(name, state.schema);
|
|
2159
|
+
if (schemaType === 'node') {
|
|
2160
|
+
return isNodeActive(state, name, attributes);
|
|
2161
|
+
}
|
|
2162
|
+
if (schemaType === 'mark') {
|
|
2163
|
+
return isMarkActive(state, name, attributes);
|
|
2164
|
+
}
|
|
2165
|
+
return false;
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
function getHTMLFromFragment(fragment, schema) {
|
|
2169
|
+
const documentFragment = prosemirrorModel.DOMSerializer
|
|
2170
|
+
.fromSchema(schema)
|
|
2171
|
+
.serializeFragment(fragment);
|
|
2172
|
+
const temporaryDocument = document.implementation.createHTMLDocument();
|
|
2173
|
+
const container = temporaryDocument.createElement('div');
|
|
2174
|
+
container.appendChild(documentFragment);
|
|
2175
|
+
return container.innerHTML;
|
|
2176
|
+
}
|
|
2177
|
+
|
|
2178
|
+
function getText(node, options) {
|
|
2179
|
+
const range = {
|
|
2180
|
+
from: 0,
|
|
2181
|
+
to: node.content.size,
|
|
2182
|
+
};
|
|
2183
|
+
return getTextBetween(node, range, options);
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
function isNodeEmpty(node) {
|
|
2187
|
+
var _a;
|
|
2188
|
+
const defaultContent = (_a = node.type.createAndFill()) === null || _a === void 0 ? void 0 : _a.toJSON();
|
|
2189
|
+
const content = node.toJSON();
|
|
2190
|
+
return JSON.stringify(defaultContent) === JSON.stringify(content);
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
function createStyleTag(style) {
|
|
2194
|
+
const tipTapStyleTag = document.querySelector('style[data-tiptap-style]');
|
|
2195
|
+
if (tipTapStyleTag !== null) {
|
|
2196
|
+
return tipTapStyleTag;
|
|
2197
|
+
}
|
|
2198
|
+
const styleNode = document.createElement('style');
|
|
2199
|
+
styleNode.setAttribute('data-tiptap-style', '');
|
|
2200
|
+
styleNode.innerHTML = style;
|
|
2201
|
+
document.getElementsByTagName('head')[0].appendChild(styleNode);
|
|
2202
|
+
return styleNode;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2137
2205
|
class InputRule {
|
|
2138
2206
|
constructor(config) {
|
|
2139
2207
|
this.find = config.find;
|