fix: resolve TypeScript errors in frontend build

This commit is contained in:
Hiro
2026-03-30 23:16:07 +00:00
parent b733306773
commit 24925e1acb
2941 changed files with 418042 additions and 49 deletions

8
node_modules/prosemirror-markdown/.tern-project generated vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"libs": ["browser"],
"plugins": {
"node": {},
"complete_strings": {},
"es_modules": {}
}
}

311
node_modules/prosemirror-markdown/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,311 @@
## 1.13.4 (2026-02-04)
### Bug fixes
Fix a regression that caused the serializer to crash when a block ends in a hard break.
## 1.13.3 (2026-01-20)
### Bug fixes
Properly move trailing whitespace out of marks when they end in a hard break node.
## 1.13.2 (2025-03-18)
### Bug fixes
Add a `code` flag to the code mark.
## 1.13.1 (2024-09-26)
### Bug fixes
Fix a type error caused by use of an older markdown-it type package.
## 1.13.0 (2024-05-20)
### Bug fixes
Fix the type of `MarkdownParser.parse` to be non-nullable. Add a strict option to MarkdownSerializer
### New features
The new `strict` option to `MarkdownSerializer` makes it possible to make the serializer ignore node and mark types it doesn't know.
## 1.12.0 (2023-12-11)
### Bug fixes
Block-level markup inside a heading is no longer escaped by the serializer.
Do not backslash-escape a `+` at the start of line when it isn't followed by a space. Upgrade to markdown-it 14
### New features
`MarkdownSerializerState.renderInline` now takes a parameter that controls whether block-level markup should be escaped.
Upgrade to markdown-it version 14, which provides ES modules.
## 1.11.2 (2023-08-04)
### Bug fixes
Fix some unnecessary escapes for period characters in Markdown serialization.
Only escape `#` signs if they would otherwise create a heading. Add a test for headings in list items
Fix a bug in `MarkdownSerializer` that broken expelling of whitespace from marks when the mark spanned multiple nodes.
## 1.11.1 (2023-06-30)
### Bug fixes
Allow any blocks as first child of list items to align with what Markdown itself does.
Add parse rules that clear `strong` and `em` marks when inline CSS resets it.
## 1.11.0 (2023-05-17)
### Bug fixes
Make sure blank lines at the end of code blocks are properly serialized.
Convert soft breaks (single newlines) in Markdown to spaces, rather than newlines in the ProseMirror document, because newlines tend to behave awkwardly in the editor.
Fix a bug that cause the object passed as configuration to `MarkdownSerializer` to be mutated. Add release note
Include CommonJS type declarations in the package to please new TypeScript resolution settings.
### New features
A new option to `MarkdownSerializer` allows client code to configure which node type should be treated as hard breaks during mark serialization. Remove the extra left bracket
## 1.10.1 (2022-10-28)
### Bug fixes
Don't treat the empty string the same as `null` in `wrapBlock`'s `firstDelim` argument. Check content of code blocks for any sequence of backticks
Use longer sequences of backticks when serializing a code block that contains three or more backticks in a row.
## 1.10.0 (2022-10-05)
### New features
You can now pass an optional markdown-it environment object to .
## 1.9.4 (2022-08-19)
### Bug fixes
Don't escape colon characters at the start of a line.
Escape parentheses in images and links.
Allow links to wrap emphasis markers when serializing Markdown.
## 1.9.3 (2022-07-05)
### Bug fixes
Make sure '\!' characters in front of links are escaped.
## 1.9.2 (2022-07-04)
### Bug fixes
Don't escape characters in autolinks.
Fix a bug that caused the serializer to not escape start-of-line markup when inside a list.
## 1.9.1 (2022-06-02)
### Bug fixes
Fix a bug where inline nodes with content would reset the marks in their parent node during Markdown parsing.
## 1.9.0 (2022-05-30)
### New features
Include TypeScript type declarations.
## 1.8.0 (2022-03-14)
### New features
`MarkdownSerializer` now takes an `escapeExtraCharacters` option that can be used to control backslash-escaping behavior. Fix types for new option
## 1.7.1 (2022-02-16)
### Bug fixes
Avoid escaping underscores surrounded by word characters.
## 1.7.0 (2022-01-06)
### New features
Upgrade markdown-it to version 12.
## 1.6.2 (2022-01-04)
### Bug fixes
Fix a bug where URL text in links and images was overzealously escaped.
## 1.6.1 (2021-12-16)
### Bug fixes
Fix a bug where `MarkdownParser.parse` could return null when the parsed content doesn't fit the schema.
Make sure underscores are escaped when serializing to Markdown.
## 1.6.0 (2021-09-21)
### New features
`MarkdownParser.tokenizer` is now public, for easier creation of parsers that base on other parsers.
## 1.5.2 (2021-09-03)
### Bug fixes
Serializing to Markdown now properly escapes '>' characters at the start of the line.
## 1.5.1 (2021-01-06)
### Bug fixes
The Markdown parser will now correctly set the `tight` attribute on list nodes.
## 1.5.0 (2020-07-17)
### New features
Markdown parse specs can now be specified as `noCloseToken`, which will cause the parser to treat them as a single token, rather than a pair of `_open`/`_close` tokens.
## 1.4.5 (2020-05-14)
### Bug fixes
Don't allow hard_break nodes in headings.
## 1.4.4 (2019-12-19)
### Bug fixes
Fix issue that broke parsing ordered lists with a starting number other than 1.
## 1.4.3 (2019-12-17)
### Bug fixes
Don't use short-hand angle bracket syntax when outputting self-linking URLs that are relative.
## 1.4.2 (2019-11-20)
### Bug fixes
Rename ES module files to use a .js extension, since Webpack gets confused by .mjs
## 1.4.1 (2019-11-19)
### Bug fixes
The file referred to in the package's `module` field now is compiled down to ES5.
## 1.4.0 (2019-11-08)
### New features
Add a `module` field to package json file.
## 1.3.2 (2019-10-30)
### Bug fixes
Code blocks in the schema no longer allow marks inside them.
Code blocks are now parsed with `preserveWhiteSpace: full`, preventing removal of newline characters.
## 1.3.1 (2019-06-08)
### Bug fixes
Fix a bug that could occur when parsing multiple adjacent pieces of text with the same style.
## 1.3.0 (2019-01-22)
### Bug fixes
Inline code containing backticks is now serialized wrapped in the appropriate amount of backticks.
### New features
The serializer now serializes links whose target is the same as their text content using \< \> syntax.
Mark opening and close string callbacks now get passed the mark's context (parent fragment and index).
## 1.2.2 (2018-11-22)
### Bug fixes
Hard breaks at the end of an emphasized or strong mark are no longer serialized to invalid Markdown text.
## 1.2.1 (2018-10-19)
### Bug fixes
Fixes a bug where inline mark delimiters were serialized incorrectly (the closing and opening marks were swapped, which was only noticeable when they are different).
## 1.2.0 (2018-10-08)
### Bug fixes
Fixes an issue where the Markdown serializer would escape special characters in inline code.
### New features
Upgrade the markdown-it dependency to version 8.
## 1.1.1 (2018-07-08)
### Bug fixes
Fix bug that caused superfluous backslashes to be inserted at the start of some lines when serializing to Markdown.
## 1.1.0 (2018-06-20)
### New features
You can now override the handling of softbreak tokens in a custom handler.
## 1.0.4 (2018-04-17)
### Bug fixes
Fix crash when serializing marks with line breaks inside of them.
## 1.0.3 (2018-01-10)
### Bug fixes
Fix dependency version range for prosemirror-model.
## 1.0.2 (2017-12-07)
### Bug fixes
Code blocks are always wrapped in triple backticks when serializing, to avoid parsing corner cases around indented code blocks.
## 1.0.1 (2017-11-05)
### Bug fixes
Link marks are now non-inclusive (typing after them produces non-linked text).
## 1.0.0 (2017-10-13)
First stable release.

100
node_modules/prosemirror-markdown/CONTRIBUTING.md generated vendored Normal file
View File

@@ -0,0 +1,100 @@
# 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
- 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
node_modules/prosemirror-markdown/LICENSE generated vendored Normal file
View 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.

276
node_modules/prosemirror-markdown/README.md generated vendored Normal file
View File

@@ -0,0 +1,276 @@
<h1>prosemirror-markdown</h1>
<p>[ <a href="http://prosemirror.net"><strong>WEBSITE</strong></a> | <a href="https://github.com/prosemirror/prosemirror-markdown/issues"><strong>ISSUES</strong></a> | <a href="https://discuss.prosemirror.net"><strong>FORUM</strong></a> | <a href="https://gitter.im/ProseMirror/prosemirror"><strong>GITTER</strong></a> ]</p>
<p>This is a (non-core) module for <a href="http://prosemirror.net">ProseMirror</a>.
ProseMirror is a well-behaved rich semantic content editor based on
contentEditable, with support for collaborative editing and custom
document schemas.</p>
<p>This module implements a ProseMirror
<a href="https://prosemirror.net/docs/guide/#schema">schema</a> that corresponds to
the document schema used by <a href="http://commonmark.org/">CommonMark</a>, and
a parser and serializer to convert between ProseMirror documents in
that schema and CommonMark/Markdown text.</p>
<p>This code is released under an
<a href="https://github.com/prosemirror/prosemirror/tree/master/LICENSE">MIT license</a>.
There's a <a href="http://discuss.prosemirror.net">forum</a> for general
discussion and support requests, and the
<a href="https://github.com/prosemirror/prosemirror/issues">Github bug tracker</a>
is the place to report issues.</p>
<p>We aim to be an inclusive, welcoming community. To make that explicit,
we have a <a href="http://contributor-covenant.org/version/1/1/0/">code of
conduct</a> that applies
to communication around the project.</p>
<h2>Documentation</h2>
<dl>
<dt id="schema">
<code><strong><a href="#schema">schema</a></strong>: <span class="type">Schema</span>&lt;<span class="string">&quot;doc&quot;</span> | <span class="string">&quot;paragraph&quot;</span> | <span class="string">&quot;blockquote&quot;</span> | <span class="string">&quot;horizontal_rule&quot;</span> | <span class="string">&quot;heading&quot;</span> | <span class="string">&quot;code_block&quot;</span> | <span class="string">&quot;ordered_list&quot;</span> | <span class="string">&quot;bullet_list&quot;</span> | <span class="string">&quot;list_item&quot;</span> | <span class="string">&quot;text&quot;</span> | <span class="string">&quot;image&quot;</span> | <span class="string">&quot;hard_break&quot;</span>, <span class="string">&quot;em&quot;</span> | <span class="string">&quot;strong&quot;</span> | <span class="string">&quot;link&quot;</span> | <span class="string">&quot;code&quot;</span>&gt;</code></dt>
<dd><p>Document schema for the data model used by CommonMark.</p>
</dd>
<dt id="MarkdownParser">
<h4>
<code><span class=keyword>class</span></code>
<a href="#MarkdownParser">MarkdownParser</a></h4>
</dt>
<dd><p>A configuration of a Markdown parser. Such a parser uses
<a href="https://github.com/markdown-it/markdown-it">markdown-it</a> to
tokenize a file, and then runs the custom rules it is given over
the tokens to create a ProseMirror document tree.</p>
<dl><dt id="MarkdownParser.constructor">
<code><span class=keyword>new</span> <strong><a href="#MarkdownParser.constructor">MarkdownParser</a></strong>(<a id="MarkdownParser.constructor^schema" href="#MarkdownParser.constructor^schema"><span class=param>schema</span></a>: <span class="type">Schema</span>, <a id="MarkdownParser.constructor^tokenizer" href="#MarkdownParser.constructor^tokenizer"><span class=param>tokenizer</span></a>: <span class="type">any</span>, <a id="MarkdownParser.constructor^tokens" href="#MarkdownParser.constructor^tokens"><span class=param>tokens</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><span class="type">Object</span></a>&lt;<a href="#ParseSpec"><span class="type">ParseSpec</span></a>&gt;)</code></dt>
<dd><p>Create a parser with the given configuration. You can configure
the markdown-it parser to parse the dialect you want, and provide
a description of the ProseMirror entities those tokens map to in
the <code>tokens</code> object, which maps token names to descriptions of
what to do with them. Such a description is an object, and may
have the following properties:</p>
</dd><dt id="MarkdownParser.schema">
<code><strong><a href="#MarkdownParser.schema">schema</a></strong>: <span class="type">Schema</span></code></dt>
<dd><p>The parser's document schema.</p>
</dd><dt id="MarkdownParser.tokenizer">
<code><strong><a href="#MarkdownParser.tokenizer">tokenizer</a></strong>: <span class="type">any</span></code></dt>
<dd><p>This parser's markdown-it tokenizer.</p>
</dd><dt id="MarkdownParser.tokens">
<code><strong><a href="#MarkdownParser.tokens">tokens</a></strong>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><span class="type">Object</span></a>&lt;<a href="#ParseSpec"><span class="type">ParseSpec</span></a>&gt;</code></dt>
<dd><p>The value of the <code>tokens</code> object used to construct this
parser. Can be useful to copy and modify to base other parsers
on.</p>
</dd><dt id="MarkdownParser.parse">
<code><strong><a href="#MarkdownParser.parse">parse</a></strong>(<a id="MarkdownParser.parse^text" href="#MarkdownParser.parse^text"><span class=param>text</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>) → <span class="type">any</span></code></dt>
<dd><p>Parse a string as <a href="http://commonmark.org/">CommonMark</a> markup,
and create a ProseMirror document as prescribed by this parser's
rules.</p>
</dd></dl>
</dd>
<dt id="ParseSpec">
<h4>
<code><span class=keyword>interface</span></code>
<a href="#ParseSpec">ParseSpec</a></h4>
</dt>
<dd><p>Object type used to specify how Markdown tokens should be parsed.</p>
<dl><dt id="ParseSpec.node">
<code><strong><a href="#ParseSpec.node">node</a></strong>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a></code></dt>
<dd><p>This token maps to a single node, whose type can be looked up
in the schema under the given name. Exactly one of <code>node</code>,
<code>block</code>, or <code>mark</code> must be set.</p>
</dd><dt id="ParseSpec.block">
<code><strong><a href="#ParseSpec.block">block</a></strong>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a></code></dt>
<dd><p>This token (unless <code>noCloseToken</code> is true) comes in <code>_open</code>
and <code>_close</code> variants (which are appended to the base token
name provides a the object property), and wraps a block of
content. The block should be wrapped in a node of the type
named to by the property's value. If the token does not have
<code>_open</code> or <code>_close</code>, use the <code>noCloseToken</code> option.</p>
</dd><dt id="ParseSpec.mark">
<code><strong><a href="#ParseSpec.mark">mark</a></strong>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a></code></dt>
<dd><p>This token (again, unless <code>noCloseToken</code> is true) also comes
in <code>_open</code> and <code>_close</code> variants, but should add a mark
(named by the value) to its content, rather than wrapping it
in a node.</p>
</dd><dt id="ParseSpec.attrs">
<code><strong><a href="#ParseSpec.attrs">attrs</a></strong>&#8288;?: <span class="type">Attrs</span></code></dt>
<dd><p>Attributes for the node or mark. When <code>getAttrs</code> is provided,
it takes precedence.</p>
</dd><dt id="ParseSpec.getAttrs">
<code><strong><a href="#ParseSpec.getAttrs">getAttrs</a></strong>&#8288;?: <span class=fn>fn</span>(<a id="ParseSpec.getAttrs^token" href="#ParseSpec.getAttrs^token"><span class=param>token</span></a>: <span class="type">any</span>, <a id="ParseSpec.getAttrs^tokenStream" href="#ParseSpec.getAttrs^tokenStream"><span class=param>tokenStream</span></a>: <span class="type">any</span>[], <a id="ParseSpec.getAttrs^index" href="#ParseSpec.getAttrs^index"><span class=param>index</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number"><span class="prim">number</span></a>) → <span class="type">Attrs</span></code></dt>
<dd><p>A function used to compute the attributes for the node or mark
that takes a <a href="https://markdown-it.github.io/markdown-it/#Token">markdown-it
token</a> and
returns an attribute object.</p>
</dd><dt id="ParseSpec.noCloseToken">
<code><strong><a href="#ParseSpec.noCloseToken">noCloseToken</a></strong>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean"><span class="prim">boolean</span></a></code></dt>
<dd><p>Indicates that the <a href="https://markdown-it.github.io/markdown-it/#Token">markdown-it
token</a> has
no <code>_open</code> or <code>_close</code> for the nodes. This defaults to <code>true</code>
for <code>code_inline</code>, <code>code_block</code> and <code>fence</code>.</p>
</dd><dt id="ParseSpec.ignore">
<code><strong><a href="#ParseSpec.ignore">ignore</a></strong>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean"><span class="prim">boolean</span></a></code></dt>
<dd><p>When true, ignore content for the matched token.</p>
</dd></dl>
</dd>
<dt id="defaultMarkdownParser">
<code><strong><a href="#defaultMarkdownParser">defaultMarkdownParser</a></strong>: <a href="#MarkdownParser"><span class="type">MarkdownParser</span></a></code></dt>
<dd><p>A parser parsing unextended <a href="http://commonmark.org/">CommonMark</a>,
without inline HTML, and producing a document in the basic schema.</p>
</dd>
<dt id="MarkdownSerializer">
<h4>
<code><span class=keyword>class</span></code>
<a href="#MarkdownSerializer">MarkdownSerializer</a></h4>
</dt>
<dd><p>A specification for serializing a ProseMirror document as
Markdown/CommonMark text.</p>
<dl><dt id="MarkdownSerializer.constructor">
<code><span class=keyword>new</span> <strong><a href="#MarkdownSerializer.constructor">MarkdownSerializer</a></strong>(<a id="MarkdownSerializer.constructor^nodes" href="#MarkdownSerializer.constructor^nodes"><span class=param>nodes</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><span class="type">Object</span></a>&lt;<span class=fn>fn</span>(<a id="MarkdownSerializer.constructor^nodes^state" href="#MarkdownSerializer.constructor^nodes^state"><span class=param>state</span></a>: <a href="#MarkdownSerializerState"><span class="type">MarkdownSerializerState</span></a>, <a id="MarkdownSerializer.constructor^nodes^node" href="#MarkdownSerializer.constructor^nodes^node"><span class=param>node</span></a>: <span class="type">Node</span>, <a id="MarkdownSerializer.constructor^nodes^parent" href="#MarkdownSerializer.constructor^nodes^parent"><span class=param>parent</span></a>: <span class="type">Node</span>, <a id="MarkdownSerializer.constructor^nodes^index" href="#MarkdownSerializer.constructor^nodes^index"><span class=param>index</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number"><span class="prim">number</span></a>)&gt;, <a id="MarkdownSerializer.constructor^marks" href="#MarkdownSerializer.constructor^marks"><span class=param>marks</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><span class="type">Object</span></a>&lt;<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><span class="type">Object</span></a>&gt;, <a id="MarkdownSerializer.constructor^options" href="#MarkdownSerializer.constructor^options"><span class=param>options</span></a>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><span class="type">Object</span></a><span class=defaultvalue> = {}</span>)</code></dt>
<dd><p>Construct a serializer with the given configuration. The <code>nodes</code>
object should map node names in a given schema to function that
take a serializer state and such a node, and serialize the node.</p>
<dl><dt id="MarkdownSerializer.constructor^options">
<code><strong><a href="#MarkdownSerializer.constructor^options">options</a></strong></code></dt>
<dd><dl><dt id="MarkdownSerializer.constructor^options.escapeExtraCharacters">
<code><strong><a href="#MarkdownSerializer.constructor^options.escapeExtraCharacters">escapeExtraCharacters</a></strong>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp"><span class="type">RegExp</span></a></code></dt>
<dd><p>Extra characters can be added for escaping. This is passed
directly to String.replace(), and the matching characters are
preceded by a backslash.</p>
</dd></dl></dd></dl></dd><dt id="MarkdownSerializer.nodes">
<code><strong><a href="#MarkdownSerializer.nodes">nodes</a></strong>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><span class="type">Object</span></a>&lt;<span class=fn>fn</span>(<a id="MarkdownSerializer.nodes^state" href="#MarkdownSerializer.nodes^state"><span class=param>state</span></a>: <a href="#MarkdownSerializerState"><span class="type">MarkdownSerializerState</span></a>, <a id="MarkdownSerializer.nodes^node" href="#MarkdownSerializer.nodes^node"><span class=param>node</span></a>: <span class="type">Node</span>, <a id="MarkdownSerializer.nodes^parent" href="#MarkdownSerializer.nodes^parent"><span class=param>parent</span></a>: <span class="type">Node</span>, <a id="MarkdownSerializer.nodes^index" href="#MarkdownSerializer.nodes^index"><span class=param>index</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number"><span class="prim">number</span></a>)&gt;</code></dt>
<dd><p>The node serializer functions for this serializer.</p>
</dd><dt id="MarkdownSerializer.marks">
<code><strong><a href="#MarkdownSerializer.marks">marks</a></strong>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><span class="type">Object</span></a>&lt;<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><span class="type">Object</span></a>&gt;</code></dt>
<dd><p>The mark serializer info.</p>
</dd><dt id="MarkdownSerializer.options">
<code><strong><a href="#MarkdownSerializer.options">options</a></strong>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><span class="type">Object</span></a></code></dt>
<dd><dl><dt id="MarkdownSerializer.options.escapeExtraCharacters">
<code><strong><a href="#MarkdownSerializer.options.escapeExtraCharacters">escapeExtraCharacters</a></strong>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp"><span class="type">RegExp</span></a></code></dt>
<dd><p>Extra characters can be added for escaping. This is passed
directly to String.replace(), and the matching characters are
preceded by a backslash.</p>
</dd></dl></dd><dt id="MarkdownSerializer.serialize">
<code><strong><a href="#MarkdownSerializer.serialize">serialize</a></strong>(<a id="MarkdownSerializer.serialize^content" href="#MarkdownSerializer.serialize^content"><span class=param>content</span></a>: <span class="type">Node</span>, <a id="MarkdownSerializer.serialize^options" href="#MarkdownSerializer.serialize^options"><span class=param>options</span></a>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object"><span class="type">Object</span></a><span class=defaultvalue> = {}</span>) → <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a></code></dt>
<dd><p>Serialize the content of the given node to
<a href="http://commonmark.org/">CommonMark</a>.</p>
<dl><dt id="MarkdownSerializer.serialize^options">
<code><strong><a href="#MarkdownSerializer.serialize^options">options</a></strong></code></dt>
<dd><dl><dt id="MarkdownSerializer.serialize^options.tightLists">
<code><strong><a href="#MarkdownSerializer.serialize^options.tightLists">tightLists</a></strong>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean"><span class="prim">boolean</span></a></code></dt>
<dd><p>Whether to render lists in a tight style. This can be overridden
on a node level by specifying a tight attribute on the node.
Defaults to false.</p>
</dd></dl></dd></dl></dd></dl>
</dd>
<dt id="MarkdownSerializerState">
<h4>
<code><span class=keyword>class</span></code>
<a href="#MarkdownSerializerState">MarkdownSerializerState</a></h4>
</dt>
<dd><p>This is an object used to track state and expose
methods related to markdown serialization. Instances are passed to
node and mark serialization methods (see <code>toMarkdown</code>).</p>
<dl><dt id="MarkdownSerializerState.options">
<code><strong><a href="#MarkdownSerializerState.options">options</a></strong>: {<span class=prop>tightLists</span>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean"><span class="prim">boolean</span></a>, <span class=prop>escapeExtraCharacters</span>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp"><span class="type">RegExp</span></a>}</code></dt>
<dd><p>The options passed to the serializer.</p>
</dd><dt id="MarkdownSerializerState.wrapBlock">
<code><strong><a href="#MarkdownSerializerState.wrapBlock">wrapBlock</a></strong>(<a id="MarkdownSerializerState.wrapBlock^delim" href="#MarkdownSerializerState.wrapBlock^delim"><span class=param>delim</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>, <a id="MarkdownSerializerState.wrapBlock^firstDelim" href="#MarkdownSerializerState.wrapBlock^firstDelim"><span class=param>firstDelim</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>, <a id="MarkdownSerializerState.wrapBlock^node" href="#MarkdownSerializerState.wrapBlock^node"><span class=param>node</span></a>: <span class="type">Node</span>, <a id="MarkdownSerializerState.wrapBlock^f" href="#MarkdownSerializerState.wrapBlock^f"><span class=param>f</span></a>: <span class=fn>fn</span>())</code></dt>
<dd><p>Render a block, prefixing each line with <code>delim</code>, and the first
line in <code>firstDelim</code>. <code>node</code> should be the node that is closed at
the end of the block, and <code>f</code> is a function that renders the
content of the block.</p>
</dd><dt id="MarkdownSerializerState.ensureNewLine">
<code><strong><a href="#MarkdownSerializerState.ensureNewLine">ensureNewLine</a></strong>()</code></dt>
<dd><p>Ensure the current content ends with a newline.</p>
</dd><dt id="MarkdownSerializerState.write">
<code><strong><a href="#MarkdownSerializerState.write">write</a></strong>(<a id="MarkdownSerializerState.write^content" href="#MarkdownSerializerState.write^content"><span class=param>content</span></a>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>)</code></dt>
<dd><p>Prepare the state for writing output (closing closed paragraphs,
adding delimiters, and so on), and then optionally add content
(unescaped) to the output.</p>
</dd><dt id="MarkdownSerializerState.closeBlock">
<code><strong><a href="#MarkdownSerializerState.closeBlock">closeBlock</a></strong>(<a id="MarkdownSerializerState.closeBlock^node" href="#MarkdownSerializerState.closeBlock^node"><span class=param>node</span></a>: <span class="type">Node</span>)</code></dt>
<dd><p>Close the block for the given node.</p>
</dd><dt id="MarkdownSerializerState.text">
<code><strong><a href="#MarkdownSerializerState.text">text</a></strong>(<a id="MarkdownSerializerState.text^text" href="#MarkdownSerializerState.text^text"><span class=param>text</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>, <a id="MarkdownSerializerState.text^escape" href="#MarkdownSerializerState.text^escape"><span class=param>escape</span></a>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean"><span class="prim">boolean</span></a><span class=defaultvalue> = true</span>)</code></dt>
<dd><p>Add the given text to the document. When escape is not <code>false</code>,
it will be escaped.</p>
</dd><dt id="MarkdownSerializerState.render">
<code><strong><a href="#MarkdownSerializerState.render">render</a></strong>(<a id="MarkdownSerializerState.render^node" href="#MarkdownSerializerState.render^node"><span class=param>node</span></a>: <span class="type">Node</span>, <a id="MarkdownSerializerState.render^parent" href="#MarkdownSerializerState.render^parent"><span class=param>parent</span></a>: <span class="type">Node</span>, <a id="MarkdownSerializerState.render^index" href="#MarkdownSerializerState.render^index"><span class=param>index</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number"><span class="prim">number</span></a>)</code></dt>
<dd><p>Render the given node as a block.</p>
</dd><dt id="MarkdownSerializerState.renderContent">
<code><strong><a href="#MarkdownSerializerState.renderContent">renderContent</a></strong>(<a id="MarkdownSerializerState.renderContent^parent" href="#MarkdownSerializerState.renderContent^parent"><span class=param>parent</span></a>: <span class="type">Node</span>)</code></dt>
<dd><p>Render the contents of <code>parent</code> as block nodes.</p>
</dd><dt id="MarkdownSerializerState.renderInline">
<code><strong><a href="#MarkdownSerializerState.renderInline">renderInline</a></strong>(<a id="MarkdownSerializerState.renderInline^parent" href="#MarkdownSerializerState.renderInline^parent"><span class=param>parent</span></a>: <span class="type">Node</span>)</code></dt>
<dd><p>Render the contents of <code>parent</code> as inline content.</p>
</dd><dt id="MarkdownSerializerState.renderList">
<code><strong><a href="#MarkdownSerializerState.renderList">renderList</a></strong>(<a id="MarkdownSerializerState.renderList^node" href="#MarkdownSerializerState.renderList^node"><span class=param>node</span></a>: <span class="type">Node</span>, <a id="MarkdownSerializerState.renderList^delim" href="#MarkdownSerializerState.renderList^delim"><span class=param>delim</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>, <a id="MarkdownSerializerState.renderList^firstDelim" href="#MarkdownSerializerState.renderList^firstDelim"><span class=param>firstDelim</span></a>: <span class=fn>fn</span>(<a id="MarkdownSerializerState.renderList^firstDelim^index" href="#MarkdownSerializerState.renderList^firstDelim^index"><span class=param>index</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number"><span class="prim">number</span></a>) → <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>)</code></dt>
<dd><p>Render a node's content as a list. <code>delim</code> should be the extra
indentation added to all lines except the first in an item,
<code>firstDelim</code> is a function going from an item index to a
delimiter for the first line of the item.</p>
</dd><dt id="MarkdownSerializerState.esc">
<code><strong><a href="#MarkdownSerializerState.esc">esc</a></strong>(<a id="MarkdownSerializerState.esc^str" href="#MarkdownSerializerState.esc^str"><span class=param>str</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>, <a id="MarkdownSerializerState.esc^startOfLine" href="#MarkdownSerializerState.esc^startOfLine"><span class=param>startOfLine</span></a>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean"><span class="prim">boolean</span></a><span class=defaultvalue> = false</span>) → <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a></code></dt>
<dd><p>Escape the given string so that it can safely appear in Markdown
content. If <code>startOfLine</code> is true, also escape characters that
have special meaning only at the start of the line.</p>
</dd><dt id="MarkdownSerializerState.repeat">
<code><strong><a href="#MarkdownSerializerState.repeat">repeat</a></strong>(<a id="MarkdownSerializerState.repeat^str" href="#MarkdownSerializerState.repeat^str"><span class=param>str</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>, <a id="MarkdownSerializerState.repeat^n" href="#MarkdownSerializerState.repeat^n"><span class=param>n</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number"><span class="prim">number</span></a>) → <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a></code></dt>
<dd><p>Repeat the given string <code>n</code> times.</p>
</dd><dt id="MarkdownSerializerState.markString">
<code><strong><a href="#MarkdownSerializerState.markString">markString</a></strong>(<a id="MarkdownSerializerState.markString^mark" href="#MarkdownSerializerState.markString^mark"><span class=param>mark</span></a>: <span class="type">Mark</span>, <a id="MarkdownSerializerState.markString^open" href="#MarkdownSerializerState.markString^open"><span class=param>open</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean"><span class="prim">boolean</span></a>, <a id="MarkdownSerializerState.markString^parent" href="#MarkdownSerializerState.markString^parent"><span class=param>parent</span></a>: <span class="type">Node</span>, <a id="MarkdownSerializerState.markString^index" href="#MarkdownSerializerState.markString^index"><span class=param>index</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number"><span class="prim">number</span></a>) → <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a></code></dt>
<dd><p>Get the markdown string for a given opening or closing mark.</p>
</dd><dt id="MarkdownSerializerState.getEnclosingWhitespace">
<code><strong><a href="#MarkdownSerializerState.getEnclosingWhitespace">getEnclosingWhitespace</a></strong>(<a id="MarkdownSerializerState.getEnclosingWhitespace^text" href="#MarkdownSerializerState.getEnclosingWhitespace^text"><span class=param>text</span></a>: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>) → {<span class=prop>leading</span>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>, <span class=prop>trailing</span>&#8288;?: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String"><span class="prim">string</span></a>}</code></dt>
<dd><p>Get leading and trailing whitespace from a string. Values of
leading or trailing property of the return object will be undefined
if there is no match.</p>
</dd></dl>
</dd>
<dt id="defaultMarkdownSerializer">
<code><strong><a href="#defaultMarkdownSerializer">defaultMarkdownSerializer</a></strong>: <a href="#MarkdownSerializer"><span class="type">MarkdownSerializer</span></a></code></dt>
<dd><p>A serializer for the <a href="#schema">basic schema</a>.</p>
</dd>
</dl>

966
node_modules/prosemirror-markdown/dist/index.cjs generated vendored Normal file
View File

@@ -0,0 +1,966 @@
'use strict';
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
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 _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
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); }
var prosemirrorModel = require('prosemirror-model');
var MarkdownIt = require('markdown-it');
var schema = new prosemirrorModel.Schema({
nodes: {
doc: {
content: "block+"
},
paragraph: {
content: "inline*",
group: "block",
parseDOM: [{
tag: "p"
}],
toDOM: function toDOM() {
return ["p", 0];
}
},
blockquote: {
content: "block+",
group: "block",
parseDOM: [{
tag: "blockquote"
}],
toDOM: function toDOM() {
return ["blockquote", 0];
}
},
horizontal_rule: {
group: "block",
parseDOM: [{
tag: "hr"
}],
toDOM: function toDOM() {
return ["div", ["hr"]];
}
},
heading: {
attrs: {
level: {
"default": 1
}
},
content: "(text | image)*",
group: "block",
defining: true,
parseDOM: [{
tag: "h1",
attrs: {
level: 1
}
}, {
tag: "h2",
attrs: {
level: 2
}
}, {
tag: "h3",
attrs: {
level: 3
}
}, {
tag: "h4",
attrs: {
level: 4
}
}, {
tag: "h5",
attrs: {
level: 5
}
}, {
tag: "h6",
attrs: {
level: 6
}
}],
toDOM: function toDOM(node) {
return ["h" + node.attrs.level, 0];
}
},
code_block: {
content: "text*",
group: "block",
code: true,
defining: true,
marks: "",
attrs: {
params: {
"default": ""
}
},
parseDOM: [{
tag: "pre",
preserveWhitespace: "full",
getAttrs: function getAttrs(node) {
return {
params: node.getAttribute("data-params") || ""
};
}
}],
toDOM: function toDOM(node) {
return ["pre", node.attrs.params ? {
"data-params": node.attrs.params
} : {}, ["code", 0]];
}
},
ordered_list: {
content: "list_item+",
group: "block",
attrs: {
order: {
"default": 1
},
tight: {
"default": false
}
},
parseDOM: [{
tag: "ol",
getAttrs: function getAttrs(dom) {
return {
order: dom.hasAttribute("start") ? +dom.getAttribute("start") : 1,
tight: dom.hasAttribute("data-tight")
};
}
}],
toDOM: function toDOM(node) {
return ["ol", {
start: node.attrs.order == 1 ? null : node.attrs.order,
"data-tight": node.attrs.tight ? "true" : null
}, 0];
}
},
bullet_list: {
content: "list_item+",
group: "block",
attrs: {
tight: {
"default": false
}
},
parseDOM: [{
tag: "ul",
getAttrs: function getAttrs(dom) {
return {
tight: dom.hasAttribute("data-tight")
};
}
}],
toDOM: function toDOM(node) {
return ["ul", {
"data-tight": node.attrs.tight ? "true" : null
}, 0];
}
},
list_item: {
content: "block+",
defining: true,
parseDOM: [{
tag: "li"
}],
toDOM: function toDOM() {
return ["li", 0];
}
},
text: {
group: "inline"
},
image: {
inline: true,
attrs: {
src: {},
alt: {
"default": null
},
title: {
"default": null
}
},
group: "inline",
draggable: true,
parseDOM: [{
tag: "img[src]",
getAttrs: function getAttrs(dom) {
return {
src: dom.getAttribute("src"),
title: dom.getAttribute("title"),
alt: dom.getAttribute("alt")
};
}
}],
toDOM: function toDOM(node) {
return ["img", node.attrs];
}
},
hard_break: {
inline: true,
group: "inline",
selectable: false,
parseDOM: [{
tag: "br"
}],
toDOM: function toDOM() {
return ["br"];
}
}
},
marks: {
em: {
parseDOM: [{
tag: "i"
}, {
tag: "em"
}, {
style: "font-style=italic"
}, {
style: "font-style=normal",
clearMark: function clearMark(m) {
return m.type.name == "em";
}
}],
toDOM: function toDOM() {
return ["em"];
}
},
strong: {
parseDOM: [{
tag: "strong"
}, {
tag: "b",
getAttrs: function getAttrs(node) {
return node.style.fontWeight != "normal" && null;
}
}, {
style: "font-weight=400",
clearMark: function clearMark(m) {
return m.type.name == "strong";
}
}, {
style: "font-weight",
getAttrs: function getAttrs(value) {
return /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null;
}
}],
toDOM: function toDOM() {
return ["strong"];
}
},
link: {
attrs: {
href: {},
title: {
"default": null
}
},
inclusive: false,
parseDOM: [{
tag: "a[href]",
getAttrs: function getAttrs(dom) {
return {
href: dom.getAttribute("href"),
title: dom.getAttribute("title")
};
}
}],
toDOM: function toDOM(node) {
return ["a", node.attrs];
}
},
code: {
code: true,
parseDOM: [{
tag: "code"
}],
toDOM: function toDOM() {
return ["code"];
}
}
}
});
function maybeMerge(a, b) {
if (a.isText && b.isText && prosemirrorModel.Mark.sameSet(a.marks, b.marks)) return a.withText(a.text + b.text);
}
var MarkdownParseState = function () {
function MarkdownParseState(schema, tokenHandlers) {
_classCallCheck(this, MarkdownParseState);
this.schema = schema;
this.tokenHandlers = tokenHandlers;
this.stack = [{
type: schema.topNodeType,
attrs: null,
content: [],
marks: prosemirrorModel.Mark.none
}];
}
_createClass(MarkdownParseState, [{
key: "top",
value: function top() {
return this.stack[this.stack.length - 1];
}
}, {
key: "push",
value: function push(elt) {
if (this.stack.length) this.top().content.push(elt);
}
}, {
key: "addText",
value: function addText(text) {
if (!text) return;
var top = this.top(),
nodes = top.content,
last = nodes[nodes.length - 1];
var node = this.schema.text(text, top.marks),
merged;
if (last && (merged = maybeMerge(last, node))) nodes[nodes.length - 1] = merged;else nodes.push(node);
}
}, {
key: "openMark",
value: function openMark(mark) {
var top = this.top();
top.marks = mark.addToSet(top.marks);
}
}, {
key: "closeMark",
value: function closeMark(mark) {
var top = this.top();
top.marks = mark.removeFromSet(top.marks);
}
}, {
key: "parseTokens",
value: function parseTokens(toks) {
for (var i = 0; i < toks.length; i++) {
var tok = toks[i];
var handler = this.tokenHandlers[tok.type];
if (!handler) throw new Error("Token type `" + tok.type + "` not supported by Markdown parser");
handler(this, tok, toks, i);
}
}
}, {
key: "addNode",
value: function addNode(type, attrs, content) {
var top = this.top();
var node = type.createAndFill(attrs, content, top ? top.marks : []);
if (!node) return null;
this.push(node);
return node;
}
}, {
key: "openNode",
value: function openNode(type, attrs) {
this.stack.push({
type: type,
attrs: attrs,
content: [],
marks: prosemirrorModel.Mark.none
});
}
}, {
key: "closeNode",
value: function closeNode() {
var info = this.stack.pop();
return this.addNode(info.type, info.attrs, info.content);
}
}]);
return MarkdownParseState;
}();
function attrs(spec, token, tokens, i) {
if (spec.getAttrs) return spec.getAttrs(token, tokens, i);else if (spec.attrs instanceof Function) return spec.attrs(token);else return spec.attrs;
}
function noCloseToken(spec, type) {
return spec.noCloseToken || type == "code_inline" || type == "code_block" || type == "fence";
}
function withoutTrailingNewline(str) {
return str[str.length - 1] == "\n" ? str.slice(0, str.length - 1) : str;
}
function noOp() {}
function tokenHandlers(schema, tokens) {
var handlers = Object.create(null);
var _loop = function _loop() {
var spec = tokens[type];
if (spec.block) {
var nodeType = schema.nodeType(spec.block);
if (noCloseToken(spec, type)) {
handlers[type] = function (state, tok, tokens, i) {
state.openNode(nodeType, attrs(spec, tok, tokens, i));
state.addText(withoutTrailingNewline(tok.content));
state.closeNode();
};
} else {
handlers[type + "_open"] = function (state, tok, tokens, i) {
return state.openNode(nodeType, attrs(spec, tok, tokens, i));
};
handlers[type + "_close"] = function (state) {
return state.closeNode();
};
}
} else if (spec.node) {
var _nodeType = schema.nodeType(spec.node);
handlers[type] = function (state, tok, tokens, i) {
return state.addNode(_nodeType, attrs(spec, tok, tokens, i));
};
} else if (spec.mark) {
var markType = schema.marks[spec.mark];
if (noCloseToken(spec, type)) {
handlers[type] = function (state, tok, tokens, i) {
state.openMark(markType.create(attrs(spec, tok, tokens, i)));
state.addText(withoutTrailingNewline(tok.content));
state.closeMark(markType);
};
} else {
handlers[type + "_open"] = function (state, tok, tokens, i) {
return state.openMark(markType.create(attrs(spec, tok, tokens, i)));
};
handlers[type + "_close"] = function (state) {
return state.closeMark(markType);
};
}
} else if (spec.ignore) {
if (noCloseToken(spec, type)) {
handlers[type] = noOp;
} else {
handlers[type + "_open"] = noOp;
handlers[type + "_close"] = noOp;
}
} else {
throw new RangeError("Unrecognized parsing spec " + JSON.stringify(spec));
}
};
for (var type in tokens) {
_loop();
}
handlers.text = function (state, tok) {
return state.addText(tok.content);
};
handlers.inline = function (state, tok) {
return state.parseTokens(tok.children);
};
handlers.softbreak = handlers.softbreak || function (state) {
return state.addText(" ");
};
return handlers;
}
var MarkdownParser = function () {
function MarkdownParser(schema, tokenizer, tokens) {
_classCallCheck(this, MarkdownParser);
this.schema = schema;
this.tokenizer = tokenizer;
this.tokens = tokens;
this.tokenHandlers = tokenHandlers(schema, tokens);
}
_createClass(MarkdownParser, [{
key: "parse",
value: function parse(text) {
var markdownEnv = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var state = new MarkdownParseState(this.schema, this.tokenHandlers),
doc;
state.parseTokens(this.tokenizer.parse(text, markdownEnv));
do {
doc = state.closeNode();
} while (state.stack.length);
return doc || this.schema.topNodeType.createAndFill();
}
}]);
return MarkdownParser;
}();
function listIsTight(tokens, i) {
while (++i < tokens.length) if (tokens[i].type != "list_item_open") return tokens[i].hidden;
return false;
}
var defaultMarkdownParser = new MarkdownParser(schema, MarkdownIt("commonmark", {
html: false
}), {
blockquote: {
block: "blockquote"
},
paragraph: {
block: "paragraph"
},
list_item: {
block: "list_item"
},
bullet_list: {
block: "bullet_list",
getAttrs: function getAttrs(_, tokens, i) {
return {
tight: listIsTight(tokens, i)
};
}
},
ordered_list: {
block: "ordered_list",
getAttrs: function getAttrs(tok, tokens, i) {
return {
order: +tok.attrGet("start") || 1,
tight: listIsTight(tokens, i)
};
}
},
heading: {
block: "heading",
getAttrs: function getAttrs(tok) {
return {
level: +tok.tag.slice(1)
};
}
},
code_block: {
block: "code_block",
noCloseToken: true
},
fence: {
block: "code_block",
getAttrs: function getAttrs(tok) {
return {
params: tok.info || ""
};
},
noCloseToken: true
},
hr: {
node: "horizontal_rule"
},
image: {
node: "image",
getAttrs: function getAttrs(tok) {
return {
src: tok.attrGet("src"),
title: tok.attrGet("title") || null,
alt: tok.children[0] && tok.children[0].content || null
};
}
},
hardbreak: {
node: "hard_break"
},
em: {
mark: "em"
},
strong: {
mark: "strong"
},
link: {
mark: "link",
getAttrs: function getAttrs(tok) {
return {
href: tok.attrGet("href"),
title: tok.attrGet("title") || null
};
}
},
code_inline: {
mark: "code",
noCloseToken: true
}
});
var blankMark = {
open: "",
close: "",
mixable: true
};
var MarkdownSerializer = function () {
function MarkdownSerializer(nodes, marks) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
_classCallCheck(this, MarkdownSerializer);
this.nodes = nodes;
this.marks = marks;
this.options = options;
}
_createClass(MarkdownSerializer, [{
key: "serialize",
value: function serialize(content) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
options = Object.assign({}, this.options, options);
var state = new MarkdownSerializerState(this.nodes, this.marks, options);
state.renderContent(content);
return state.out;
}
}]);
return MarkdownSerializer;
}();
var defaultMarkdownSerializer = new MarkdownSerializer({
blockquote: function blockquote(state, node) {
state.wrapBlock("> ", null, node, function () {
return state.renderContent(node);
});
},
code_block: function code_block(state, node) {
var backticks = node.textContent.match(/`{3,}/gm);
var fence = backticks ? backticks.sort().slice(-1)[0] + "`" : "```";
state.write(fence + (node.attrs.params || "") + "\n");
state.text(node.textContent, false);
state.write("\n");
state.write(fence);
state.closeBlock(node);
},
heading: function heading(state, node) {
state.write(state.repeat("#", node.attrs.level) + " ");
state.renderInline(node, false);
state.closeBlock(node);
},
horizontal_rule: function horizontal_rule(state, node) {
state.write(node.attrs.markup || "---");
state.closeBlock(node);
},
bullet_list: function bullet_list(state, node) {
state.renderList(node, " ", function () {
return (node.attrs.bullet || "*") + " ";
});
},
ordered_list: function ordered_list(state, node) {
var start = node.attrs.order || 1;
var maxW = String(start + node.childCount - 1).length;
var space = state.repeat(" ", maxW + 2);
state.renderList(node, space, function (i) {
var nStr = String(start + i);
return state.repeat(" ", maxW - nStr.length) + nStr + ". ";
});
},
list_item: function list_item(state, node) {
state.renderContent(node);
},
paragraph: function paragraph(state, node) {
state.renderInline(node);
state.closeBlock(node);
},
image: function image(state, node) {
state.write("![" + state.esc(node.attrs.alt || "") + "](" + node.attrs.src.replace(/[\(\)]/g, "\\$&") + (node.attrs.title ? ' "' + node.attrs.title.replace(/"/g, '\\"') + '"' : "") + ")");
},
hard_break: function hard_break(state, node, parent, index) {
for (var i = index + 1; i < parent.childCount; i++) if (parent.child(i).type != node.type) {
state.write("\\\n");
return;
}
},
text: function text(state, node) {
state.text(node.text, !state.inAutolink);
}
}, {
em: {
open: "*",
close: "*",
mixable: true,
expelEnclosingWhitespace: true
},
strong: {
open: "**",
close: "**",
mixable: true,
expelEnclosingWhitespace: true
},
link: {
open: function open(state, mark, parent, index) {
state.inAutolink = isPlainURL(mark, parent, index);
return state.inAutolink ? "<" : "[";
},
close: function close(state, mark, parent, index) {
var inAutolink = state.inAutolink;
state.inAutolink = undefined;
return inAutolink ? ">" : "](" + mark.attrs.href.replace(/[\(\)"]/g, "\\$&") + (mark.attrs.title ? " \"".concat(mark.attrs.title.replace(/"/g, '\\"'), "\"") : "") + ")";
},
mixable: true
},
code: {
open: function open(_state, _mark, parent, index) {
return backticksFor(parent.child(index), -1);
},
close: function close(_state, _mark, parent, index) {
return backticksFor(parent.child(index - 1), 1);
},
escape: false
}
});
function backticksFor(node, side) {
var ticks = /`+/g,
m,
len = 0;
if (node.isText) while (m = ticks.exec(node.text)) len = Math.max(len, m[0].length);
var result = len > 0 && side > 0 ? " `" : "`";
for (var i = 0; i < len; i++) result += "`";
if (len > 0 && side < 0) result += " ";
return result;
}
function isPlainURL(link, parent, index) {
if (link.attrs.title || !/^\w+:/.test(link.attrs.href)) return false;
var content = parent.child(index);
if (!content.isText || content.text != link.attrs.href || content.marks[content.marks.length - 1] != link) return false;
return index == parent.childCount - 1 || !link.isInSet(parent.child(index + 1).marks);
}
var MarkdownSerializerState = function () {
function MarkdownSerializerState(nodes, marks, options) {
_classCallCheck(this, MarkdownSerializerState);
this.nodes = nodes;
this.marks = marks;
this.options = options;
this.delim = "";
this.out = "";
this.closed = null;
this.inAutolink = undefined;
this.atBlockStart = false;
this.inTightList = false;
if (typeof this.options.tightLists == "undefined") this.options.tightLists = false;
if (typeof this.options.hardBreakNodeName == "undefined") this.options.hardBreakNodeName = "hard_break";
}
_createClass(MarkdownSerializerState, [{
key: "flushClose",
value: function flushClose() {
var size = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2;
if (this.closed) {
if (!this.atBlank()) this.out += "\n";
if (size > 1) {
var delimMin = this.delim;
var trim = /\s+$/.exec(delimMin);
if (trim) delimMin = delimMin.slice(0, delimMin.length - trim[0].length);
for (var i = 1; i < size; i++) this.out += delimMin + "\n";
}
this.closed = null;
}
}
}, {
key: "getMark",
value: function getMark(name) {
var info = this.marks[name];
if (!info) {
if (this.options.strict !== false) throw new Error("Mark type `".concat(name, "` not supported by Markdown renderer"));
info = blankMark;
}
return info;
}
}, {
key: "wrapBlock",
value: function wrapBlock(delim, firstDelim, node, f) {
var old = this.delim;
this.write(firstDelim != null ? firstDelim : delim);
this.delim += delim;
f();
this.delim = old;
this.closeBlock(node);
}
}, {
key: "atBlank",
value: function atBlank() {
return /(^|\n)$/.test(this.out);
}
}, {
key: "ensureNewLine",
value: function ensureNewLine() {
if (!this.atBlank()) this.out += "\n";
}
}, {
key: "write",
value: function write(content) {
this.flushClose();
if (this.delim && this.atBlank()) this.out += this.delim;
if (content) this.out += content;
}
}, {
key: "closeBlock",
value: function closeBlock(node) {
this.closed = node;
}
}, {
key: "text",
value: function text(_text) {
var escape = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var lines = _text.split("\n");
for (var i = 0; i < lines.length; i++) {
this.write();
if (!escape && lines[i][0] == "[" && /(^|[^\\])\!$/.test(this.out)) this.out = this.out.slice(0, this.out.length - 1) + "\\!";
this.out += escape ? this.esc(lines[i], this.atBlockStart) : lines[i];
if (i != lines.length - 1) this.out += "\n";
}
}
}, {
key: "render",
value: function render(node, parent, index) {
if (this.nodes[node.type.name]) {
this.nodes[node.type.name](this, node, parent, index);
} else {
if (this.options.strict !== false) {
throw new Error("Token type `" + node.type.name + "` not supported by Markdown renderer");
} else if (!node.type.isLeaf) {
if (node.type.inlineContent) this.renderInline(node);else this.renderContent(node);
if (node.isBlock) this.closeBlock(node);
}
}
}
}, {
key: "renderContent",
value: function renderContent(parent) {
var _this = this;
parent.forEach(function (node, _, i) {
return _this.render(node, parent, i);
});
}
}, {
key: "renderInline",
value: function renderInline(parent) {
var _this2 = this;
var fromBlockStart = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
this.atBlockStart = fromBlockStart;
var active = [],
trailing = "";
var progress = function progress(node, offset, index) {
var marks = node ? node.marks : [];
if (node && node.type.name === _this2.options.hardBreakNodeName) marks = marks.filter(function (m) {
if (index + 1 == parent.childCount) return false;
var next = parent.child(index + 1);
return m.isInSet(next.marks) && (!next.isText || /\S/.test(next.text));
});
var leading = trailing;
trailing = "";
if (node && node.isText && marks.some(function (mark) {
var info = _this2.getMark(mark.type.name);
return info && info.expelEnclosingWhitespace && !mark.isInSet(active);
})) {
var _exec = /^(\s*)(.*)$/m.exec(node.text),
_exec2 = _slicedToArray(_exec, 3),
_ = _exec2[0],
lead = _exec2[1],
rest = _exec2[2];
if (lead) {
leading += lead;
node = rest ? node.withText(rest) : null;
if (!node) marks = active;
}
}
if (node && node.isText && marks.some(function (mark) {
var info = _this2.getMark(mark.type.name);
return info && info.expelEnclosingWhitespace && !_this2.isMarkAhead(parent, index + 1, mark);
})) {
var _exec3 = /^(.*?)(\s*)$/m.exec(node.text),
_exec4 = _slicedToArray(_exec3, 3),
_2 = _exec4[0],
_rest = _exec4[1],
trail = _exec4[2];
if (trail) {
trailing = trail;
node = _rest ? node.withText(_rest) : null;
if (!node) marks = active;
}
}
var inner = marks.length ? marks[marks.length - 1] : null;
var noEsc = inner && _this2.getMark(inner.type.name).escape === false;
var len = marks.length - (noEsc ? 1 : 0);
outer: for (var i = 0; i < len; i++) {
var mark = marks[i];
if (!_this2.getMark(mark.type.name).mixable) break;
for (var j = 0; j < active.length; j++) {
var other = active[j];
if (!_this2.getMark(other.type.name).mixable) break;
if (mark.eq(other)) {
if (i > j) marks = marks.slice(0, j).concat(mark).concat(marks.slice(j, i)).concat(marks.slice(i + 1, len));else if (j > i) marks = marks.slice(0, i).concat(marks.slice(i + 1, j)).concat(mark).concat(marks.slice(j, len));
continue outer;
}
}
}
var keep = 0;
while (keep < Math.min(active.length, len) && marks[keep].eq(active[keep])) ++keep;
while (keep < active.length) _this2.text(_this2.markString(active.pop(), false, parent, index), false);
if (leading) _this2.text(leading);
if (node) {
while (active.length < len) {
var add = marks[active.length];
active.push(add);
_this2.text(_this2.markString(add, true, parent, index), false);
_this2.atBlockStart = false;
}
if (noEsc && node.isText) _this2.text(_this2.markString(inner, true, parent, index) + node.text + _this2.markString(inner, false, parent, index + 1), false);else _this2.render(node, parent, index);
_this2.atBlockStart = false;
}
if ((node === null || node === void 0 ? void 0 : node.isText) && node.nodeSize > 0) {
_this2.atBlockStart = false;
}
};
parent.forEach(progress);
progress(null, 0, parent.childCount);
this.atBlockStart = false;
}
}, {
key: "renderList",
value: function renderList(node, delim, firstDelim) {
var _this3 = this;
if (this.closed && this.closed.type == node.type) this.flushClose(3);else if (this.inTightList) this.flushClose(1);
var isTight = typeof node.attrs.tight != "undefined" ? node.attrs.tight : this.options.tightLists;
var prevTight = this.inTightList;
this.inTightList = isTight;
node.forEach(function (child, _, i) {
if (i && isTight) _this3.flushClose(1);
_this3.wrapBlock(delim, firstDelim(i), node, function () {
return _this3.render(child, node, i);
});
});
this.inTightList = prevTight;
}
}, {
key: "esc",
value: function esc(str) {
var startOfLine = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
str = str.replace(/[`*\\~\[\]_]/g, function (m, i) {
return m == "_" && i > 0 && i + 1 < str.length && str[i - 1].match(/\w/) && str[i + 1].match(/\w/) ? m : "\\" + m;
});
if (startOfLine) str = str.replace(/^(\+[ ]|[\-*>])/, "\\$&").replace(/^(\s*)(#{1,6})(\s|$)/, '$1\\$2$3').replace(/^(\s*\d+)\.\s/, "$1\\. ");
if (this.options.escapeExtraCharacters) str = str.replace(this.options.escapeExtraCharacters, "\\$&");
return str;
}
}, {
key: "quote",
value: function quote(str) {
var wrap = str.indexOf('"') == -1 ? '""' : str.indexOf("'") == -1 ? "''" : "()";
return wrap[0] + str + wrap[1];
}
}, {
key: "repeat",
value: function repeat(str, n) {
var out = "";
for (var i = 0; i < n; i++) out += str;
return out;
}
}, {
key: "markString",
value: function markString(mark, open, parent, index) {
var info = this.getMark(mark.type.name);
var value = open ? info.open : info.close;
return typeof value == "string" ? value : value(this, mark, parent, index);
}
}, {
key: "getEnclosingWhitespace",
value: function getEnclosingWhitespace(text) {
return {
leading: (text.match(/^(\s+)/) || [undefined])[0],
trailing: (text.match(/(\s+)$/) || [undefined])[0]
};
}
}, {
key: "isMarkAhead",
value: function isMarkAhead(parent, index, mark) {
for (;; index++) {
if (index >= parent.childCount) return false;
var next = parent.child(index);
if (next.type.name != this.options.hardBreakNodeName) return mark.isInSet(next.marks);
index++;
}
}
}]);
return MarkdownSerializerState;
}();
exports.MarkdownParser = MarkdownParser;
exports.MarkdownSerializer = MarkdownSerializer;
exports.MarkdownSerializerState = MarkdownSerializerState;
exports.defaultMarkdownParser = defaultMarkdownParser;
exports.defaultMarkdownSerializer = defaultMarkdownSerializer;
exports.schema = schema;

335
node_modules/prosemirror-markdown/dist/index.d.cts generated vendored Normal file
View File

@@ -0,0 +1,335 @@
import { Schema, Attrs, Node, Mark } from 'prosemirror-model';
import MarkdownIt from 'markdown-it';
import Token from 'markdown-it/lib/token.mjs';
/**
Document schema for the data model used by CommonMark.
*/
declare const schema: Schema<"blockquote" | "image" | "text" | "paragraph" | "code_block" | "doc" | "horizontal_rule" | "heading" | "ordered_list" | "bullet_list" | "list_item" | "hard_break", "link" | "code" | "em" | "strong">;
/**
Object type used to specify how Markdown tokens should be parsed.
*/
interface ParseSpec {
/**
This token maps to a single node, whose type can be looked up
in the schema under the given name. Exactly one of `node`,
`block`, or `mark` must be set.
*/
node?: string;
/**
This token (unless `noCloseToken` is true) comes in `_open`
and `_close` variants (which are appended to the base token
name provides a the object property), and wraps a block of
content. The block should be wrapped in a node of the type
named to by the property's value. If the token does not have
`_open` or `_close`, use the `noCloseToken` option.
*/
block?: string;
/**
This token (again, unless `noCloseToken` is true) also comes
in `_open` and `_close` variants, but should add a mark
(named by the value) to its content, rather than wrapping it
in a node.
*/
mark?: string;
/**
Attributes for the node or mark. When `getAttrs` is provided,
it takes precedence.
*/
attrs?: Attrs | null;
/**
A function used to compute the attributes for the node or mark
that takes a [markdown-it
token](https://markdown-it.github.io/markdown-it/#Token) and
returns an attribute object.
*/
getAttrs?: (token: Token, tokenStream: Token[], index: number) => Attrs | null;
/**
Indicates that the [markdown-it
token](https://markdown-it.github.io/markdown-it/#Token) has
no `_open` or `_close` for the nodes. This defaults to `true`
for `code_inline`, `code_block` and `fence`.
*/
noCloseToken?: boolean;
/**
When true, ignore content for the matched token.
*/
ignore?: boolean;
}
/**
A configuration of a Markdown parser. Such a parser uses
[markdown-it](https://github.com/markdown-it/markdown-it) to
tokenize a file, and then runs the custom rules it is given over
the tokens to create a ProseMirror document tree.
*/
declare class MarkdownParser {
/**
The parser's document schema.
*/
readonly schema: Schema;
/**
This parser's markdown-it tokenizer.
*/
readonly tokenizer: MarkdownIt;
/**
The value of the `tokens` object used to construct this
parser. Can be useful to copy and modify to base other parsers
on.
*/
readonly tokens: {
[name: string]: ParseSpec;
};
/**
Create a parser with the given configuration. You can configure
the markdown-it parser to parse the dialect you want, and provide
a description of the ProseMirror entities those tokens map to in
the `tokens` object, which maps token names to descriptions of
what to do with them. Such a description is an object, and may
have the following properties:
*/
constructor(
/**
The parser's document schema.
*/
schema: Schema,
/**
This parser's markdown-it tokenizer.
*/
tokenizer: MarkdownIt,
/**
The value of the `tokens` object used to construct this
parser. Can be useful to copy and modify to base other parsers
on.
*/
tokens: {
[name: string]: ParseSpec;
});
/**
Parse a string as [CommonMark](http://commonmark.org/) markup,
and create a ProseMirror document as prescribed by this parser's
rules.
The second argument, when given, is passed through to the
[Markdown
parser](https://markdown-it.github.io/markdown-it/#MarkdownIt.parse).
*/
parse(text: string, markdownEnv?: Object): Node;
}
/**
A parser parsing unextended [CommonMark](http://commonmark.org/),
without inline HTML, and producing a document in the basic schema.
*/
declare const defaultMarkdownParser: MarkdownParser;
type MarkSerializerSpec = {
/**
The string that should appear before a piece of content marked
by this mark, either directly or as a function that returns an
appropriate string.
*/
open: string | ((state: MarkdownSerializerState, mark: Mark, parent: Node, index: number) => string);
/**
The string that should appear after a piece of content marked by
this mark.
*/
close: string | ((state: MarkdownSerializerState, mark: Mark, parent: Node, index: number) => string);
/**
When `true`, this indicates that the order in which the mark's
opening and closing syntax appears relative to other mixable
marks can be varied. (For example, you can say `**a *b***` and
`*a **b***`, but not `` `a *b*` ``.)
*/
mixable?: boolean;
/**
When enabled, causes the serializer to move enclosing whitespace
from inside the marks to outside the marks. This is necessary
for emphasis marks as CommonMark does not permit enclosing
whitespace inside emphasis marks, see:
http:spec.commonmark.org/0.26/#example-330
*/
expelEnclosingWhitespace?: boolean;
/**
Can be set to `false` to disable character escaping in a mark. A
non-escaping mark has to have the highest precedence (must
always be the innermost mark).
*/
escape?: boolean;
};
/**
A specification for serializing a ProseMirror document as
Markdown/CommonMark text.
*/
declare class MarkdownSerializer {
/**
The node serializer functions for this serializer.
*/
readonly nodes: {
[node: string]: (state: MarkdownSerializerState, node: Node, parent: Node, index: number) => void;
};
/**
The mark serializer info.
*/
readonly marks: {
[mark: string]: MarkSerializerSpec;
};
readonly options: {
/**
Extra characters can be added for escaping. This is passed
directly to String.replace(), and the matching characters are
preceded by a backslash.
*/
escapeExtraCharacters?: RegExp;
/**
Specify the node name of hard breaks.
Defaults to "hard_break"
*/
hardBreakNodeName?: string;
/**
By default, the serializer raises an error when it finds a
node or mark type for which no serializer is defined. Set
this to `false` to make it just ignore such elements,
rendering only their content.
*/
strict?: boolean;
};
/**
Construct a serializer with the given configuration. The `nodes`
object should map node names in a given schema to function that
take a serializer state and such a node, and serialize the node.
*/
constructor(
/**
The node serializer functions for this serializer.
*/
nodes: {
[node: string]: (state: MarkdownSerializerState, node: Node, parent: Node, index: number) => void;
},
/**
The mark serializer info.
*/
marks: {
[mark: string]: MarkSerializerSpec;
}, options?: {
/**
Extra characters can be added for escaping. This is passed
directly to String.replace(), and the matching characters are
preceded by a backslash.
*/
escapeExtraCharacters?: RegExp;
/**
Specify the node name of hard breaks.
Defaults to "hard_break"
*/
hardBreakNodeName?: string;
/**
By default, the serializer raises an error when it finds a
node or mark type for which no serializer is defined. Set
this to `false` to make it just ignore such elements,
rendering only their content.
*/
strict?: boolean;
});
/**
Serialize the content of the given node to
[CommonMark](http://commonmark.org/).
*/
serialize(content: Node, options?: {
/**
Whether to render lists in a tight style. This can be overridden
on a node level by specifying a tight attribute on the node.
Defaults to false.
*/
tightLists?: boolean;
}): string;
}
/**
A serializer for the [basic schema](https://prosemirror.net/docs/ref/#schema).
*/
declare const defaultMarkdownSerializer: MarkdownSerializer;
/**
This is an object used to track state and expose
methods related to markdown serialization. Instances are passed to
node and mark serialization methods (see `toMarkdown`).
*/
declare class MarkdownSerializerState {
/**
The options passed to the serializer.
*/
readonly options: {
tightLists?: boolean;
escapeExtraCharacters?: RegExp;
hardBreakNodeName?: string;
strict?: boolean;
};
/**
Render a block, prefixing each line with `delim`, and the first
line in `firstDelim`. `node` should be the node that is closed at
the end of the block, and `f` is a function that renders the
content of the block.
*/
wrapBlock(delim: string, firstDelim: string | null, node: Node, f: () => void): void;
/**
Ensure the current content ends with a newline.
*/
ensureNewLine(): void;
/**
Prepare the state for writing output (closing closed paragraphs,
adding delimiters, and so on), and then optionally add content
(unescaped) to the output.
*/
write(content?: string): void;
/**
Close the block for the given node.
*/
closeBlock(node: Node): void;
/**
Add the given text to the document. When escape is not `false`,
it will be escaped.
*/
text(text: string, escape?: boolean): void;
/**
Render the given node as a block.
*/
render(node: Node, parent: Node, index: number): void;
/**
Render the contents of `parent` as block nodes.
*/
renderContent(parent: Node): void;
/**
Render the contents of `parent` as inline content.
*/
renderInline(parent: Node, fromBlockStart?: boolean): void;
/**
Render a node's content as a list. `delim` should be the extra
indentation added to all lines except the first in an item,
`firstDelim` is a function going from an item index to a
delimiter for the first line of the item.
*/
renderList(node: Node, delim: string, firstDelim: (index: number) => string): void;
/**
Escape the given string so that it can safely appear in Markdown
content. If `startOfLine` is true, also escape characters that
have special meaning only at the start of the line.
*/
esc(str: string, startOfLine?: boolean): string;
/**
Repeat the given string `n` times.
*/
repeat(str: string, n: number): string;
/**
Get the markdown string for a given opening or closing mark.
*/
markString(mark: Mark, open: boolean, parent: Node, index: number): string;
/**
Get leading and trailing whitespace from a string. Values of
leading or trailing property of the return object will be undefined
if there is no match.
*/
getEnclosingWhitespace(text: string): {
leading?: string;
trailing?: string;
};
}
export { MarkdownParser, MarkdownSerializer, MarkdownSerializerState, type ParseSpec, defaultMarkdownParser, defaultMarkdownSerializer, schema };

335
node_modules/prosemirror-markdown/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,335 @@
import { Schema, Attrs, Node, Mark } from 'prosemirror-model';
import MarkdownIt from 'markdown-it';
import Token from 'markdown-it/lib/token.mjs';
/**
Document schema for the data model used by CommonMark.
*/
declare const schema: Schema<"blockquote" | "image" | "text" | "paragraph" | "code_block" | "doc" | "horizontal_rule" | "heading" | "ordered_list" | "bullet_list" | "list_item" | "hard_break", "link" | "code" | "em" | "strong">;
/**
Object type used to specify how Markdown tokens should be parsed.
*/
interface ParseSpec {
/**
This token maps to a single node, whose type can be looked up
in the schema under the given name. Exactly one of `node`,
`block`, or `mark` must be set.
*/
node?: string;
/**
This token (unless `noCloseToken` is true) comes in `_open`
and `_close` variants (which are appended to the base token
name provides a the object property), and wraps a block of
content. The block should be wrapped in a node of the type
named to by the property's value. If the token does not have
`_open` or `_close`, use the `noCloseToken` option.
*/
block?: string;
/**
This token (again, unless `noCloseToken` is true) also comes
in `_open` and `_close` variants, but should add a mark
(named by the value) to its content, rather than wrapping it
in a node.
*/
mark?: string;
/**
Attributes for the node or mark. When `getAttrs` is provided,
it takes precedence.
*/
attrs?: Attrs | null;
/**
A function used to compute the attributes for the node or mark
that takes a [markdown-it
token](https://markdown-it.github.io/markdown-it/#Token) and
returns an attribute object.
*/
getAttrs?: (token: Token, tokenStream: Token[], index: number) => Attrs | null;
/**
Indicates that the [markdown-it
token](https://markdown-it.github.io/markdown-it/#Token) has
no `_open` or `_close` for the nodes. This defaults to `true`
for `code_inline`, `code_block` and `fence`.
*/
noCloseToken?: boolean;
/**
When true, ignore content for the matched token.
*/
ignore?: boolean;
}
/**
A configuration of a Markdown parser. Such a parser uses
[markdown-it](https://github.com/markdown-it/markdown-it) to
tokenize a file, and then runs the custom rules it is given over
the tokens to create a ProseMirror document tree.
*/
declare class MarkdownParser {
/**
The parser's document schema.
*/
readonly schema: Schema;
/**
This parser's markdown-it tokenizer.
*/
readonly tokenizer: MarkdownIt;
/**
The value of the `tokens` object used to construct this
parser. Can be useful to copy and modify to base other parsers
on.
*/
readonly tokens: {
[name: string]: ParseSpec;
};
/**
Create a parser with the given configuration. You can configure
the markdown-it parser to parse the dialect you want, and provide
a description of the ProseMirror entities those tokens map to in
the `tokens` object, which maps token names to descriptions of
what to do with them. Such a description is an object, and may
have the following properties:
*/
constructor(
/**
The parser's document schema.
*/
schema: Schema,
/**
This parser's markdown-it tokenizer.
*/
tokenizer: MarkdownIt,
/**
The value of the `tokens` object used to construct this
parser. Can be useful to copy and modify to base other parsers
on.
*/
tokens: {
[name: string]: ParseSpec;
});
/**
Parse a string as [CommonMark](http://commonmark.org/) markup,
and create a ProseMirror document as prescribed by this parser's
rules.
The second argument, when given, is passed through to the
[Markdown
parser](https://markdown-it.github.io/markdown-it/#MarkdownIt.parse).
*/
parse(text: string, markdownEnv?: Object): Node;
}
/**
A parser parsing unextended [CommonMark](http://commonmark.org/),
without inline HTML, and producing a document in the basic schema.
*/
declare const defaultMarkdownParser: MarkdownParser;
type MarkSerializerSpec = {
/**
The string that should appear before a piece of content marked
by this mark, either directly or as a function that returns an
appropriate string.
*/
open: string | ((state: MarkdownSerializerState, mark: Mark, parent: Node, index: number) => string);
/**
The string that should appear after a piece of content marked by
this mark.
*/
close: string | ((state: MarkdownSerializerState, mark: Mark, parent: Node, index: number) => string);
/**
When `true`, this indicates that the order in which the mark's
opening and closing syntax appears relative to other mixable
marks can be varied. (For example, you can say `**a *b***` and
`*a **b***`, but not `` `a *b*` ``.)
*/
mixable?: boolean;
/**
When enabled, causes the serializer to move enclosing whitespace
from inside the marks to outside the marks. This is necessary
for emphasis marks as CommonMark does not permit enclosing
whitespace inside emphasis marks, see:
http:spec.commonmark.org/0.26/#example-330
*/
expelEnclosingWhitespace?: boolean;
/**
Can be set to `false` to disable character escaping in a mark. A
non-escaping mark has to have the highest precedence (must
always be the innermost mark).
*/
escape?: boolean;
};
/**
A specification for serializing a ProseMirror document as
Markdown/CommonMark text.
*/
declare class MarkdownSerializer {
/**
The node serializer functions for this serializer.
*/
readonly nodes: {
[node: string]: (state: MarkdownSerializerState, node: Node, parent: Node, index: number) => void;
};
/**
The mark serializer info.
*/
readonly marks: {
[mark: string]: MarkSerializerSpec;
};
readonly options: {
/**
Extra characters can be added for escaping. This is passed
directly to String.replace(), and the matching characters are
preceded by a backslash.
*/
escapeExtraCharacters?: RegExp;
/**
Specify the node name of hard breaks.
Defaults to "hard_break"
*/
hardBreakNodeName?: string;
/**
By default, the serializer raises an error when it finds a
node or mark type for which no serializer is defined. Set
this to `false` to make it just ignore such elements,
rendering only their content.
*/
strict?: boolean;
};
/**
Construct a serializer with the given configuration. The `nodes`
object should map node names in a given schema to function that
take a serializer state and such a node, and serialize the node.
*/
constructor(
/**
The node serializer functions for this serializer.
*/
nodes: {
[node: string]: (state: MarkdownSerializerState, node: Node, parent: Node, index: number) => void;
},
/**
The mark serializer info.
*/
marks: {
[mark: string]: MarkSerializerSpec;
}, options?: {
/**
Extra characters can be added for escaping. This is passed
directly to String.replace(), and the matching characters are
preceded by a backslash.
*/
escapeExtraCharacters?: RegExp;
/**
Specify the node name of hard breaks.
Defaults to "hard_break"
*/
hardBreakNodeName?: string;
/**
By default, the serializer raises an error when it finds a
node or mark type for which no serializer is defined. Set
this to `false` to make it just ignore such elements,
rendering only their content.
*/
strict?: boolean;
});
/**
Serialize the content of the given node to
[CommonMark](http://commonmark.org/).
*/
serialize(content: Node, options?: {
/**
Whether to render lists in a tight style. This can be overridden
on a node level by specifying a tight attribute on the node.
Defaults to false.
*/
tightLists?: boolean;
}): string;
}
/**
A serializer for the [basic schema](https://prosemirror.net/docs/ref/#schema).
*/
declare const defaultMarkdownSerializer: MarkdownSerializer;
/**
This is an object used to track state and expose
methods related to markdown serialization. Instances are passed to
node and mark serialization methods (see `toMarkdown`).
*/
declare class MarkdownSerializerState {
/**
The options passed to the serializer.
*/
readonly options: {
tightLists?: boolean;
escapeExtraCharacters?: RegExp;
hardBreakNodeName?: string;
strict?: boolean;
};
/**
Render a block, prefixing each line with `delim`, and the first
line in `firstDelim`. `node` should be the node that is closed at
the end of the block, and `f` is a function that renders the
content of the block.
*/
wrapBlock(delim: string, firstDelim: string | null, node: Node, f: () => void): void;
/**
Ensure the current content ends with a newline.
*/
ensureNewLine(): void;
/**
Prepare the state for writing output (closing closed paragraphs,
adding delimiters, and so on), and then optionally add content
(unescaped) to the output.
*/
write(content?: string): void;
/**
Close the block for the given node.
*/
closeBlock(node: Node): void;
/**
Add the given text to the document. When escape is not `false`,
it will be escaped.
*/
text(text: string, escape?: boolean): void;
/**
Render the given node as a block.
*/
render(node: Node, parent: Node, index: number): void;
/**
Render the contents of `parent` as block nodes.
*/
renderContent(parent: Node): void;
/**
Render the contents of `parent` as inline content.
*/
renderInline(parent: Node, fromBlockStart?: boolean): void;
/**
Render a node's content as a list. `delim` should be the extra
indentation added to all lines except the first in an item,
`firstDelim` is a function going from an item index to a
delimiter for the first line of the item.
*/
renderList(node: Node, delim: string, firstDelim: (index: number) => string): void;
/**
Escape the given string so that it can safely appear in Markdown
content. If `startOfLine` is true, also escape characters that
have special meaning only at the start of the line.
*/
esc(str: string, startOfLine?: boolean): string;
/**
Repeat the given string `n` times.
*/
repeat(str: string, n: number): string;
/**
Get the markdown string for a given opening or closing mark.
*/
markString(mark: Mark, open: boolean, parent: Node, index: number): string;
/**
Get leading and trailing whitespace from a string. Values of
leading or trailing property of the return object will be undefined
if there is no match.
*/
getEnclosingWhitespace(text: string): {
leading?: string;
trailing?: string;
};
}
export { MarkdownParser, MarkdownSerializer, MarkdownSerializerState, type ParseSpec, defaultMarkdownParser, defaultMarkdownSerializer, schema };

878
node_modules/prosemirror-markdown/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,878 @@
import { Schema, Mark } from 'prosemirror-model';
import MarkdownIt from 'markdown-it';
/**
Document schema for the data model used by CommonMark.
*/
const schema = new Schema({
nodes: {
doc: {
content: "block+"
},
paragraph: {
content: "inline*",
group: "block",
parseDOM: [{ tag: "p" }],
toDOM() { return ["p", 0]; }
},
blockquote: {
content: "block+",
group: "block",
parseDOM: [{ tag: "blockquote" }],
toDOM() { return ["blockquote", 0]; }
},
horizontal_rule: {
group: "block",
parseDOM: [{ tag: "hr" }],
toDOM() { return ["div", ["hr"]]; }
},
heading: {
attrs: { level: { default: 1 } },
content: "(text | image)*",
group: "block",
defining: true,
parseDOM: [{ tag: "h1", attrs: { level: 1 } },
{ tag: "h2", attrs: { level: 2 } },
{ tag: "h3", attrs: { level: 3 } },
{ tag: "h4", attrs: { level: 4 } },
{ tag: "h5", attrs: { level: 5 } },
{ tag: "h6", attrs: { level: 6 } }],
toDOM(node) { return ["h" + node.attrs.level, 0]; }
},
code_block: {
content: "text*",
group: "block",
code: true,
defining: true,
marks: "",
attrs: { params: { default: "" } },
parseDOM: [{ tag: "pre", preserveWhitespace: "full", getAttrs: node => ({ params: node.getAttribute("data-params") || "" }) }],
toDOM(node) { return ["pre", node.attrs.params ? { "data-params": node.attrs.params } : {}, ["code", 0]]; }
},
ordered_list: {
content: "list_item+",
group: "block",
attrs: { order: { default: 1 }, tight: { default: false } },
parseDOM: [{ tag: "ol", getAttrs(dom) {
return { order: dom.hasAttribute("start") ? +dom.getAttribute("start") : 1,
tight: dom.hasAttribute("data-tight") };
} }],
toDOM(node) {
return ["ol", { start: node.attrs.order == 1 ? null : node.attrs.order,
"data-tight": node.attrs.tight ? "true" : null }, 0];
}
},
bullet_list: {
content: "list_item+",
group: "block",
attrs: { tight: { default: false } },
parseDOM: [{ tag: "ul", getAttrs: dom => ({ tight: dom.hasAttribute("data-tight") }) }],
toDOM(node) { return ["ul", { "data-tight": node.attrs.tight ? "true" : null }, 0]; }
},
list_item: {
content: "block+",
defining: true,
parseDOM: [{ tag: "li" }],
toDOM() { return ["li", 0]; }
},
text: {
group: "inline"
},
image: {
inline: true,
attrs: {
src: {},
alt: { default: null },
title: { default: null }
},
group: "inline",
draggable: true,
parseDOM: [{ tag: "img[src]", getAttrs(dom) {
return {
src: dom.getAttribute("src"),
title: dom.getAttribute("title"),
alt: dom.getAttribute("alt")
};
} }],
toDOM(node) { return ["img", node.attrs]; }
},
hard_break: {
inline: true,
group: "inline",
selectable: false,
parseDOM: [{ tag: "br" }],
toDOM() { return ["br"]; }
}
},
marks: {
em: {
parseDOM: [
{ tag: "i" }, { tag: "em" },
{ style: "font-style=italic" },
{ style: "font-style=normal", clearMark: m => m.type.name == "em" }
],
toDOM() { return ["em"]; }
},
strong: {
parseDOM: [
{ tag: "strong" },
{ tag: "b", getAttrs: node => node.style.fontWeight != "normal" && null },
{ style: "font-weight=400", clearMark: m => m.type.name == "strong" },
{ style: "font-weight", getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null }
],
toDOM() { return ["strong"]; }
},
link: {
attrs: {
href: {},
title: { default: null }
},
inclusive: false,
parseDOM: [{ tag: "a[href]", getAttrs(dom) {
return { href: dom.getAttribute("href"), title: dom.getAttribute("title") };
} }],
toDOM(node) { return ["a", node.attrs]; }
},
code: {
code: true,
parseDOM: [{ tag: "code" }],
toDOM() { return ["code"]; }
}
}
});
// @ts-ignore
function maybeMerge(a, b) {
if (a.isText && b.isText && Mark.sameSet(a.marks, b.marks))
return a.withText(a.text + b.text);
}
// Object used to track the context of a running parse.
class MarkdownParseState {
constructor(schema, tokenHandlers) {
this.schema = schema;
this.tokenHandlers = tokenHandlers;
this.stack = [{ type: schema.topNodeType, attrs: null, content: [], marks: Mark.none }];
}
top() {
return this.stack[this.stack.length - 1];
}
push(elt) {
if (this.stack.length)
this.top().content.push(elt);
}
// Adds the given text to the current position in the document,
// using the current marks as styling.
addText(text) {
if (!text)
return;
let top = this.top(), nodes = top.content, last = nodes[nodes.length - 1];
let node = this.schema.text(text, top.marks), merged;
if (last && (merged = maybeMerge(last, node)))
nodes[nodes.length - 1] = merged;
else
nodes.push(node);
}
// Adds the given mark to the set of active marks.
openMark(mark) {
let top = this.top();
top.marks = mark.addToSet(top.marks);
}
// Removes the given mark from the set of active marks.
closeMark(mark) {
let top = this.top();
top.marks = mark.removeFromSet(top.marks);
}
parseTokens(toks) {
for (let i = 0; i < toks.length; i++) {
let tok = toks[i];
let handler = this.tokenHandlers[tok.type];
if (!handler)
throw new Error("Token type `" + tok.type + "` not supported by Markdown parser");
handler(this, tok, toks, i);
}
}
// Add a node at the current position.
addNode(type, attrs, content) {
let top = this.top();
let node = type.createAndFill(attrs, content, top ? top.marks : []);
if (!node)
return null;
this.push(node);
return node;
}
// Wrap subsequent content in a node of the given type.
openNode(type, attrs) {
this.stack.push({ type: type, attrs: attrs, content: [], marks: Mark.none });
}
// Close and return the node that is currently on top of the stack.
closeNode() {
let info = this.stack.pop();
return this.addNode(info.type, info.attrs, info.content);
}
}
function attrs(spec, token, tokens, i) {
if (spec.getAttrs)
return spec.getAttrs(token, tokens, i);
// For backwards compatibility when `attrs` is a Function
else if (spec.attrs instanceof Function)
return spec.attrs(token);
else
return spec.attrs;
}
// Code content is represented as a single token with a `content`
// property in Markdown-it.
function noCloseToken(spec, type) {
return spec.noCloseToken || type == "code_inline" || type == "code_block" || type == "fence";
}
function withoutTrailingNewline(str) {
return str[str.length - 1] == "\n" ? str.slice(0, str.length - 1) : str;
}
function noOp() { }
function tokenHandlers(schema, tokens) {
let handlers = Object.create(null);
for (let type in tokens) {
let spec = tokens[type];
if (spec.block) {
let nodeType = schema.nodeType(spec.block);
if (noCloseToken(spec, type)) {
handlers[type] = (state, tok, tokens, i) => {
state.openNode(nodeType, attrs(spec, tok, tokens, i));
state.addText(withoutTrailingNewline(tok.content));
state.closeNode();
};
}
else {
handlers[type + "_open"] = (state, tok, tokens, i) => state.openNode(nodeType, attrs(spec, tok, tokens, i));
handlers[type + "_close"] = state => state.closeNode();
}
}
else if (spec.node) {
let nodeType = schema.nodeType(spec.node);
handlers[type] = (state, tok, tokens, i) => state.addNode(nodeType, attrs(spec, tok, tokens, i));
}
else if (spec.mark) {
let markType = schema.marks[spec.mark];
if (noCloseToken(spec, type)) {
handlers[type] = (state, tok, tokens, i) => {
state.openMark(markType.create(attrs(spec, tok, tokens, i)));
state.addText(withoutTrailingNewline(tok.content));
state.closeMark(markType);
};
}
else {
handlers[type + "_open"] = (state, tok, tokens, i) => state.openMark(markType.create(attrs(spec, tok, tokens, i)));
handlers[type + "_close"] = state => state.closeMark(markType);
}
}
else if (spec.ignore) {
if (noCloseToken(spec, type)) {
handlers[type] = noOp;
}
else {
handlers[type + "_open"] = noOp;
handlers[type + "_close"] = noOp;
}
}
else {
throw new RangeError("Unrecognized parsing spec " + JSON.stringify(spec));
}
}
handlers.text = (state, tok) => state.addText(tok.content);
handlers.inline = (state, tok) => state.parseTokens(tok.children);
handlers.softbreak = handlers.softbreak || (state => state.addText(" "));
return handlers;
}
/**
A configuration of a Markdown parser. Such a parser uses
[markdown-it](https://github.com/markdown-it/markdown-it) to
tokenize a file, and then runs the custom rules it is given over
the tokens to create a ProseMirror document tree.
*/
class MarkdownParser {
/**
Create a parser with the given configuration. You can configure
the markdown-it parser to parse the dialect you want, and provide
a description of the ProseMirror entities those tokens map to in
the `tokens` object, which maps token names to descriptions of
what to do with them. Such a description is an object, and may
have the following properties:
*/
constructor(
/**
The parser's document schema.
*/
schema,
/**
This parser's markdown-it tokenizer.
*/
tokenizer,
/**
The value of the `tokens` object used to construct this
parser. Can be useful to copy and modify to base other parsers
on.
*/
tokens) {
this.schema = schema;
this.tokenizer = tokenizer;
this.tokens = tokens;
this.tokenHandlers = tokenHandlers(schema, tokens);
}
/**
Parse a string as [CommonMark](http://commonmark.org/) markup,
and create a ProseMirror document as prescribed by this parser's
rules.
The second argument, when given, is passed through to the
[Markdown
parser](https://markdown-it.github.io/markdown-it/#MarkdownIt.parse).
*/
parse(text, markdownEnv = {}) {
let state = new MarkdownParseState(this.schema, this.tokenHandlers), doc;
state.parseTokens(this.tokenizer.parse(text, markdownEnv));
do {
doc = state.closeNode();
} while (state.stack.length);
return doc || this.schema.topNodeType.createAndFill();
}
}
function listIsTight(tokens, i) {
while (++i < tokens.length)
if (tokens[i].type != "list_item_open")
return tokens[i].hidden;
return false;
}
/**
A parser parsing unextended [CommonMark](http://commonmark.org/),
without inline HTML, and producing a document in the basic schema.
*/
const defaultMarkdownParser = new MarkdownParser(schema, MarkdownIt("commonmark", { html: false }), {
blockquote: { block: "blockquote" },
paragraph: { block: "paragraph" },
list_item: { block: "list_item" },
bullet_list: { block: "bullet_list", getAttrs: (_, tokens, i) => ({ tight: listIsTight(tokens, i) }) },
ordered_list: { block: "ordered_list", getAttrs: (tok, tokens, i) => ({
order: +tok.attrGet("start") || 1,
tight: listIsTight(tokens, i)
}) },
heading: { block: "heading", getAttrs: tok => ({ level: +tok.tag.slice(1) }) },
code_block: { block: "code_block", noCloseToken: true },
fence: { block: "code_block", getAttrs: tok => ({ params: tok.info || "" }), noCloseToken: true },
hr: { node: "horizontal_rule" },
image: { node: "image", getAttrs: tok => ({
src: tok.attrGet("src"),
title: tok.attrGet("title") || null,
alt: tok.children[0] && tok.children[0].content || null
}) },
hardbreak: { node: "hard_break" },
em: { mark: "em" },
strong: { mark: "strong" },
link: { mark: "link", getAttrs: tok => ({
href: tok.attrGet("href"),
title: tok.attrGet("title") || null
}) },
code_inline: { mark: "code", noCloseToken: true }
});
const blankMark = { open: "", close: "", mixable: true };
/**
A specification for serializing a ProseMirror document as
Markdown/CommonMark text.
*/
class MarkdownSerializer {
/**
Construct a serializer with the given configuration. The `nodes`
object should map node names in a given schema to function that
take a serializer state and such a node, and serialize the node.
*/
constructor(
/**
The node serializer functions for this serializer.
*/
nodes,
/**
The mark serializer info.
*/
marks, options = {}) {
this.nodes = nodes;
this.marks = marks;
this.options = options;
}
/**
Serialize the content of the given node to
[CommonMark](http://commonmark.org/).
*/
serialize(content, options = {}) {
options = Object.assign({}, this.options, options);
let state = new MarkdownSerializerState(this.nodes, this.marks, options);
state.renderContent(content);
return state.out;
}
}
/**
A serializer for the [basic schema](https://prosemirror.net/docs/ref/#schema).
*/
const defaultMarkdownSerializer = new MarkdownSerializer({
blockquote(state, node) {
state.wrapBlock("> ", null, node, () => state.renderContent(node));
},
code_block(state, node) {
// Make sure the front matter fences are longer than any dash sequence within it
const backticks = node.textContent.match(/`{3,}/gm);
const fence = backticks ? (backticks.sort().slice(-1)[0] + "`") : "```";
state.write(fence + (node.attrs.params || "") + "\n");
state.text(node.textContent, false);
// Add a newline to the current content before adding closing marker
state.write("\n");
state.write(fence);
state.closeBlock(node);
},
heading(state, node) {
state.write(state.repeat("#", node.attrs.level) + " ");
state.renderInline(node, false);
state.closeBlock(node);
},
horizontal_rule(state, node) {
state.write(node.attrs.markup || "---");
state.closeBlock(node);
},
bullet_list(state, node) {
state.renderList(node, " ", () => (node.attrs.bullet || "*") + " ");
},
ordered_list(state, node) {
let start = node.attrs.order || 1;
let maxW = String(start + node.childCount - 1).length;
let space = state.repeat(" ", maxW + 2);
state.renderList(node, space, i => {
let nStr = String(start + i);
return state.repeat(" ", maxW - nStr.length) + nStr + ". ";
});
},
list_item(state, node) {
state.renderContent(node);
},
paragraph(state, node) {
state.renderInline(node);
state.closeBlock(node);
},
image(state, node) {
state.write("![" + state.esc(node.attrs.alt || "") + "](" + node.attrs.src.replace(/[\(\)]/g, "\\$&") +
(node.attrs.title ? ' "' + node.attrs.title.replace(/"/g, '\\"') + '"' : "") + ")");
},
hard_break(state, node, parent, index) {
for (let i = index + 1; i < parent.childCount; i++)
if (parent.child(i).type != node.type) {
state.write("\\\n");
return;
}
},
text(state, node) {
state.text(node.text, !state.inAutolink);
}
}, {
em: { open: "*", close: "*", mixable: true, expelEnclosingWhitespace: true },
strong: { open: "**", close: "**", mixable: true, expelEnclosingWhitespace: true },
link: {
open(state, mark, parent, index) {
state.inAutolink = isPlainURL(mark, parent, index);
return state.inAutolink ? "<" : "[";
},
close(state, mark, parent, index) {
let { inAutolink } = state;
state.inAutolink = undefined;
return inAutolink ? ">"
: "](" + mark.attrs.href.replace(/[\(\)"]/g, "\\$&") + (mark.attrs.title ? ` "${mark.attrs.title.replace(/"/g, '\\"')}"` : "") + ")";
},
mixable: true
},
code: { open(_state, _mark, parent, index) { return backticksFor(parent.child(index), -1); },
close(_state, _mark, parent, index) { return backticksFor(parent.child(index - 1), 1); },
escape: false }
});
function backticksFor(node, side) {
let ticks = /`+/g, m, len = 0;
if (node.isText)
while (m = ticks.exec(node.text))
len = Math.max(len, m[0].length);
let result = len > 0 && side > 0 ? " `" : "`";
for (let i = 0; i < len; i++)
result += "`";
if (len > 0 && side < 0)
result += " ";
return result;
}
function isPlainURL(link, parent, index) {
if (link.attrs.title || !/^\w+:/.test(link.attrs.href))
return false;
let content = parent.child(index);
if (!content.isText || content.text != link.attrs.href || content.marks[content.marks.length - 1] != link)
return false;
return index == parent.childCount - 1 || !link.isInSet(parent.child(index + 1).marks);
}
/**
This is an object used to track state and expose
methods related to markdown serialization. Instances are passed to
node and mark serialization methods (see `toMarkdown`).
*/
class MarkdownSerializerState {
/**
@internal
*/
constructor(
/**
@internal
*/
nodes,
/**
@internal
*/
marks,
/**
The options passed to the serializer.
*/
options) {
this.nodes = nodes;
this.marks = marks;
this.options = options;
/**
@internal
*/
this.delim = "";
/**
@internal
*/
this.out = "";
/**
@internal
*/
this.closed = null;
/**
@internal
*/
this.inAutolink = undefined;
/**
@internal
*/
this.atBlockStart = false;
/**
@internal
*/
this.inTightList = false;
if (typeof this.options.tightLists == "undefined")
this.options.tightLists = false;
if (typeof this.options.hardBreakNodeName == "undefined")
this.options.hardBreakNodeName = "hard_break";
}
/**
@internal
*/
flushClose(size = 2) {
if (this.closed) {
if (!this.atBlank())
this.out += "\n";
if (size > 1) {
let delimMin = this.delim;
let trim = /\s+$/.exec(delimMin);
if (trim)
delimMin = delimMin.slice(0, delimMin.length - trim[0].length);
for (let i = 1; i < size; i++)
this.out += delimMin + "\n";
}
this.closed = null;
}
}
/**
@internal
*/
getMark(name) {
let info = this.marks[name];
if (!info) {
if (this.options.strict !== false)
throw new Error(`Mark type \`${name}\` not supported by Markdown renderer`);
info = blankMark;
}
return info;
}
/**
Render a block, prefixing each line with `delim`, and the first
line in `firstDelim`. `node` should be the node that is closed at
the end of the block, and `f` is a function that renders the
content of the block.
*/
wrapBlock(delim, firstDelim, node, f) {
let old = this.delim;
this.write(firstDelim != null ? firstDelim : delim);
this.delim += delim;
f();
this.delim = old;
this.closeBlock(node);
}
/**
@internal
*/
atBlank() {
return /(^|\n)$/.test(this.out);
}
/**
Ensure the current content ends with a newline.
*/
ensureNewLine() {
if (!this.atBlank())
this.out += "\n";
}
/**
Prepare the state for writing output (closing closed paragraphs,
adding delimiters, and so on), and then optionally add content
(unescaped) to the output.
*/
write(content) {
this.flushClose();
if (this.delim && this.atBlank())
this.out += this.delim;
if (content)
this.out += content;
}
/**
Close the block for the given node.
*/
closeBlock(node) {
this.closed = node;
}
/**
Add the given text to the document. When escape is not `false`,
it will be escaped.
*/
text(text, escape = true) {
let lines = text.split("\n");
for (let i = 0; i < lines.length; i++) {
this.write();
// Escape exclamation marks in front of links
if (!escape && lines[i][0] == "[" && /(^|[^\\])\!$/.test(this.out))
this.out = this.out.slice(0, this.out.length - 1) + "\\!";
this.out += escape ? this.esc(lines[i], this.atBlockStart) : lines[i];
if (i != lines.length - 1)
this.out += "\n";
}
}
/**
Render the given node as a block.
*/
render(node, parent, index) {
if (this.nodes[node.type.name]) {
this.nodes[node.type.name](this, node, parent, index);
}
else {
if (this.options.strict !== false) {
throw new Error("Token type `" + node.type.name + "` not supported by Markdown renderer");
}
else if (!node.type.isLeaf) {
if (node.type.inlineContent)
this.renderInline(node);
else
this.renderContent(node);
if (node.isBlock)
this.closeBlock(node);
}
}
}
/**
Render the contents of `parent` as block nodes.
*/
renderContent(parent) {
parent.forEach((node, _, i) => this.render(node, parent, i));
}
/**
Render the contents of `parent` as inline content.
*/
renderInline(parent, fromBlockStart = true) {
this.atBlockStart = fromBlockStart;
let active = [], trailing = "";
let progress = (node, offset, index) => {
let marks = node ? node.marks : [];
// Remove marks from `hard_break` that are the last node inside
// that mark to prevent parser edge cases with new lines just
// before closing marks.
if (node && node.type.name === this.options.hardBreakNodeName)
marks = marks.filter(m => {
if (index + 1 == parent.childCount)
return false;
let next = parent.child(index + 1);
return m.isInSet(next.marks) && (!next.isText || /\S/.test(next.text));
});
let leading = trailing;
trailing = "";
// If whitespace has to be expelled from the node, adjust
// leading and trailing accordingly.
if (node && node.isText && marks.some(mark => {
let info = this.getMark(mark.type.name);
return info && info.expelEnclosingWhitespace && !mark.isInSet(active);
})) {
let [_, lead, rest] = /^(\s*)(.*)$/m.exec(node.text);
if (lead) {
leading += lead;
node = rest ? node.withText(rest) : null;
if (!node)
marks = active;
}
}
if (node && node.isText && marks.some(mark => {
let info = this.getMark(mark.type.name);
return info && info.expelEnclosingWhitespace && !this.isMarkAhead(parent, index + 1, mark);
})) {
let [_, rest, trail] = /^(.*?)(\s*)$/m.exec(node.text);
if (trail) {
trailing = trail;
node = rest ? node.withText(rest) : null;
if (!node)
marks = active;
}
}
let inner = marks.length ? marks[marks.length - 1] : null;
let noEsc = inner && this.getMark(inner.type.name).escape === false;
let len = marks.length - (noEsc ? 1 : 0);
// Try to reorder 'mixable' marks, such as em and strong, which
// in Markdown may be opened and closed in different order, so
// that order of the marks for the token matches the order in
// active.
outer: for (let i = 0; i < len; i++) {
let mark = marks[i];
if (!this.getMark(mark.type.name).mixable)
break;
for (let j = 0; j < active.length; j++) {
let other = active[j];
if (!this.getMark(other.type.name).mixable)
break;
if (mark.eq(other)) {
if (i > j)
marks = marks.slice(0, j).concat(mark).concat(marks.slice(j, i)).concat(marks.slice(i + 1, len));
else if (j > i)
marks = marks.slice(0, i).concat(marks.slice(i + 1, j)).concat(mark).concat(marks.slice(j, len));
continue outer;
}
}
}
// Find the prefix of the mark set that didn't change
let keep = 0;
while (keep < Math.min(active.length, len) && marks[keep].eq(active[keep]))
++keep;
// Close the marks that need to be closed
while (keep < active.length)
this.text(this.markString(active.pop(), false, parent, index), false);
// Output any previously expelled trailing whitespace outside the marks
if (leading)
this.text(leading);
// Open the marks that need to be opened
if (node) {
while (active.length < len) {
let add = marks[active.length];
active.push(add);
this.text(this.markString(add, true, parent, index), false);
this.atBlockStart = false;
}
// Render the node. Special case code marks, since their content
// may not be escaped.
if (noEsc && node.isText)
this.text(this.markString(inner, true, parent, index) + node.text +
this.markString(inner, false, parent, index + 1), false);
else
this.render(node, parent, index);
this.atBlockStart = false;
}
// After the first non-empty text node is rendered, the end of output
// is no longer at block start.
//
// FIXME: If a non-text node writes something to the output for this
// block, the end of output is also no longer at block start. But how
// can we detect that?
if ((node === null || node === void 0 ? void 0 : node.isText) && node.nodeSize > 0) {
this.atBlockStart = false;
}
};
parent.forEach(progress);
progress(null, 0, parent.childCount);
this.atBlockStart = false;
}
/**
Render a node's content as a list. `delim` should be the extra
indentation added to all lines except the first in an item,
`firstDelim` is a function going from an item index to a
delimiter for the first line of the item.
*/
renderList(node, delim, firstDelim) {
if (this.closed && this.closed.type == node.type)
this.flushClose(3);
else if (this.inTightList)
this.flushClose(1);
let isTight = typeof node.attrs.tight != "undefined" ? node.attrs.tight : this.options.tightLists;
let prevTight = this.inTightList;
this.inTightList = isTight;
node.forEach((child, _, i) => {
if (i && isTight)
this.flushClose(1);
this.wrapBlock(delim, firstDelim(i), node, () => this.render(child, node, i));
});
this.inTightList = prevTight;
}
/**
Escape the given string so that it can safely appear in Markdown
content. If `startOfLine` is true, also escape characters that
have special meaning only at the start of the line.
*/
esc(str, startOfLine = false) {
str = str.replace(/[`*\\~\[\]_]/g, (m, i) => m == "_" && i > 0 && i + 1 < str.length && str[i - 1].match(/\w/) && str[i + 1].match(/\w/) ? m : "\\" + m);
if (startOfLine)
str = str.replace(/^(\+[ ]|[\-*>])/, "\\$&").replace(/^(\s*)(#{1,6})(\s|$)/, '$1\\$2$3').replace(/^(\s*\d+)\.\s/, "$1\\. ");
if (this.options.escapeExtraCharacters)
str = str.replace(this.options.escapeExtraCharacters, "\\$&");
return str;
}
/**
@internal
*/
quote(str) {
let wrap = str.indexOf('"') == -1 ? '""' : str.indexOf("'") == -1 ? "''" : "()";
return wrap[0] + str + wrap[1];
}
/**
Repeat the given string `n` times.
*/
repeat(str, n) {
let out = "";
for (let i = 0; i < n; i++)
out += str;
return out;
}
/**
Get the markdown string for a given opening or closing mark.
*/
markString(mark, open, parent, index) {
let info = this.getMark(mark.type.name);
let value = open ? info.open : info.close;
return typeof value == "string" ? value : value(this, mark, parent, index);
}
/**
Get leading and trailing whitespace from a string. Values of
leading or trailing property of the return object will be undefined
if there is no match.
*/
getEnclosingWhitespace(text) {
return {
leading: (text.match(/^(\s+)/) || [undefined])[0],
trailing: (text.match(/(\s+)$/) || [undefined])[0]
};
}
/**
@internal
*/
isMarkAhead(parent, index, mark) {
for (;; index++) {
if (index >= parent.childCount)
return false;
let next = parent.child(index);
if (next.type.name != this.options.hardBreakNodeName)
return mark.isInSet(next.marks);
index++;
}
}
}
export { MarkdownParser, MarkdownSerializer, MarkdownSerializerState, defaultMarkdownParser, defaultMarkdownSerializer, schema };

40
node_modules/prosemirror-markdown/package.json generated vendored Normal file
View File

@@ -0,0 +1,40 @@
{
"name": "prosemirror-markdown",
"version": "1.13.4",
"description": "ProseMirror Markdown integration",
"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-markdown.git"
},
"dependencies": {
"markdown-it": "^14.0.0",
"prosemirror-model": "^1.25.0",
"@types/markdown-it": "^14.0.0"
},
"devDependencies": {
"@prosemirror/buildhelper": "^0.1.5",
"prosemirror-test-builder": "^1.0.0",
"punycode": "^1.4.0"
},
"scripts": {
"test": "pm-runtests",
"prepare": "pm-buildhelper src/index.ts"
}
}

42
node_modules/prosemirror-markdown/src/README.md generated vendored Normal file
View File

@@ -0,0 +1,42 @@
# prosemirror-markdown
[ [**WEBSITE**](http://prosemirror.net) | [**ISSUES**](https://github.com/prosemirror/prosemirror-markdown/issues) | [**FORUM**](https://discuss.prosemirror.net) | [**GITTER**](https://gitter.im/ProseMirror/prosemirror) ]
This is a (non-core) module for [ProseMirror](http://prosemirror.net).
ProseMirror is a well-behaved rich semantic content editor based on
contentEditable, with support for collaborative editing and custom
document schemas.
This module implements a ProseMirror
[schema](https://prosemirror.net/docs/guide/#schema) that corresponds to
the document schema used by [CommonMark](http://commonmark.org/), and
a parser and serializer to convert between ProseMirror documents in
that schema and CommonMark/Markdown text.
This code is released under an
[MIT license](https://github.com/prosemirror/prosemirror/tree/master/LICENSE).
There's a [forum](http://discuss.prosemirror.net) for general
discussion and support requests, and the
[Github bug tracker](https://github.com/prosemirror/prosemirror/issues)
is the place to report issues.
We aim to be an inclusive, welcoming community. To make that explicit,
we have a [code of
conduct](http://contributor-covenant.org/version/1/1/0/) that applies
to communication around the project.
## Documentation
@schema
@MarkdownParser
@ParseSpec
@defaultMarkdownParser
@MarkdownSerializer
@MarkdownSerializerState
@defaultMarkdownSerializer

272
node_modules/prosemirror-markdown/src/from_markdown.ts generated vendored Normal file
View File

@@ -0,0 +1,272 @@
// @ts-ignore
import MarkdownIt from "markdown-it"
import Token from "markdown-it/lib/token.mjs"
import {schema} from "./schema"
import {Mark, MarkType, Node, Attrs, Schema, NodeType} from "prosemirror-model"
function maybeMerge(a: Node, b: Node): Node | undefined {
if (a.isText && b.isText && Mark.sameSet(a.marks, b.marks))
return (a as any).withText(a.text! + b.text!)
}
// Object used to track the context of a running parse.
class MarkdownParseState {
stack: {type: NodeType, attrs: Attrs | null, content: Node[], marks: readonly Mark[]}[]
constructor(
readonly schema: Schema,
readonly tokenHandlers: {[token: string]: (stat: MarkdownParseState, token: Token, tokens: Token[], i: number) => void}
) {
this.stack = [{type: schema.topNodeType, attrs: null, content: [], marks: Mark.none}]
}
top() {
return this.stack[this.stack.length - 1]
}
push(elt: Node) {
if (this.stack.length) this.top().content.push(elt)
}
// Adds the given text to the current position in the document,
// using the current marks as styling.
addText(text: string) {
if (!text) return
let top = this.top(), nodes = top.content, last = nodes[nodes.length - 1]
let node = this.schema.text(text, top.marks), merged
if (last && (merged = maybeMerge(last, node))) nodes[nodes.length - 1] = merged
else nodes.push(node)
}
// Adds the given mark to the set of active marks.
openMark(mark: Mark) {
let top = this.top()
top.marks = mark.addToSet(top.marks)
}
// Removes the given mark from the set of active marks.
closeMark(mark: MarkType) {
let top = this.top()
top.marks = mark.removeFromSet(top.marks)
}
parseTokens(toks: Token[]) {
for (let i = 0; i < toks.length; i++) {
let tok = toks[i]
let handler = this.tokenHandlers[tok.type]
if (!handler)
throw new Error("Token type `" + tok.type + "` not supported by Markdown parser")
handler(this, tok, toks, i)
}
}
// Add a node at the current position.
addNode(type: NodeType, attrs: Attrs | null, content?: readonly Node[]) {
let top = this.top()
let node = type.createAndFill(attrs, content, top ? top.marks : [])
if (!node) return null
this.push(node)
return node
}
// Wrap subsequent content in a node of the given type.
openNode(type: NodeType, attrs: Attrs | null) {
this.stack.push({type: type, attrs: attrs, content: [], marks: Mark.none})
}
// Close and return the node that is currently on top of the stack.
closeNode() {
let info = this.stack.pop()!
return this.addNode(info.type, info.attrs, info.content)
}
}
function attrs(spec: ParseSpec, token: Token, tokens: Token[], i: number) {
if (spec.getAttrs) return spec.getAttrs(token, tokens, i)
// For backwards compatibility when `attrs` is a Function
else if (spec.attrs instanceof Function) return spec.attrs(token)
else return spec.attrs
}
// Code content is represented as a single token with a `content`
// property in Markdown-it.
function noCloseToken(spec: ParseSpec, type: string) {
return spec.noCloseToken || type == "code_inline" || type == "code_block" || type == "fence"
}
function withoutTrailingNewline(str: string) {
return str[str.length - 1] == "\n" ? str.slice(0, str.length - 1) : str
}
function noOp() {}
function tokenHandlers(schema: Schema, tokens: {[token: string]: ParseSpec}) {
let handlers: {[token: string]: (stat: MarkdownParseState, token: Token, tokens: Token[], i: number) => void} =
Object.create(null)
for (let type in tokens) {
let spec = tokens[type]
if (spec.block) {
let nodeType = schema.nodeType(spec.block)
if (noCloseToken(spec, type)) {
handlers[type] = (state, tok, tokens, i) => {
state.openNode(nodeType, attrs(spec, tok, tokens, i))
state.addText(withoutTrailingNewline(tok.content))
state.closeNode()
}
} else {
handlers[type + "_open"] = (state, tok, tokens, i) => state.openNode(nodeType, attrs(spec, tok, tokens, i))
handlers[type + "_close"] = state => state.closeNode()
}
} else if (spec.node) {
let nodeType = schema.nodeType(spec.node)
handlers[type] = (state, tok, tokens, i) => state.addNode(nodeType, attrs(spec, tok, tokens, i))
} else if (spec.mark) {
let markType = schema.marks[spec.mark]
if (noCloseToken(spec, type)) {
handlers[type] = (state, tok, tokens, i) => {
state.openMark(markType.create(attrs(spec, tok, tokens, i)))
state.addText(withoutTrailingNewline(tok.content))
state.closeMark(markType)
}
} else {
handlers[type + "_open"] = (state, tok, tokens, i) => state.openMark(markType.create(attrs(spec, tok, tokens, i)))
handlers[type + "_close"] = state => state.closeMark(markType)
}
} else if (spec.ignore) {
if (noCloseToken(spec, type)) {
handlers[type] = noOp
} else {
handlers[type + "_open"] = noOp
handlers[type + "_close"] = noOp
}
} else {
throw new RangeError("Unrecognized parsing spec " + JSON.stringify(spec))
}
}
handlers.text = (state, tok) => state.addText(tok.content)
handlers.inline = (state, tok) => state.parseTokens(tok.children!)
handlers.softbreak = handlers.softbreak || (state => state.addText(" "))
return handlers
}
/// Object type used to specify how Markdown tokens should be parsed.
export interface ParseSpec {
/// This token maps to a single node, whose type can be looked up
/// in the schema under the given name. Exactly one of `node`,
/// `block`, or `mark` must be set.
node?: string
/// This token (unless `noCloseToken` is true) comes in `_open`
/// and `_close` variants (which are appended to the base token
/// name provides a the object property), and wraps a block of
/// content. The block should be wrapped in a node of the type
/// named to by the property's value. If the token does not have
/// `_open` or `_close`, use the `noCloseToken` option.
block?: string
/// This token (again, unless `noCloseToken` is true) also comes
/// in `_open` and `_close` variants, but should add a mark
/// (named by the value) to its content, rather than wrapping it
/// in a node.
mark?: string
/// Attributes for the node or mark. When `getAttrs` is provided,
/// it takes precedence.
attrs?: Attrs | null
/// A function used to compute the attributes for the node or mark
/// that takes a [markdown-it
/// token](https://markdown-it.github.io/markdown-it/#Token) and
/// returns an attribute object.
getAttrs?: (token: Token, tokenStream: Token[], index: number) => Attrs | null
/// Indicates that the [markdown-it
/// token](https://markdown-it.github.io/markdown-it/#Token) has
/// no `_open` or `_close` for the nodes. This defaults to `true`
/// for `code_inline`, `code_block` and `fence`.
noCloseToken?: boolean
/// When true, ignore content for the matched token.
ignore?: boolean
}
/// A configuration of a Markdown parser. Such a parser uses
/// [markdown-it](https://github.com/markdown-it/markdown-it) to
/// tokenize a file, and then runs the custom rules it is given over
/// the tokens to create a ProseMirror document tree.
export class MarkdownParser {
/// @internal
tokenHandlers: {[token: string]: (stat: MarkdownParseState, token: Token, tokens: Token[], i: number) => void}
/// Create a parser with the given configuration. You can configure
/// the markdown-it parser to parse the dialect you want, and provide
/// a description of the ProseMirror entities those tokens map to in
/// the `tokens` object, which maps token names to descriptions of
/// what to do with them. Such a description is an object, and may
/// have the following properties:
constructor(
/// The parser's document schema.
readonly schema: Schema,
/// This parser's markdown-it tokenizer.
readonly tokenizer: MarkdownIt,
/// The value of the `tokens` object used to construct this
/// parser. Can be useful to copy and modify to base other parsers
/// on.
readonly tokens: {[name: string]: ParseSpec}
) {
this.tokenHandlers = tokenHandlers(schema, tokens)
}
/// Parse a string as [CommonMark](http://commonmark.org/) markup,
/// and create a ProseMirror document as prescribed by this parser's
/// rules.
///
/// The second argument, when given, is passed through to the
/// [Markdown
/// parser](https://markdown-it.github.io/markdown-it/#MarkdownIt.parse).
parse(text: string, markdownEnv: Object = {}) {
let state = new MarkdownParseState(this.schema, this.tokenHandlers), doc
state.parseTokens(this.tokenizer.parse(text, markdownEnv))
do { doc = state.closeNode() } while (state.stack.length)
return doc || this.schema.topNodeType.createAndFill()!
}
}
function listIsTight(tokens: readonly Token[], i: number) {
while (++i < tokens.length)
if (tokens[i].type != "list_item_open") return tokens[i].hidden
return false
}
/// A parser parsing unextended [CommonMark](http://commonmark.org/),
/// without inline HTML, and producing a document in the basic schema.
export const defaultMarkdownParser = new MarkdownParser(schema, MarkdownIt("commonmark", {html: false}), {
blockquote: {block: "blockquote"},
paragraph: {block: "paragraph"},
list_item: {block: "list_item"},
bullet_list: {block: "bullet_list", getAttrs: (_, tokens, i) => ({tight: listIsTight(tokens, i)})},
ordered_list: {block: "ordered_list", getAttrs: (tok, tokens, i) => ({
order: +tok.attrGet("start")! || 1,
tight: listIsTight(tokens, i)
})},
heading: {block: "heading", getAttrs: tok => ({level: +tok.tag.slice(1)})},
code_block: {block: "code_block", noCloseToken: true},
fence: {block: "code_block", getAttrs: tok => ({params: tok.info || ""}), noCloseToken: true},
hr: {node: "horizontal_rule"},
image: {node: "image", getAttrs: tok => ({
src: tok.attrGet("src"),
title: tok.attrGet("title") || null,
alt: tok.children![0] && tok.children![0].content || null
})},
hardbreak: {node: "hard_break"},
em: {mark: "em"},
strong: {mark: "strong"},
link: {mark: "link", getAttrs: tok => ({
href: tok.attrGet("href"),
title: tok.attrGet("title") || null
})},
code_inline: {mark: "code", noCloseToken: true}
})

5
node_modules/prosemirror-markdown/src/index.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
// Defines a parser and serializer for [CommonMark](http://commonmark.org/) text.
export {schema} from "./schema"
export {defaultMarkdownParser, MarkdownParser, ParseSpec} from "./from_markdown"
export {MarkdownSerializer, defaultMarkdownSerializer, MarkdownSerializerState} from "./to_markdown"

156
node_modules/prosemirror-markdown/src/schema.ts generated vendored Normal file
View File

@@ -0,0 +1,156 @@
import {Schema, MarkSpec} from "prosemirror-model"
/// Document schema for the data model used by CommonMark.
export const schema = new Schema({
nodes: {
doc: {
content: "block+"
},
paragraph: {
content: "inline*",
group: "block",
parseDOM: [{tag: "p"}],
toDOM() { return ["p", 0] }
},
blockquote: {
content: "block+",
group: "block",
parseDOM: [{tag: "blockquote"}],
toDOM() { return ["blockquote", 0] }
},
horizontal_rule: {
group: "block",
parseDOM: [{tag: "hr"}],
toDOM() { return ["div", ["hr"]] }
},
heading: {
attrs: {level: {default: 1}},
content: "(text | image)*",
group: "block",
defining: true,
parseDOM: [{tag: "h1", attrs: {level: 1}},
{tag: "h2", attrs: {level: 2}},
{tag: "h3", attrs: {level: 3}},
{tag: "h4", attrs: {level: 4}},
{tag: "h5", attrs: {level: 5}},
{tag: "h6", attrs: {level: 6}}],
toDOM(node) { return ["h" + node.attrs.level, 0] }
},
code_block: {
content: "text*",
group: "block",
code: true,
defining: true,
marks: "",
attrs: {params: {default: ""}},
parseDOM: [{tag: "pre", preserveWhitespace: "full", getAttrs: node => (
{params: (node as HTMLElement).getAttribute("data-params") || ""}
)}],
toDOM(node) { return ["pre", node.attrs.params ? {"data-params": node.attrs.params} : {}, ["code", 0]] }
},
ordered_list: {
content: "list_item+",
group: "block",
attrs: {order: {default: 1}, tight: {default: false}},
parseDOM: [{tag: "ol", getAttrs(dom) {
return {order: (dom as HTMLElement).hasAttribute("start") ? +(dom as HTMLElement).getAttribute("start")! : 1,
tight: (dom as HTMLElement).hasAttribute("data-tight")}
}}],
toDOM(node) {
return ["ol", {start: node.attrs.order == 1 ? null : node.attrs.order,
"data-tight": node.attrs.tight ? "true" : null}, 0]
}
},
bullet_list: {
content: "list_item+",
group: "block",
attrs: {tight: {default: false}},
parseDOM: [{tag: "ul", getAttrs: dom => ({tight: (dom as HTMLElement).hasAttribute("data-tight")})}],
toDOM(node) { return ["ul", {"data-tight": node.attrs.tight ? "true" : null}, 0] }
},
list_item: {
content: "block+",
defining: true,
parseDOM: [{tag: "li"}],
toDOM() { return ["li", 0] }
},
text: {
group: "inline"
},
image: {
inline: true,
attrs: {
src: {},
alt: {default: null},
title: {default: null}
},
group: "inline",
draggable: true,
parseDOM: [{tag: "img[src]", getAttrs(dom) {
return {
src: (dom as HTMLElement).getAttribute("src"),
title: (dom as HTMLElement).getAttribute("title"),
alt: (dom as HTMLElement).getAttribute("alt")
}
}}],
toDOM(node) { return ["img", node.attrs] }
},
hard_break: {
inline: true,
group: "inline",
selectable: false,
parseDOM: [{tag: "br"}],
toDOM() { return ["br"] }
}
},
marks: {
em: {
parseDOM: [
{tag: "i"}, {tag: "em"},
{style: "font-style=italic"},
{style: "font-style=normal", clearMark: m => m.type.name == "em"}
],
toDOM() { return ["em"] }
},
strong: {
parseDOM: [
{tag: "strong"},
{tag: "b", getAttrs: node => node.style.fontWeight != "normal" && null},
{style: "font-weight=400", clearMark: m => m.type.name == "strong"},
{style: "font-weight", getAttrs: value => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null}
],
toDOM() { return ["strong"] }
} as MarkSpec,
link: {
attrs: {
href: {},
title: {default: null}
},
inclusive: false,
parseDOM: [{tag: "a[href]", getAttrs(dom) {
return {href: (dom as HTMLElement).getAttribute("href"), title: dom.getAttribute("title")}
}}],
toDOM(node) { return ["a", node.attrs] }
},
code: {
code: true,
parseDOM: [{tag: "code"}],
toDOM() { return ["code"] }
}
}
})

483
node_modules/prosemirror-markdown/src/to_markdown.ts generated vendored Normal file
View File

@@ -0,0 +1,483 @@
import {Node, Mark} from "prosemirror-model"
type MarkSerializerSpec = {
/// The string that should appear before a piece of content marked
/// by this mark, either directly or as a function that returns an
/// appropriate string.
open: string | ((state: MarkdownSerializerState, mark: Mark, parent: Node, index: number) => string),
/// The string that should appear after a piece of content marked by
/// this mark.
close: string | ((state: MarkdownSerializerState, mark: Mark, parent: Node, index: number) => string),
/// When `true`, this indicates that the order in which the mark's
/// opening and closing syntax appears relative to other mixable
/// marks can be varied. (For example, you can say `**a *b***` and
/// `*a **b***`, but not `` `a *b*` ``.)
mixable?: boolean,
/// When enabled, causes the serializer to move enclosing whitespace
/// from inside the marks to outside the marks. This is necessary
/// for emphasis marks as CommonMark does not permit enclosing
/// whitespace inside emphasis marks, see:
/// http:///spec.commonmark.org/0.26/#example-330
expelEnclosingWhitespace?: boolean,
/// Can be set to `false` to disable character escaping in a mark. A
/// non-escaping mark has to have the highest precedence (must
/// always be the innermost mark).
escape?: boolean
}
const blankMark: MarkSerializerSpec = {open: "", close: "", mixable: true}
/// A specification for serializing a ProseMirror document as
/// Markdown/CommonMark text.
export class MarkdownSerializer {
/// Construct a serializer with the given configuration. The `nodes`
/// object should map node names in a given schema to function that
/// take a serializer state and such a node, and serialize the node.
constructor(
/// The node serializer functions for this serializer.
readonly nodes: {[node: string]: (state: MarkdownSerializerState, node: Node, parent: Node, index: number) => void},
/// The mark serializer info.
readonly marks: {[mark: string]: MarkSerializerSpec},
readonly options: {
/// Extra characters can be added for escaping. This is passed
/// directly to String.replace(), and the matching characters are
/// preceded by a backslash.
escapeExtraCharacters?: RegExp,
/// Specify the node name of hard breaks.
/// Defaults to "hard_break"
hardBreakNodeName?: string,
/// By default, the serializer raises an error when it finds a
/// node or mark type for which no serializer is defined. Set
/// this to `false` to make it just ignore such elements,
/// rendering only their content.
strict?: boolean
} = {}
) {}
/// Serialize the content of the given node to
/// [CommonMark](http://commonmark.org/).
serialize(content: Node, options: {
/// Whether to render lists in a tight style. This can be overridden
/// on a node level by specifying a tight attribute on the node.
/// Defaults to false.
tightLists?: boolean
} = {}) {
options = Object.assign({}, this.options, options)
let state = new MarkdownSerializerState(this.nodes, this.marks, options)
state.renderContent(content)
return state.out
}
}
/// A serializer for the [basic schema](#schema).
export const defaultMarkdownSerializer = new MarkdownSerializer({
blockquote(state, node) {
state.wrapBlock("> ", null, node, () => state.renderContent(node))
},
code_block(state, node) {
// Make sure the front matter fences are longer than any dash sequence within it
const backticks = node.textContent.match(/`{3,}/gm)
const fence = backticks ? (backticks.sort().slice(-1)[0] + "`") : "```"
state.write(fence + (node.attrs.params || "") + "\n")
state.text(node.textContent, false)
// Add a newline to the current content before adding closing marker
state.write("\n")
state.write(fence)
state.closeBlock(node)
},
heading(state, node) {
state.write(state.repeat("#", node.attrs.level) + " ")
state.renderInline(node, false)
state.closeBlock(node)
},
horizontal_rule(state, node) {
state.write(node.attrs.markup || "---")
state.closeBlock(node)
},
bullet_list(state, node) {
state.renderList(node, " ", () => (node.attrs.bullet || "*") + " ")
},
ordered_list(state, node) {
let start = node.attrs.order || 1
let maxW = String(start + node.childCount - 1).length
let space = state.repeat(" ", maxW + 2)
state.renderList(node, space, i => {
let nStr = String(start + i)
return state.repeat(" ", maxW - nStr.length) + nStr + ". "
})
},
list_item(state, node) {
state.renderContent(node)
},
paragraph(state, node) {
state.renderInline(node)
state.closeBlock(node)
},
image(state, node) {
state.write("![" + state.esc(node.attrs.alt || "") + "](" + node.attrs.src.replace(/[\(\)]/g, "\\$&") +
(node.attrs.title ? ' "' + node.attrs.title.replace(/"/g, '\\"') + '"' : "") + ")")
},
hard_break(state, node, parent, index) {
for (let i = index + 1; i < parent.childCount; i++)
if (parent.child(i).type != node.type) {
state.write("\\\n")
return
}
},
text(state, node) {
state.text(node.text!, !state.inAutolink)
}
}, {
em: {open: "*", close: "*", mixable: true, expelEnclosingWhitespace: true},
strong: {open: "**", close: "**", mixable: true, expelEnclosingWhitespace: true},
link: {
open(state, mark, parent, index) {
state.inAutolink = isPlainURL(mark, parent, index)
return state.inAutolink ? "<" : "["
},
close(state, mark, parent, index) {
let {inAutolink} = state
state.inAutolink = undefined
return inAutolink ? ">"
: "](" + mark.attrs.href.replace(/[\(\)"]/g, "\\$&") + (mark.attrs.title ? ` "${mark.attrs.title.replace(/"/g, '\\"')}"` : "") + ")"
},
mixable: true
},
code: {open(_state, _mark, parent, index) { return backticksFor(parent.child(index), -1) },
close(_state, _mark, parent, index) { return backticksFor(parent.child(index - 1), 1) },
escape: false}
})
function backticksFor(node: Node, side: number) {
let ticks = /`+/g, m: RegExpExecArray | null, len = 0
if (node.isText) while (m = ticks.exec(node.text!)) len = Math.max(len, m[0].length)
let result = len > 0 && side > 0 ? " `" : "`"
for (let i = 0; i < len; i++) result += "`"
if (len > 0 && side < 0) result += " "
return result
}
function isPlainURL(link: Mark, parent: Node, index: number) {
if (link.attrs.title || !/^\w+:/.test(link.attrs.href)) return false
let content = parent.child(index)
if (!content.isText || content.text != link.attrs.href || content.marks[content.marks.length - 1] != link) return false
return index == parent.childCount - 1 || !link.isInSet(parent.child(index + 1).marks)
}
/// This is an object used to track state and expose
/// methods related to markdown serialization. Instances are passed to
/// node and mark serialization methods (see `toMarkdown`).
export class MarkdownSerializerState {
/// @internal
delim: string = ""
/// @internal
out: string = ""
/// @internal
closed: Node | null = null
/// @internal
inAutolink: boolean | undefined = undefined
/// @internal
atBlockStart: boolean = false
/// @internal
inTightList: boolean = false
/// @internal
constructor(
/// @internal
readonly nodes: {[node: string]: (state: MarkdownSerializerState, node: Node, parent: Node, index: number) => void},
/// @internal
readonly marks: {[mark: string]: MarkSerializerSpec},
/// The options passed to the serializer.
readonly options: {tightLists?: boolean, escapeExtraCharacters?: RegExp, hardBreakNodeName?: string, strict?: boolean}
) {
if (typeof this.options.tightLists == "undefined")
this.options.tightLists = false
if (typeof this.options.hardBreakNodeName == "undefined")
this.options.hardBreakNodeName = "hard_break"
}
/// @internal
flushClose(size: number = 2) {
if (this.closed) {
if (!this.atBlank()) this.out += "\n"
if (size > 1) {
let delimMin = this.delim
let trim = /\s+$/.exec(delimMin)
if (trim) delimMin = delimMin.slice(0, delimMin.length - trim[0].length)
for (let i = 1; i < size; i++)
this.out += delimMin + "\n"
}
this.closed = null
}
}
/// @internal
getMark(name: string) {
let info = this.marks[name]
if (!info) {
if (this.options.strict !== false)
throw new Error(`Mark type \`${name}\` not supported by Markdown renderer`)
info = blankMark
}
return info
}
/// Render a block, prefixing each line with `delim`, and the first
/// line in `firstDelim`. `node` should be the node that is closed at
/// the end of the block, and `f` is a function that renders the
/// content of the block.
wrapBlock(delim: string, firstDelim: string | null, node: Node, f: () => void) {
let old = this.delim
this.write(firstDelim != null ? firstDelim : delim)
this.delim += delim
f()
this.delim = old
this.closeBlock(node)
}
/// @internal
atBlank() {
return /(^|\n)$/.test(this.out)
}
/// Ensure the current content ends with a newline.
ensureNewLine() {
if (!this.atBlank()) this.out += "\n"
}
/// Prepare the state for writing output (closing closed paragraphs,
/// adding delimiters, and so on), and then optionally add content
/// (unescaped) to the output.
write(content?: string) {
this.flushClose()
if (this.delim && this.atBlank())
this.out += this.delim
if (content) this.out += content
}
/// Close the block for the given node.
closeBlock(node: Node) {
this.closed = node
}
/// Add the given text to the document. When escape is not `false`,
/// it will be escaped.
text(text: string, escape = true) {
let lines = text.split("\n")
for (let i = 0; i < lines.length; i++) {
this.write()
// Escape exclamation marks in front of links
if (!escape && lines[i][0] == "[" && /(^|[^\\])\!$/.test(this.out))
this.out = this.out.slice(0, this.out.length - 1) + "\\!"
this.out += escape ? this.esc(lines[i], this.atBlockStart) : lines[i]
if (i != lines.length - 1) this.out += "\n"
}
}
/// Render the given node as a block.
render(node: Node, parent: Node, index: number) {
if (this.nodes[node.type.name]) {
this.nodes[node.type.name](this, node, parent, index)
} else {
if (this.options.strict !== false) {
throw new Error("Token type `" + node.type.name + "` not supported by Markdown renderer")
} else if (!node.type.isLeaf) {
if (node.type.inlineContent) this.renderInline(node)
else this.renderContent(node)
if (node.isBlock) this.closeBlock(node)
}
}
}
/// Render the contents of `parent` as block nodes.
renderContent(parent: Node) {
parent.forEach((node, _, i) => this.render(node, parent, i))
}
/// Render the contents of `parent` as inline content.
renderInline(parent: Node, fromBlockStart = true) {
this.atBlockStart = fromBlockStart
let active: Mark[] = [], trailing = ""
let progress = (node: Node | null, offset: number, index: number) => {
let marks = node ? node.marks : []
// Remove marks from `hard_break` that are the last node inside
// that mark to prevent parser edge cases with new lines just
// before closing marks.
if (node && node.type.name === this.options.hardBreakNodeName)
marks = marks.filter(m => {
if (index + 1 == parent.childCount) return false
let next = parent.child(index + 1)
return m.isInSet(next.marks) && (!next.isText || /\S/.test(next.text!))
})
let leading = trailing
trailing = ""
// If whitespace has to be expelled from the node, adjust
// leading and trailing accordingly.
if (node && node.isText && marks.some(mark => {
let info = this.getMark(mark.type.name)
return info && info.expelEnclosingWhitespace && !mark.isInSet(active)
})) {
let [_, lead, rest] = /^(\s*)(.*)$/m.exec(node.text!)!
if (lead) {
leading += lead
node = rest ? (node as any).withText(rest) : null
if (!node) marks = active
}
}
if (node && node.isText && marks.some(mark => {
let info = this.getMark(mark.type.name)
return info && info.expelEnclosingWhitespace && !this.isMarkAhead(parent, index + 1, mark)
})) {
let [_, rest, trail] = /^(.*?)(\s*)$/m.exec(node.text!)!
if (trail) {
trailing = trail
node = rest ? (node as any).withText(rest) : null
if (!node) marks = active
}
}
let inner = marks.length ? marks[marks.length - 1] : null
let noEsc = inner && this.getMark(inner.type.name).escape === false
let len = marks.length - (noEsc ? 1 : 0)
// Try to reorder 'mixable' marks, such as em and strong, which
// in Markdown may be opened and closed in different order, so
// that order of the marks for the token matches the order in
// active.
outer: for (let i = 0; i < len; i++) {
let mark = marks[i]
if (!this.getMark(mark.type.name).mixable) break
for (let j = 0; j < active.length; j++) {
let other = active[j]
if (!this.getMark(other.type.name).mixable) break
if (mark.eq(other)) {
if (i > j)
marks = marks.slice(0, j).concat(mark).concat(marks.slice(j, i)).concat(marks.slice(i + 1, len))
else if (j > i)
marks = marks.slice(0, i).concat(marks.slice(i + 1, j)).concat(mark).concat(marks.slice(j, len))
continue outer
}
}
}
// Find the prefix of the mark set that didn't change
let keep = 0
while (keep < Math.min(active.length, len) && marks[keep].eq(active[keep])) ++keep
// Close the marks that need to be closed
while (keep < active.length)
this.text(this.markString(active.pop()!, false, parent, index), false)
// Output any previously expelled trailing whitespace outside the marks
if (leading) this.text(leading)
// Open the marks that need to be opened
if (node) {
while (active.length < len) {
let add = marks[active.length]
active.push(add)
this.text(this.markString(add, true, parent, index), false)
this.atBlockStart = false
}
// Render the node. Special case code marks, since their content
// may not be escaped.
if (noEsc && node.isText)
this.text(this.markString(inner!, true, parent, index) + node.text +
this.markString(inner!, false, parent, index + 1), false)
else
this.render(node, parent, index)
this.atBlockStart = false
}
// After the first non-empty text node is rendered, the end of output
// is no longer at block start.
//
// FIXME: If a non-text node writes something to the output for this
// block, the end of output is also no longer at block start. But how
// can we detect that?
if (node?.isText && node.nodeSize > 0) {
this.atBlockStart = false
}
}
parent.forEach(progress)
progress(null, 0, parent.childCount)
this.atBlockStart = false
}
/// Render a node's content as a list. `delim` should be the extra
/// indentation added to all lines except the first in an item,
/// `firstDelim` is a function going from an item index to a
/// delimiter for the first line of the item.
renderList(node: Node, delim: string, firstDelim: (index: number) => string) {
if (this.closed && this.closed.type == node.type)
this.flushClose(3)
else if (this.inTightList)
this.flushClose(1)
let isTight = typeof node.attrs.tight != "undefined" ? node.attrs.tight : this.options.tightLists
let prevTight = this.inTightList
this.inTightList = isTight
node.forEach((child, _, i) => {
if (i && isTight) this.flushClose(1)
this.wrapBlock(delim, firstDelim(i), node, () => this.render(child, node, i))
})
this.inTightList = prevTight
}
/// Escape the given string so that it can safely appear in Markdown
/// content. If `startOfLine` is true, also escape characters that
/// have special meaning only at the start of the line.
esc(str: string, startOfLine = false) {
str = str.replace(
/[`*\\~\[\]_]/g,
(m, i) => m == "_" && i > 0 && i + 1 < str.length && str[i-1].match(/\w/) && str[i+1].match(/\w/) ? m : "\\" + m
)
if (startOfLine) str = str.replace(/^(\+[ ]|[\-*>])/, "\\$&").replace(/^(\s*)(#{1,6})(\s|$)/, '$1\\$2$3').replace(/^(\s*\d+)\.\s/, "$1\\. ")
if (this.options.escapeExtraCharacters) str = str.replace(this.options.escapeExtraCharacters, "\\$&")
return str
}
/// @internal
quote(str: string) {
let wrap = str.indexOf('"') == -1 ? '""' : str.indexOf("'") == -1 ? "''" : "()"
return wrap[0] + str + wrap[1]
}
/// Repeat the given string `n` times.
repeat(str: string, n: number) {
let out = ""
for (let i = 0; i < n; i++) out += str
return out
}
/// Get the markdown string for a given opening or closing mark.
markString(mark: Mark, open: boolean, parent: Node, index: number) {
let info = this.getMark(mark.type.name)
let value = open ? info.open : info.close
return typeof value == "string" ? value : value(this, mark, parent, index)
}
/// Get leading and trailing whitespace from a string. Values of
/// leading or trailing property of the return object will be undefined
/// if there is no match.
getEnclosingWhitespace(text: string): {leading?: string, trailing?: string} {
return {
leading: (text.match(/^(\s+)/) || [undefined])[0],
trailing: (text.match(/(\s+)$/) || [undefined])[0]
}
}
/// @internal
isMarkAhead(parent: Node, index: number, mark: Mark) {
for (;; index++) {
if (index >= parent.childCount) return false
let next = parent.child(index)
if (next.type.name != this.options.hardBreakNodeName) return mark.isInSet(next.marks)
index++
}
}
}