Initial
This commit is contained in:
8
resources/app/node_modules/prosemirror-inputrules/.tern-project
generated
vendored
Normal file
8
resources/app/node_modules/prosemirror-inputrules/.tern-project
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"libs": ["browser"],
|
||||
"plugins": {
|
||||
"node": {},
|
||||
"complete_strings": {},
|
||||
"es_modules": {}
|
||||
}
|
||||
}
|
||||
104
resources/app/node_modules/prosemirror-inputrules/CONTRIBUTING.md
generated
vendored
Normal file
104
resources/app/node_modules/prosemirror-inputrules/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
# How to contribute
|
||||
|
||||
- [Getting help](#getting-help)
|
||||
- [Submitting bug reports](#submitting-bug-reports)
|
||||
- [Contributing code](#contributing-code)
|
||||
|
||||
## Getting help
|
||||
|
||||
Community discussion, questions, and informal bug reporting is done on the
|
||||
[discuss.ProseMirror forum](http://discuss.prosemirror.net).
|
||||
|
||||
## Submitting bug reports
|
||||
|
||||
Report bugs on the
|
||||
[GitHub issue tracker](http://github.com/prosemirror/prosemirror/issues).
|
||||
Before reporting a bug, please read these pointers.
|
||||
|
||||
- The issue tracker is for *bugs*, not requests for help. Questions
|
||||
should be asked on the [forum](http://discuss.prosemirror.net).
|
||||
|
||||
- Include information about the version of the code that exhibits the
|
||||
problem. For browser-related issues, include the browser and browser
|
||||
version on which the problem occurred.
|
||||
|
||||
- Mention very precisely what went wrong. "X is broken" is not a good
|
||||
bug report. What did you expect to happen? What happened instead?
|
||||
Describe the exact steps a maintainer has to take to make the
|
||||
problem occur. A screencast can be useful, but is no substitute for
|
||||
a textual description.
|
||||
|
||||
- A great way to make it easy to reproduce your problem, if it can not
|
||||
be trivially reproduced on the website demos, is to submit a script
|
||||
that triggers the issue.
|
||||
|
||||
## Contributing code
|
||||
|
||||
If you want to make a change that involves a significant overhaul of
|
||||
the code or introduces a user-visible new feature, create an
|
||||
[RFC](https://github.com/ProseMirror/rfcs/) first with your proposal.
|
||||
|
||||
- Make sure you have a [GitHub Account](https://github.com/signup/free)
|
||||
|
||||
- Fork the relevant repository
|
||||
([how to fork a repo](https://help.github.com/articles/fork-a-repo))
|
||||
|
||||
- Create a local checkout of the code. You can use the
|
||||
[main repository](https://github.com/prosemirror/prosemirror) to
|
||||
easily check out all core modules.
|
||||
|
||||
- Make your changes, and commit them
|
||||
|
||||
- Follow the code style of the rest of the project (see below). Run
|
||||
`npm run lint` (in the main repository checkout) to make sure that
|
||||
the linter is happy.
|
||||
|
||||
- If your changes are easy to test or likely to regress, add tests in
|
||||
the relevant `test/` directory. Either put them in an existing
|
||||
`test-*.js` file, if they fit there, or add a new file.
|
||||
|
||||
- Make sure all tests pass. Run `npm run test` to verify tests pass
|
||||
(you will need Node.js v6+).
|
||||
|
||||
- Submit a pull request ([how to create a pull request](https://help.github.com/articles/fork-a-repo)).
|
||||
Don't put more than one feature/fix in a single pull request.
|
||||
|
||||
By contributing code to ProseMirror you
|
||||
|
||||
- Agree to license the contributed code under the project's [MIT
|
||||
license](https://github.com/ProseMirror/prosemirror/blob/master/LICENSE).
|
||||
|
||||
- Confirm that you have the right to contribute and license the code
|
||||
in question. (Either you hold all rights on the code, or the rights
|
||||
holder has explicitly granted the right to use it like this,
|
||||
through a compatible open source license or through a direct
|
||||
agreement with you.)
|
||||
|
||||
### Coding standards
|
||||
|
||||
- ES6 syntax, targeting an ES5 runtime (i.e. don't use library
|
||||
elements added by ES6, don't use ES7/ES.next syntax).
|
||||
|
||||
- 2 spaces per indentation level, no tabs.
|
||||
|
||||
- No semicolons except when necessary.
|
||||
|
||||
- Follow the surrounding code when it comes to spacing, brace
|
||||
placement, etc.
|
||||
|
||||
- Brace-less single-statement bodies are encouraged (whenever they
|
||||
don't impact readability).
|
||||
|
||||
- [getdocs](https://github.com/marijnh/getdocs)-style doc comments
|
||||
above items that are part of the public API.
|
||||
|
||||
- When documenting non-public items, you can put the type after a
|
||||
single colon, so that getdocs doesn't pick it up and add it to the
|
||||
API reference.
|
||||
|
||||
- The linter (`npm run lint`) complains about unused variables and
|
||||
functions. Prefix their names with an underscore to muffle it.
|
||||
|
||||
- ProseMirror does *not* follow JSHint or JSLint prescribed style.
|
||||
Patches that try to 'fix' code to pass one of these linters will not
|
||||
be accepted.
|
||||
19
resources/app/node_modules/prosemirror-inputrules/LICENSE
generated
vendored
Normal file
19
resources/app/node_modules/prosemirror-inputrules/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2015-2017 by Marijn Haverbeke <marijn@haverbeke.berlin> and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
159
resources/app/node_modules/prosemirror-inputrules/dist/index.cjs
generated
vendored
Normal file
159
resources/app/node_modules/prosemirror-inputrules/dist/index.cjs
generated
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
'use strict';
|
||||
|
||||
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
||||
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
||||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
||||
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
|
||||
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
var prosemirrorState = require('prosemirror-state');
|
||||
var prosemirrorTransform = require('prosemirror-transform');
|
||||
var InputRule = _createClass(function InputRule(match, handler) {
|
||||
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
||||
_classCallCheck(this, InputRule);
|
||||
this.match = match;
|
||||
this.match = match;
|
||||
this.handler = typeof handler == "string" ? stringHandler(handler) : handler;
|
||||
this.undoable = options.undoable !== false;
|
||||
this.inCode = options.inCode || false;
|
||||
});
|
||||
function stringHandler(string) {
|
||||
return function (state, match, start, end) {
|
||||
var insert = string;
|
||||
if (match[1]) {
|
||||
var offset = match[0].lastIndexOf(match[1]);
|
||||
insert += match[0].slice(offset + match[1].length);
|
||||
start += offset;
|
||||
var cutOff = start - end;
|
||||
if (cutOff > 0) {
|
||||
insert = match[0].slice(offset - cutOff, offset) + insert;
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
return state.tr.insertText(insert, start, end);
|
||||
};
|
||||
}
|
||||
var MAX_MATCH = 500;
|
||||
function inputRules(_ref) {
|
||||
var rules = _ref.rules;
|
||||
var plugin = new prosemirrorState.Plugin({
|
||||
state: {
|
||||
init: function init() {
|
||||
return null;
|
||||
},
|
||||
apply: function apply(tr, prev) {
|
||||
var stored = tr.getMeta(this);
|
||||
if (stored) return stored;
|
||||
return tr.selectionSet || tr.docChanged ? null : prev;
|
||||
}
|
||||
},
|
||||
props: {
|
||||
handleTextInput: function handleTextInput(view, from, to, text) {
|
||||
return run(view, from, to, text, rules, plugin);
|
||||
},
|
||||
handleDOMEvents: {
|
||||
compositionend: function compositionend(view) {
|
||||
setTimeout(function () {
|
||||
var $cursor = view.state.selection.$cursor;
|
||||
if ($cursor) run(view, $cursor.pos, $cursor.pos, "", rules, plugin);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
isInputRules: true
|
||||
});
|
||||
return plugin;
|
||||
}
|
||||
function run(view, from, to, text, rules, plugin) {
|
||||
if (view.composing) return false;
|
||||
var state = view.state,
|
||||
$from = state.doc.resolve(from);
|
||||
var textBefore = $from.parent.textBetween(Math.max(0, $from.parentOffset - MAX_MATCH), $from.parentOffset, null, "\uFFFC") + text;
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
var rule = rules[i];
|
||||
if ($from.parent.type.spec.code) {
|
||||
if (!rule.inCode) continue;
|
||||
} else if (rule.inCode === "only") {
|
||||
continue;
|
||||
}
|
||||
var match = rule.match.exec(textBefore);
|
||||
var tr = match && rule.handler(state, match, from - (match[0].length - text.length), to);
|
||||
if (!tr) continue;
|
||||
if (rule.undoable) tr.setMeta(plugin, {
|
||||
transform: tr,
|
||||
from: from,
|
||||
to: to,
|
||||
text: text
|
||||
});
|
||||
view.dispatch(tr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
var undoInputRule = function undoInputRule(state, dispatch) {
|
||||
var plugins = state.plugins;
|
||||
for (var i = 0; i < plugins.length; i++) {
|
||||
var plugin = plugins[i],
|
||||
undoable = void 0;
|
||||
if (plugin.spec.isInputRules && (undoable = plugin.getState(state))) {
|
||||
if (dispatch) {
|
||||
var tr = state.tr,
|
||||
toUndo = undoable.transform;
|
||||
for (var j = toUndo.steps.length - 1; j >= 0; j--) tr.step(toUndo.steps[j].invert(toUndo.docs[j]));
|
||||
if (undoable.text) {
|
||||
var marks = tr.doc.resolve(undoable.from).marks();
|
||||
tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks));
|
||||
} else {
|
||||
tr["delete"](undoable.from, undoable.to);
|
||||
}
|
||||
dispatch(tr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
var emDash = new InputRule(/--$/, "—");
|
||||
var ellipsis = new InputRule(/\.\.\.$/, "…");
|
||||
var openDoubleQuote = new InputRule(/(?:^|[\s\{\[\(\<'"\u2018\u201C])(")$/, "“");
|
||||
var closeDoubleQuote = new InputRule(/"$/, "”");
|
||||
var openSingleQuote = new InputRule(/(?:^|[\s\{\[\(\<'"\u2018\u201C])(')$/, "‘");
|
||||
var closeSingleQuote = new InputRule(/'$/, "’");
|
||||
var smartQuotes = [openDoubleQuote, closeDoubleQuote, openSingleQuote, closeSingleQuote];
|
||||
function wrappingInputRule(regexp, nodeType) {
|
||||
var getAttrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
||||
var joinPredicate = arguments.length > 3 ? arguments[3] : undefined;
|
||||
return new InputRule(regexp, function (state, match, start, end) {
|
||||
var attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs;
|
||||
var tr = state.tr["delete"](start, end);
|
||||
var $start = tr.doc.resolve(start),
|
||||
range = $start.blockRange(),
|
||||
wrapping = range && prosemirrorTransform.findWrapping(range, nodeType, attrs);
|
||||
if (!wrapping) return null;
|
||||
tr.wrap(range, wrapping);
|
||||
var before = tr.doc.resolve(start - 1).nodeBefore;
|
||||
if (before && before.type == nodeType && prosemirrorTransform.canJoin(tr.doc, start - 1) && (!joinPredicate || joinPredicate(match, before))) tr.join(start - 1);
|
||||
return tr;
|
||||
});
|
||||
}
|
||||
function textblockTypeInputRule(regexp, nodeType) {
|
||||
var getAttrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
||||
return new InputRule(regexp, function (state, match, start, end) {
|
||||
var $start = state.doc.resolve(start);
|
||||
var attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs;
|
||||
if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), nodeType)) return null;
|
||||
return state.tr["delete"](start, end).setBlockType(start, start, nodeType, attrs);
|
||||
});
|
||||
}
|
||||
exports.InputRule = InputRule;
|
||||
exports.closeDoubleQuote = closeDoubleQuote;
|
||||
exports.closeSingleQuote = closeSingleQuote;
|
||||
exports.ellipsis = ellipsis;
|
||||
exports.emDash = emDash;
|
||||
exports.inputRules = inputRules;
|
||||
exports.openDoubleQuote = openDoubleQuote;
|
||||
exports.openSingleQuote = openSingleQuote;
|
||||
exports.smartQuotes = smartQuotes;
|
||||
exports.textblockTypeInputRule = textblockTypeInputRule;
|
||||
exports.undoInputRule = undoInputRule;
|
||||
exports.wrappingInputRule = wrappingInputRule;
|
||||
124
resources/app/node_modules/prosemirror-inputrules/dist/index.d.cts
generated
vendored
Normal file
124
resources/app/node_modules/prosemirror-inputrules/dist/index.d.cts
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
import { EditorState, Transaction, Plugin, Command } from 'prosemirror-state';
|
||||
import { NodeType, Attrs, Node } from 'prosemirror-model';
|
||||
|
||||
/**
|
||||
Input rules are regular expressions describing a piece of text
|
||||
that, when typed, causes something to happen. This might be
|
||||
changing two dashes into an emdash, wrapping a paragraph starting
|
||||
with `"> "` into a blockquote, or something entirely different.
|
||||
*/
|
||||
declare class InputRule {
|
||||
inCode: boolean | "only";
|
||||
/**
|
||||
Create an input rule. The rule applies when the user typed
|
||||
something and the text directly in front of the cursor matches
|
||||
`match`, which should end with `$`.
|
||||
|
||||
The `handler` can be a string, in which case the matched text, or
|
||||
the first matched group in the regexp, is replaced by that
|
||||
string.
|
||||
|
||||
Or a it can be a function, which will be called with the match
|
||||
array produced by
|
||||
[`RegExp.exec`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec),
|
||||
as well as the start and end of the matched range, and which can
|
||||
return a [transaction](https://prosemirror.net/docs/ref/#state.Transaction) that describes the
|
||||
rule's effect, or null to indicate the input was not handled.
|
||||
*/
|
||||
constructor(
|
||||
/**
|
||||
@internal
|
||||
*/
|
||||
match: RegExp, handler: string | ((state: EditorState, match: RegExpMatchArray, start: number, end: number) => Transaction | null), options?: {
|
||||
/**
|
||||
When set to false,
|
||||
[`undoInputRule`](https://prosemirror.net/docs/ref/#inputrules.undoInputRule) doesn't work on
|
||||
this rule.
|
||||
*/
|
||||
undoable?: boolean;
|
||||
/**
|
||||
By default, input rules will not apply inside nodes marked
|
||||
as [code](https://prosemirror.net/docs/ref/#model.NodeSpec.code). Set this to true to change
|
||||
that, or to `"only"` to _only_ match in such nodes.
|
||||
*/
|
||||
inCode?: boolean | "only";
|
||||
});
|
||||
}
|
||||
type PluginState = {
|
||||
transform: Transaction;
|
||||
from: number;
|
||||
to: number;
|
||||
text: string;
|
||||
} | null;
|
||||
/**
|
||||
Create an input rules plugin. When enabled, it will cause text
|
||||
input that matches any of the given rules to trigger the rule's
|
||||
action.
|
||||
*/
|
||||
declare function inputRules({ rules }: {
|
||||
rules: readonly InputRule[];
|
||||
}): Plugin<PluginState>;
|
||||
/**
|
||||
This is a command that will undo an input rule, if applying such a
|
||||
rule was the last thing that the user did.
|
||||
*/
|
||||
declare const undoInputRule: Command;
|
||||
|
||||
/**
|
||||
Converts double dashes to an emdash.
|
||||
*/
|
||||
declare const emDash: InputRule;
|
||||
/**
|
||||
Converts three dots to an ellipsis character.
|
||||
*/
|
||||
declare const ellipsis: InputRule;
|
||||
/**
|
||||
“Smart” opening double quotes.
|
||||
*/
|
||||
declare const openDoubleQuote: InputRule;
|
||||
/**
|
||||
“Smart” closing double quotes.
|
||||
*/
|
||||
declare const closeDoubleQuote: InputRule;
|
||||
/**
|
||||
“Smart” opening single quotes.
|
||||
*/
|
||||
declare const openSingleQuote: InputRule;
|
||||
/**
|
||||
“Smart” closing single quotes.
|
||||
*/
|
||||
declare const closeSingleQuote: InputRule;
|
||||
/**
|
||||
Smart-quote related input rules.
|
||||
*/
|
||||
declare const smartQuotes: readonly InputRule[];
|
||||
|
||||
/**
|
||||
Build an input rule for automatically wrapping a textblock when a
|
||||
given string is typed. The `regexp` argument is
|
||||
directly passed through to the `InputRule` constructor. You'll
|
||||
probably want the regexp to start with `^`, so that the pattern can
|
||||
only occur at the start of a textblock.
|
||||
|
||||
`nodeType` is the type of node to wrap in. If it needs attributes,
|
||||
you can either pass them directly, or pass a function that will
|
||||
compute them from the regular expression match.
|
||||
|
||||
By default, if there's a node with the same type above the newly
|
||||
wrapped node, the rule will try to [join](https://prosemirror.net/docs/ref/#transform.Transform.join) those
|
||||
two nodes. You can pass a join predicate, which takes a regular
|
||||
expression match and the node before the wrapped node, and can
|
||||
return a boolean to indicate whether a join should happen.
|
||||
*/
|
||||
declare function wrappingInputRule(regexp: RegExp, nodeType: NodeType, getAttrs?: Attrs | null | ((matches: RegExpMatchArray) => Attrs | null), joinPredicate?: (match: RegExpMatchArray, node: Node) => boolean): InputRule;
|
||||
/**
|
||||
Build an input rule that changes the type of a textblock when the
|
||||
matched text is typed into it. You'll usually want to start your
|
||||
regexp with `^` to that it is only matched at the start of a
|
||||
textblock. The optional `getAttrs` parameter can be used to compute
|
||||
the new node's attributes, and works the same as in the
|
||||
`wrappingInputRule` function.
|
||||
*/
|
||||
declare function textblockTypeInputRule(regexp: RegExp, nodeType: NodeType, getAttrs?: Attrs | null | ((match: RegExpMatchArray) => Attrs | null)): InputRule;
|
||||
|
||||
export { InputRule, closeDoubleQuote, closeSingleQuote, ellipsis, emDash, inputRules, openDoubleQuote, openSingleQuote, smartQuotes, textblockTypeInputRule, undoInputRule, wrappingInputRule };
|
||||
225
resources/app/node_modules/prosemirror-inputrules/dist/index.js
generated
vendored
Normal file
225
resources/app/node_modules/prosemirror-inputrules/dist/index.js
generated
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
import { Plugin } from 'prosemirror-state';
|
||||
import { findWrapping, canJoin } from 'prosemirror-transform';
|
||||
|
||||
/**
|
||||
Input rules are regular expressions describing a piece of text
|
||||
that, when typed, causes something to happen. This might be
|
||||
changing two dashes into an emdash, wrapping a paragraph starting
|
||||
with `"> "` into a blockquote, or something entirely different.
|
||||
*/
|
||||
class InputRule {
|
||||
// :: (RegExp, union<string, (state: EditorState, match: [string], start: number, end: number) → ?Transaction>)
|
||||
/**
|
||||
Create an input rule. The rule applies when the user typed
|
||||
something and the text directly in front of the cursor matches
|
||||
`match`, which should end with `$`.
|
||||
|
||||
The `handler` can be a string, in which case the matched text, or
|
||||
the first matched group in the regexp, is replaced by that
|
||||
string.
|
||||
|
||||
Or a it can be a function, which will be called with the match
|
||||
array produced by
|
||||
[`RegExp.exec`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec),
|
||||
as well as the start and end of the matched range, and which can
|
||||
return a [transaction](https://prosemirror.net/docs/ref/#state.Transaction) that describes the
|
||||
rule's effect, or null to indicate the input was not handled.
|
||||
*/
|
||||
constructor(
|
||||
/**
|
||||
@internal
|
||||
*/
|
||||
match, handler, options = {}) {
|
||||
this.match = match;
|
||||
this.match = match;
|
||||
this.handler = typeof handler == "string" ? stringHandler(handler) : handler;
|
||||
this.undoable = options.undoable !== false;
|
||||
this.inCode = options.inCode || false;
|
||||
}
|
||||
}
|
||||
function stringHandler(string) {
|
||||
return function (state, match, start, end) {
|
||||
let insert = string;
|
||||
if (match[1]) {
|
||||
let offset = match[0].lastIndexOf(match[1]);
|
||||
insert += match[0].slice(offset + match[1].length);
|
||||
start += offset;
|
||||
let cutOff = start - end;
|
||||
if (cutOff > 0) {
|
||||
insert = match[0].slice(offset - cutOff, offset) + insert;
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
return state.tr.insertText(insert, start, end);
|
||||
};
|
||||
}
|
||||
const MAX_MATCH = 500;
|
||||
/**
|
||||
Create an input rules plugin. When enabled, it will cause text
|
||||
input that matches any of the given rules to trigger the rule's
|
||||
action.
|
||||
*/
|
||||
function inputRules({ rules }) {
|
||||
let plugin = new Plugin({
|
||||
state: {
|
||||
init() { return null; },
|
||||
apply(tr, prev) {
|
||||
let stored = tr.getMeta(this);
|
||||
if (stored)
|
||||
return stored;
|
||||
return tr.selectionSet || tr.docChanged ? null : prev;
|
||||
}
|
||||
},
|
||||
props: {
|
||||
handleTextInput(view, from, to, text) {
|
||||
return run(view, from, to, text, rules, plugin);
|
||||
},
|
||||
handleDOMEvents: {
|
||||
compositionend: (view) => {
|
||||
setTimeout(() => {
|
||||
let { $cursor } = view.state.selection;
|
||||
if ($cursor)
|
||||
run(view, $cursor.pos, $cursor.pos, "", rules, plugin);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
isInputRules: true
|
||||
});
|
||||
return plugin;
|
||||
}
|
||||
function run(view, from, to, text, rules, plugin) {
|
||||
if (view.composing)
|
||||
return false;
|
||||
let state = view.state, $from = state.doc.resolve(from);
|
||||
let textBefore = $from.parent.textBetween(Math.max(0, $from.parentOffset - MAX_MATCH), $from.parentOffset, null, "\ufffc") + text;
|
||||
for (let i = 0; i < rules.length; i++) {
|
||||
let rule = rules[i];
|
||||
if ($from.parent.type.spec.code) {
|
||||
if (!rule.inCode)
|
||||
continue;
|
||||
}
|
||||
else if (rule.inCode === "only") {
|
||||
continue;
|
||||
}
|
||||
let match = rule.match.exec(textBefore);
|
||||
let tr = match && rule.handler(state, match, from - (match[0].length - text.length), to);
|
||||
if (!tr)
|
||||
continue;
|
||||
if (rule.undoable)
|
||||
tr.setMeta(plugin, { transform: tr, from, to, text });
|
||||
view.dispatch(tr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
This is a command that will undo an input rule, if applying such a
|
||||
rule was the last thing that the user did.
|
||||
*/
|
||||
const undoInputRule = (state, dispatch) => {
|
||||
let plugins = state.plugins;
|
||||
for (let i = 0; i < plugins.length; i++) {
|
||||
let plugin = plugins[i], undoable;
|
||||
if (plugin.spec.isInputRules && (undoable = plugin.getState(state))) {
|
||||
if (dispatch) {
|
||||
let tr = state.tr, toUndo = undoable.transform;
|
||||
for (let j = toUndo.steps.length - 1; j >= 0; j--)
|
||||
tr.step(toUndo.steps[j].invert(toUndo.docs[j]));
|
||||
if (undoable.text) {
|
||||
let marks = tr.doc.resolve(undoable.from).marks();
|
||||
tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks));
|
||||
}
|
||||
else {
|
||||
tr.delete(undoable.from, undoable.to);
|
||||
}
|
||||
dispatch(tr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
Converts double dashes to an emdash.
|
||||
*/
|
||||
const emDash = new InputRule(/--$/, "—");
|
||||
/**
|
||||
Converts three dots to an ellipsis character.
|
||||
*/
|
||||
const ellipsis = new InputRule(/\.\.\.$/, "…");
|
||||
/**
|
||||
“Smart” opening double quotes.
|
||||
*/
|
||||
const openDoubleQuote = new InputRule(/(?:^|[\s\{\[\(\<'"\u2018\u201C])(")$/, "“");
|
||||
/**
|
||||
“Smart” closing double quotes.
|
||||
*/
|
||||
const closeDoubleQuote = new InputRule(/"$/, "”");
|
||||
/**
|
||||
“Smart” opening single quotes.
|
||||
*/
|
||||
const openSingleQuote = new InputRule(/(?:^|[\s\{\[\(\<'"\u2018\u201C])(')$/, "‘");
|
||||
/**
|
||||
“Smart” closing single quotes.
|
||||
*/
|
||||
const closeSingleQuote = new InputRule(/'$/, "’");
|
||||
/**
|
||||
Smart-quote related input rules.
|
||||
*/
|
||||
const smartQuotes = [openDoubleQuote, closeDoubleQuote, openSingleQuote, closeSingleQuote];
|
||||
|
||||
/**
|
||||
Build an input rule for automatically wrapping a textblock when a
|
||||
given string is typed. The `regexp` argument is
|
||||
directly passed through to the `InputRule` constructor. You'll
|
||||
probably want the regexp to start with `^`, so that the pattern can
|
||||
only occur at the start of a textblock.
|
||||
|
||||
`nodeType` is the type of node to wrap in. If it needs attributes,
|
||||
you can either pass them directly, or pass a function that will
|
||||
compute them from the regular expression match.
|
||||
|
||||
By default, if there's a node with the same type above the newly
|
||||
wrapped node, the rule will try to [join](https://prosemirror.net/docs/ref/#transform.Transform.join) those
|
||||
two nodes. You can pass a join predicate, which takes a regular
|
||||
expression match and the node before the wrapped node, and can
|
||||
return a boolean to indicate whether a join should happen.
|
||||
*/
|
||||
function wrappingInputRule(regexp, nodeType, getAttrs = null, joinPredicate) {
|
||||
return new InputRule(regexp, (state, match, start, end) => {
|
||||
let attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs;
|
||||
let tr = state.tr.delete(start, end);
|
||||
let $start = tr.doc.resolve(start), range = $start.blockRange(), wrapping = range && findWrapping(range, nodeType, attrs);
|
||||
if (!wrapping)
|
||||
return null;
|
||||
tr.wrap(range, wrapping);
|
||||
let before = tr.doc.resolve(start - 1).nodeBefore;
|
||||
if (before && before.type == nodeType && canJoin(tr.doc, start - 1) &&
|
||||
(!joinPredicate || joinPredicate(match, before)))
|
||||
tr.join(start - 1);
|
||||
return tr;
|
||||
});
|
||||
}
|
||||
/**
|
||||
Build an input rule that changes the type of a textblock when the
|
||||
matched text is typed into it. You'll usually want to start your
|
||||
regexp with `^` to that it is only matched at the start of a
|
||||
textblock. The optional `getAttrs` parameter can be used to compute
|
||||
the new node's attributes, and works the same as in the
|
||||
`wrappingInputRule` function.
|
||||
*/
|
||||
function textblockTypeInputRule(regexp, nodeType, getAttrs = null) {
|
||||
return new InputRule(regexp, (state, match, start, end) => {
|
||||
let $start = state.doc.resolve(start);
|
||||
let attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs;
|
||||
if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), nodeType))
|
||||
return null;
|
||||
return state.tr
|
||||
.delete(start, end)
|
||||
.setBlockType(start, start, nodeType, attrs);
|
||||
});
|
||||
}
|
||||
|
||||
export { InputRule, closeDoubleQuote, closeSingleQuote, ellipsis, emDash, inputRules, openDoubleQuote, openSingleQuote, smartQuotes, textblockTypeInputRule, undoInputRule, wrappingInputRule };
|
||||
33
resources/app/node_modules/prosemirror-inputrules/package.json
generated
vendored
Normal file
33
resources/app/node_modules/prosemirror-inputrules/package.json
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "prosemirror-inputrules",
|
||||
"version": "1.4.0",
|
||||
"description": "Automatic transforms on text input for ProseMirror",
|
||||
"type": "module",
|
||||
"main": "dist/index.cjs",
|
||||
"module": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Marijn Haverbeke",
|
||||
"email": "marijn@haverbeke.berlin",
|
||||
"web": "http://marijnhaverbeke.nl"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/prosemirror/prosemirror-inputrules.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"prosemirror-state": "^1.0.0",
|
||||
"prosemirror-transform": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@prosemirror/buildhelper": "^0.1.5"
|
||||
}
|
||||
}
|
||||
23
resources/app/node_modules/prosemirror-inputrules/src/README.md
generated
vendored
Normal file
23
resources/app/node_modules/prosemirror-inputrules/src/README.md
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
This module defines a plugin for attaching _input rules_ to an editor,
|
||||
which can react to or transform text typed by the user. It also comes
|
||||
with a bunch of default rules that can be enabled in this plugin.
|
||||
|
||||
@InputRule
|
||||
@inputRules
|
||||
@undoInputRule
|
||||
|
||||
The module comes with a number of predefined rules:
|
||||
|
||||
@emDash
|
||||
@ellipsis
|
||||
@openDoubleQuote
|
||||
@closeDoubleQuote
|
||||
@openSingleQuote
|
||||
@closeSingleQuote
|
||||
@smartQuotes
|
||||
|
||||
These utility functions take schema-specific parameters and create
|
||||
input rules specific to that schema.
|
||||
|
||||
@wrappingInputRule
|
||||
@textblockTypeInputRule
|
||||
4
resources/app/node_modules/prosemirror-inputrules/src/index.ts
generated
vendored
Normal file
4
resources/app/node_modules/prosemirror-inputrules/src/index.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
export {InputRule, inputRules, undoInputRule} from "./inputrules"
|
||||
export {emDash, ellipsis, openDoubleQuote, closeDoubleQuote, openSingleQuote, closeSingleQuote,
|
||||
smartQuotes} from "./rules"
|
||||
export {wrappingInputRule, textblockTypeInputRule} from "./rulebuilders"
|
||||
152
resources/app/node_modules/prosemirror-inputrules/src/inputrules.ts
generated
vendored
Normal file
152
resources/app/node_modules/prosemirror-inputrules/src/inputrules.ts
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
import {Plugin, Transaction, EditorState, TextSelection, Command} from "prosemirror-state"
|
||||
import {EditorView} from "prosemirror-view"
|
||||
|
||||
/// Input rules are regular expressions describing a piece of text
|
||||
/// that, when typed, causes something to happen. This might be
|
||||
/// changing two dashes into an emdash, wrapping a paragraph starting
|
||||
/// with `"> "` into a blockquote, or something entirely different.
|
||||
export class InputRule {
|
||||
/// @internal
|
||||
handler: (state: EditorState, match: RegExpMatchArray, start: number, end: number) => Transaction | null
|
||||
|
||||
/// @internal
|
||||
undoable: boolean
|
||||
inCode: boolean | "only"
|
||||
|
||||
// :: (RegExp, union<string, (state: EditorState, match: [string], start: number, end: number) → ?Transaction>)
|
||||
/// Create an input rule. The rule applies when the user typed
|
||||
/// something and the text directly in front of the cursor matches
|
||||
/// `match`, which should end with `$`.
|
||||
///
|
||||
/// The `handler` can be a string, in which case the matched text, or
|
||||
/// the first matched group in the regexp, is replaced by that
|
||||
/// string.
|
||||
///
|
||||
/// Or a it can be a function, which will be called with the match
|
||||
/// array produced by
|
||||
/// [`RegExp.exec`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec),
|
||||
/// as well as the start and end of the matched range, and which can
|
||||
/// return a [transaction](#state.Transaction) that describes the
|
||||
/// rule's effect, or null to indicate the input was not handled.
|
||||
constructor(
|
||||
/// @internal
|
||||
readonly match: RegExp,
|
||||
handler: string | ((state: EditorState, match: RegExpMatchArray, start: number, end: number) => Transaction | null),
|
||||
options: {
|
||||
/// When set to false,
|
||||
/// [`undoInputRule`](#inputrules.undoInputRule) doesn't work on
|
||||
/// this rule.
|
||||
undoable?: boolean,
|
||||
/// By default, input rules will not apply inside nodes marked
|
||||
/// as [code](#model.NodeSpec.code). Set this to true to change
|
||||
/// that, or to `"only"` to _only_ match in such nodes.
|
||||
inCode?: boolean | "only"
|
||||
} = {}
|
||||
) {
|
||||
this.match = match
|
||||
this.handler = typeof handler == "string" ? stringHandler(handler) : handler
|
||||
this.undoable = options.undoable !== false
|
||||
this.inCode = options.inCode || false
|
||||
}
|
||||
}
|
||||
|
||||
function stringHandler(string: string) {
|
||||
return function(state: EditorState, match: RegExpMatchArray, start: number, end: number) {
|
||||
let insert = string
|
||||
if (match[1]) {
|
||||
let offset = match[0].lastIndexOf(match[1])
|
||||
insert += match[0].slice(offset + match[1].length)
|
||||
start += offset
|
||||
let cutOff = start - end
|
||||
if (cutOff > 0) {
|
||||
insert = match[0].slice(offset - cutOff, offset) + insert
|
||||
start = end
|
||||
}
|
||||
}
|
||||
return state.tr.insertText(insert, start, end)
|
||||
}
|
||||
}
|
||||
|
||||
const MAX_MATCH = 500
|
||||
|
||||
type PluginState = {transform: Transaction, from: number, to: number, text: string} | null
|
||||
|
||||
/// Create an input rules plugin. When enabled, it will cause text
|
||||
/// input that matches any of the given rules to trigger the rule's
|
||||
/// action.
|
||||
export function inputRules({rules}: {rules: readonly InputRule[]}) {
|
||||
let plugin: Plugin<PluginState> = new Plugin<PluginState>({
|
||||
state: {
|
||||
init() { return null },
|
||||
apply(this: typeof plugin, tr, prev) {
|
||||
let stored = tr.getMeta(this)
|
||||
if (stored) return stored
|
||||
return tr.selectionSet || tr.docChanged ? null : prev
|
||||
}
|
||||
},
|
||||
|
||||
props: {
|
||||
handleTextInput(view, from, to, text) {
|
||||
return run(view, from, to, text, rules, plugin)
|
||||
},
|
||||
handleDOMEvents: {
|
||||
compositionend: (view) => {
|
||||
setTimeout(() => {
|
||||
let {$cursor} = view.state.selection as TextSelection
|
||||
if ($cursor) run(view, $cursor.pos, $cursor.pos, "", rules, plugin)
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
isInputRules: true
|
||||
})
|
||||
return plugin
|
||||
}
|
||||
|
||||
function run(view: EditorView, from: number, to: number, text: string, rules: readonly InputRule[], plugin: Plugin) {
|
||||
if (view.composing) return false
|
||||
let state = view.state, $from = state.doc.resolve(from)
|
||||
let textBefore = $from.parent.textBetween(Math.max(0, $from.parentOffset - MAX_MATCH), $from.parentOffset,
|
||||
null, "\ufffc") + text
|
||||
for (let i = 0; i < rules.length; i++) {
|
||||
let rule = rules[i];
|
||||
if ($from.parent.type.spec.code) {
|
||||
if (!rule.inCode) continue
|
||||
} else if (rule.inCode === "only") {
|
||||
continue
|
||||
}
|
||||
let match = rule.match.exec(textBefore)
|
||||
let tr = match && rule.handler(state, match, from - (match[0].length - text.length), to)
|
||||
if (!tr) continue
|
||||
if (rule.undoable) tr.setMeta(plugin, {transform: tr, from, to, text})
|
||||
view.dispatch(tr)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/// This is a command that will undo an input rule, if applying such a
|
||||
/// rule was the last thing that the user did.
|
||||
export const undoInputRule: Command = (state, dispatch) => {
|
||||
let plugins = state.plugins
|
||||
for (let i = 0; i < plugins.length; i++) {
|
||||
let plugin = plugins[i], undoable
|
||||
if ((plugin.spec as any).isInputRules && (undoable = plugin.getState(state))) {
|
||||
if (dispatch) {
|
||||
let tr = state.tr, toUndo = undoable.transform
|
||||
for (let j = toUndo.steps.length - 1; j >= 0; j--)
|
||||
tr.step(toUndo.steps[j].invert(toUndo.docs[j]))
|
||||
if (undoable.text) {
|
||||
let marks = tr.doc.resolve(undoable.from).marks()
|
||||
tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks))
|
||||
} else {
|
||||
tr.delete(undoable.from, undoable.to)
|
||||
}
|
||||
dispatch(tr)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
59
resources/app/node_modules/prosemirror-inputrules/src/rulebuilders.ts
generated
vendored
Normal file
59
resources/app/node_modules/prosemirror-inputrules/src/rulebuilders.ts
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import {InputRule} from "./inputrules"
|
||||
import {findWrapping, canJoin} from "prosemirror-transform"
|
||||
import {NodeType, Node, Attrs} from "prosemirror-model"
|
||||
|
||||
/// Build an input rule for automatically wrapping a textblock when a
|
||||
/// given string is typed. The `regexp` argument is
|
||||
/// directly passed through to the `InputRule` constructor. You'll
|
||||
/// probably want the regexp to start with `^`, so that the pattern can
|
||||
/// only occur at the start of a textblock.
|
||||
///
|
||||
/// `nodeType` is the type of node to wrap in. If it needs attributes,
|
||||
/// you can either pass them directly, or pass a function that will
|
||||
/// compute them from the regular expression match.
|
||||
///
|
||||
/// By default, if there's a node with the same type above the newly
|
||||
/// wrapped node, the rule will try to [join](#transform.Transform.join) those
|
||||
/// two nodes. You can pass a join predicate, which takes a regular
|
||||
/// expression match and the node before the wrapped node, and can
|
||||
/// return a boolean to indicate whether a join should happen.
|
||||
export function wrappingInputRule(
|
||||
regexp: RegExp,
|
||||
nodeType: NodeType,
|
||||
getAttrs: Attrs | null | ((matches: RegExpMatchArray) => Attrs | null) = null,
|
||||
joinPredicate?: (match: RegExpMatchArray, node: Node) => boolean
|
||||
) {
|
||||
return new InputRule(regexp, (state, match, start, end) => {
|
||||
let attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs
|
||||
let tr = state.tr.delete(start, end)
|
||||
let $start = tr.doc.resolve(start), range = $start.blockRange(), wrapping = range && findWrapping(range, nodeType, attrs)
|
||||
if (!wrapping) return null
|
||||
tr.wrap(range!, wrapping)
|
||||
let before = tr.doc.resolve(start - 1).nodeBefore
|
||||
if (before && before.type == nodeType && canJoin(tr.doc, start - 1) &&
|
||||
(!joinPredicate || joinPredicate(match, before)))
|
||||
tr.join(start - 1)
|
||||
return tr
|
||||
})
|
||||
}
|
||||
|
||||
/// Build an input rule that changes the type of a textblock when the
|
||||
/// matched text is typed into it. You'll usually want to start your
|
||||
/// regexp with `^` to that it is only matched at the start of a
|
||||
/// textblock. The optional `getAttrs` parameter can be used to compute
|
||||
/// the new node's attributes, and works the same as in the
|
||||
/// `wrappingInputRule` function.
|
||||
export function textblockTypeInputRule(
|
||||
regexp: RegExp,
|
||||
nodeType: NodeType,
|
||||
getAttrs: Attrs | null | ((match: RegExpMatchArray) => Attrs | null) = null
|
||||
) {
|
||||
return new InputRule(regexp, (state, match, start, end) => {
|
||||
let $start = state.doc.resolve(start)
|
||||
let attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs
|
||||
if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), nodeType)) return null
|
||||
return state.tr
|
||||
.delete(start, end)
|
||||
.setBlockType(start, start, nodeType, attrs)
|
||||
})
|
||||
}
|
||||
17
resources/app/node_modules/prosemirror-inputrules/src/rules.ts
generated
vendored
Normal file
17
resources/app/node_modules/prosemirror-inputrules/src/rules.ts
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import {InputRule} from "./inputrules"
|
||||
|
||||
/// Converts double dashes to an emdash.
|
||||
export const emDash = new InputRule(/--$/, "—")
|
||||
/// Converts three dots to an ellipsis character.
|
||||
export const ellipsis = new InputRule(/\.\.\.$/, "…")
|
||||
/// “Smart” opening double quotes.
|
||||
export const openDoubleQuote = new InputRule(/(?:^|[\s\{\[\(\<'"\u2018\u201C])(")$/, "“")
|
||||
/// “Smart” closing double quotes.
|
||||
export const closeDoubleQuote = new InputRule(/"$/, "”")
|
||||
/// “Smart” opening single quotes.
|
||||
export const openSingleQuote = new InputRule(/(?:^|[\s\{\[\(\<'"\u2018\u201C])(')$/, "‘")
|
||||
/// “Smart” closing single quotes.
|
||||
export const closeSingleQuote = new InputRule(/'$/, "’")
|
||||
|
||||
/// Smart-quote related input rules.
|
||||
export const smartQuotes: readonly InputRule[] = [openDoubleQuote, closeDoubleQuote, openSingleQuote, closeSingleQuote]
|
||||
Reference in New Issue
Block a user