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