完成世界书、骰子、apiconfig页面处理

This commit is contained in:
2026-04-30 01:35:10 +08:00
parent a3e3711b2b
commit ba9b925c32
4602 changed files with 785225 additions and 23 deletions

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.js"],"names":[],"mappings":""}

View File

@@ -0,0 +1 @@
{"version":3,"file":"block-quote.d.ts","sourceRoot":"","sources":["block-quote.js"],"names":[],"mappings":"AAeA,wBAAwB;AACxB,yBADW,SAAS,CAMnB;+BAdS,sBAAsB"}

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const characterEscape: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=character-escape.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"character-escape.d.ts","sourceRoot":"","sources":["character-escape.js"],"names":[],"mappings":"AAaA,wBAAwB;AACxB,8BADW,SAAS,CAInB;+BAXS,sBAAsB"}

View File

@@ -0,0 +1 @@
{"version":3,"file":"character-reference.d.ts","sourceRoot":"","sources":["character-reference.js"],"names":[],"mappings":"AAmBA,wBAAwB;AACxB,iCADW,SAAS,CAInB;+BAhBS,sBAAsB"}

View File

@@ -0,0 +1 @@
{"version":3,"file":"code-fenced.d.ts","sourceRoot":"","sources":["code-fenced.js"],"names":[],"mappings":"AAqBA,wBAAwB;AACxB,yBADW,SAAS,CAKnB;+BAnBS,sBAAsB"}

View File

@@ -0,0 +1,514 @@
/**
* @import {
* Code,
* Construct,
* State,
* TokenizeContext,
* Tokenizer
* } from 'micromark-util-types'
*/
import {ok as assert} from 'devlop'
import {factorySpace} from 'micromark-factory-space'
import {markdownLineEnding, markdownSpace} from 'micromark-util-character'
import {codes, constants, types} from 'micromark-util-symbol'
/** @type {Construct} */
const nonLazyContinuation = {
partial: true,
tokenize: tokenizeNonLazyContinuation
}
/** @type {Construct} */
export const codeFenced = {
concrete: true,
name: 'codeFenced',
tokenize: tokenizeCodeFenced
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeCodeFenced(effects, ok, nok) {
const self = this
/** @type {Construct} */
const closeStart = {partial: true, tokenize: tokenizeCloseStart}
let initialPrefix = 0
let sizeOpen = 0
/** @type {NonNullable<Code>} */
let marker
return start
/**
* Start of code.
*
* ```markdown
* > | ~~~js
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function start(code) {
// To do: parse whitespace like `markdown-rs`.
return beforeSequenceOpen(code)
}
/**
* In opening fence, after prefix, at sequence.
*
* ```markdown
* > | ~~~js
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function beforeSequenceOpen(code) {
assert(
code === codes.graveAccent || code === codes.tilde,
'expected `` ` `` or `~`'
)
const tail = self.events[self.events.length - 1]
initialPrefix =
tail && tail[1].type === types.linePrefix
? tail[2].sliceSerialize(tail[1], true).length
: 0
marker = code
effects.enter(types.codeFenced)
effects.enter(types.codeFencedFence)
effects.enter(types.codeFencedFenceSequence)
return sequenceOpen(code)
}
/**
* In opening fence sequence.
*
* ```markdown
* > | ~~~js
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function sequenceOpen(code) {
if (code === marker) {
sizeOpen++
effects.consume(code)
return sequenceOpen
}
if (sizeOpen < constants.codeFencedSequenceSizeMin) {
return nok(code)
}
effects.exit(types.codeFencedFenceSequence)
return markdownSpace(code)
? factorySpace(effects, infoBefore, types.whitespace)(code)
: infoBefore(code)
}
/**
* In opening fence, after the sequence (and optional whitespace), before info.
*
* ```markdown
* > | ~~~js
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function infoBefore(code) {
if (code === codes.eof || markdownLineEnding(code)) {
effects.exit(types.codeFencedFence)
return self.interrupt
? ok(code)
: effects.check(nonLazyContinuation, atNonLazyBreak, after)(code)
}
effects.enter(types.codeFencedFenceInfo)
effects.enter(types.chunkString, {contentType: constants.contentTypeString})
return info(code)
}
/**
* In info.
*
* ```markdown
* > | ~~~js
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function info(code) {
if (code === codes.eof || markdownLineEnding(code)) {
effects.exit(types.chunkString)
effects.exit(types.codeFencedFenceInfo)
return infoBefore(code)
}
if (markdownSpace(code)) {
effects.exit(types.chunkString)
effects.exit(types.codeFencedFenceInfo)
return factorySpace(effects, metaBefore, types.whitespace)(code)
}
if (code === codes.graveAccent && code === marker) {
return nok(code)
}
effects.consume(code)
return info
}
/**
* In opening fence, after info and whitespace, before meta.
*
* ```markdown
* > | ~~~js eval
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function metaBefore(code) {
if (code === codes.eof || markdownLineEnding(code)) {
return infoBefore(code)
}
effects.enter(types.codeFencedFenceMeta)
effects.enter(types.chunkString, {contentType: constants.contentTypeString})
return meta(code)
}
/**
* In meta.
*
* ```markdown
* > | ~~~js eval
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function meta(code) {
if (code === codes.eof || markdownLineEnding(code)) {
effects.exit(types.chunkString)
effects.exit(types.codeFencedFenceMeta)
return infoBefore(code)
}
if (code === codes.graveAccent && code === marker) {
return nok(code)
}
effects.consume(code)
return meta
}
/**
* At eol/eof in code, before a non-lazy closing fence or content.
*
* ```markdown
* > | ~~~js
* ^
* > | alert(1)
* ^
* | ~~~
* ```
*
* @type {State}
*/
function atNonLazyBreak(code) {
assert(markdownLineEnding(code), 'expected eol')
return effects.attempt(closeStart, after, contentBefore)(code)
}
/**
* Before code content, not a closing fence, at eol.
*
* ```markdown
* | ~~~js
* > | alert(1)
* ^
* | ~~~
* ```
*
* @type {State}
*/
function contentBefore(code) {
assert(markdownLineEnding(code), 'expected eol')
effects.enter(types.lineEnding)
effects.consume(code)
effects.exit(types.lineEnding)
return contentStart
}
/**
* Before code content, not a closing fence.
*
* ```markdown
* | ~~~js
* > | alert(1)
* ^
* | ~~~
* ```
*
* @type {State}
*/
function contentStart(code) {
return initialPrefix > 0 && markdownSpace(code)
? factorySpace(
effects,
beforeContentChunk,
types.linePrefix,
initialPrefix + 1
)(code)
: beforeContentChunk(code)
}
/**
* Before code content, after optional prefix.
*
* ```markdown
* | ~~~js
* > | alert(1)
* ^
* | ~~~
* ```
*
* @type {State}
*/
function beforeContentChunk(code) {
if (code === codes.eof || markdownLineEnding(code)) {
return effects.check(nonLazyContinuation, atNonLazyBreak, after)(code)
}
effects.enter(types.codeFlowValue)
return contentChunk(code)
}
/**
* In code content.
*
* ```markdown
* | ~~~js
* > | alert(1)
* ^^^^^^^^
* | ~~~
* ```
*
* @type {State}
*/
function contentChunk(code) {
if (code === codes.eof || markdownLineEnding(code)) {
effects.exit(types.codeFlowValue)
return beforeContentChunk(code)
}
effects.consume(code)
return contentChunk
}
/**
* After code.
*
* ```markdown
* | ~~~js
* | alert(1)
* > | ~~~
* ^
* ```
*
* @type {State}
*/
function after(code) {
effects.exit(types.codeFenced)
return ok(code)
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeCloseStart(effects, ok, nok) {
let size = 0
return startBefore
/**
*
*
* @type {State}
*/
function startBefore(code) {
assert(markdownLineEnding(code), 'expected eol')
effects.enter(types.lineEnding)
effects.consume(code)
effects.exit(types.lineEnding)
return start
}
/**
* Before closing fence, at optional whitespace.
*
* ```markdown
* | ~~~js
* | alert(1)
* > | ~~~
* ^
* ```
*
* @type {State}
*/
function start(code) {
// Always populated by defaults.
assert(
self.parser.constructs.disable.null,
'expected `disable.null` to be populated'
)
// To do: `enter` here or in next state?
effects.enter(types.codeFencedFence)
return markdownSpace(code)
? factorySpace(
effects,
beforeSequenceClose,
types.linePrefix,
self.parser.constructs.disable.null.includes('codeIndented')
? undefined
: constants.tabSize
)(code)
: beforeSequenceClose(code)
}
/**
* In closing fence, after optional whitespace, at sequence.
*
* ```markdown
* | ~~~js
* | alert(1)
* > | ~~~
* ^
* ```
*
* @type {State}
*/
function beforeSequenceClose(code) {
if (code === marker) {
effects.enter(types.codeFencedFenceSequence)
return sequenceClose(code)
}
return nok(code)
}
/**
* In closing fence sequence.
*
* ```markdown
* | ~~~js
* | alert(1)
* > | ~~~
* ^
* ```
*
* @type {State}
*/
function sequenceClose(code) {
if (code === marker) {
size++
effects.consume(code)
return sequenceClose
}
if (size >= sizeOpen) {
effects.exit(types.codeFencedFenceSequence)
return markdownSpace(code)
? factorySpace(effects, sequenceCloseAfter, types.whitespace)(code)
: sequenceCloseAfter(code)
}
return nok(code)
}
/**
* After closing fence sequence, after optional whitespace.
*
* ```markdown
* | ~~~js
* | alert(1)
* > | ~~~
* ^
* ```
*
* @type {State}
*/
function sequenceCloseAfter(code) {
if (code === codes.eof || markdownLineEnding(code)) {
effects.exit(types.codeFencedFence)
return ok(code)
}
return nok(code)
}
}
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeNonLazyContinuation(effects, ok, nok) {
const self = this
return start
/**
*
*
* @type {State}
*/
function start(code) {
if (code === codes.eof) {
return nok(code)
}
assert(markdownLineEnding(code), 'expected eol')
effects.enter(types.lineEnding)
effects.consume(code)
effects.exit(types.lineEnding)
return lineStart
}
/**
*
*
* @type {State}
*/
function lineStart(code) {
return self.parser.lazy[self.now().line] ? nok(code) : ok(code)
}
}

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const codeIndented: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=code-indented.d.ts.map

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const codeText: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=code-text.d.ts.map

View File

@@ -0,0 +1,7 @@
/**
* No name because it must not be turned off.
* @type {Construct}
*/
export const content: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=content.d.ts.map

View File

@@ -0,0 +1,295 @@
/**
* @import {
* Construct,
* State,
* TokenizeContext,
* Tokenizer
* } from 'micromark-util-types'
*/
import {ok as assert} from 'devlop'
import {factoryDestination} from 'micromark-factory-destination'
import {factoryLabel} from 'micromark-factory-label'
import {factorySpace} from 'micromark-factory-space'
import {factoryTitle} from 'micromark-factory-title'
import {factoryWhitespace} from 'micromark-factory-whitespace'
import {
markdownLineEndingOrSpace,
markdownLineEnding,
markdownSpace
} from 'micromark-util-character'
import {normalizeIdentifier} from 'micromark-util-normalize-identifier'
import {codes, types} from 'micromark-util-symbol'
/** @type {Construct} */
export const definition = {name: 'definition', tokenize: tokenizeDefinition}
/** @type {Construct} */
const titleBefore = {partial: true, tokenize: tokenizeTitleBefore}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeDefinition(effects, ok, nok) {
const self = this
/** @type {string} */
let identifier
return start
/**
* At start of a definition.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function start(code) {
// Do not interrupt paragraphs (but do follow definitions).
// To do: do `interrupt` the way `markdown-rs` does.
// To do: parse whitespace the way `markdown-rs` does.
effects.enter(types.definition)
return before(code)
}
/**
* After optional whitespace, at `[`.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function before(code) {
// To do: parse whitespace the way `markdown-rs` does.
assert(code === codes.leftSquareBracket, 'expected `[`')
return factoryLabel.call(
self,
effects,
labelAfter,
// Note: we dont need to reset the way `markdown-rs` does.
nok,
types.definitionLabel,
types.definitionLabelMarker,
types.definitionLabelString
)(code)
}
/**
* After label.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function labelAfter(code) {
identifier = normalizeIdentifier(
self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1)
)
if (code === codes.colon) {
effects.enter(types.definitionMarker)
effects.consume(code)
effects.exit(types.definitionMarker)
return markerAfter
}
return nok(code)
}
/**
* After marker.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function markerAfter(code) {
// Note: whitespace is optional.
return markdownLineEndingOrSpace(code)
? factoryWhitespace(effects, destinationBefore)(code)
: destinationBefore(code)
}
/**
* Before destination.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function destinationBefore(code) {
return factoryDestination(
effects,
destinationAfter,
// Note: we dont need to reset the way `markdown-rs` does.
nok,
types.definitionDestination,
types.definitionDestinationLiteral,
types.definitionDestinationLiteralMarker,
types.definitionDestinationRaw,
types.definitionDestinationString
)(code)
}
/**
* After destination.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function destinationAfter(code) {
return effects.attempt(titleBefore, after, after)(code)
}
/**
* After definition.
*
* ```markdown
* > | [a]: b
* ^
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function after(code) {
return markdownSpace(code)
? factorySpace(effects, afterWhitespace, types.whitespace)(code)
: afterWhitespace(code)
}
/**
* After definition, after optional whitespace.
*
* ```markdown
* > | [a]: b
* ^
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function afterWhitespace(code) {
if (code === codes.eof || markdownLineEnding(code)) {
effects.exit(types.definition)
// Note: we dont care about uniqueness.
// Its likely that that doesnt happen very frequently.
// It is more likely that it wastes precious time.
self.parser.defined.push(identifier)
// To do: `markdown-rs` interrupt.
// // Youd be interrupting.
// tokenizer.interrupt = true
return ok(code)
}
return nok(code)
}
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeTitleBefore(effects, ok, nok) {
return titleBefore
/**
* After destination, at whitespace.
*
* ```markdown
* > | [a]: b
* ^
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function titleBefore(code) {
return markdownLineEndingOrSpace(code)
? factoryWhitespace(effects, beforeMarker)(code)
: nok(code)
}
/**
* At title.
*
* ```markdown
* | [a]: b
* > | "c"
* ^
* ```
*
* @type {State}
*/
function beforeMarker(code) {
return factoryTitle(
effects,
titleAfter,
nok,
types.definitionTitle,
types.definitionTitleMarker,
types.definitionTitleString
)(code)
}
/**
* After title.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function titleAfter(code) {
return markdownSpace(code)
? factorySpace(
effects,
titleAfterOptionalWhitespace,
types.whitespace
)(code)
: titleAfterOptionalWhitespace(code)
}
/**
* After title, after optional whitespace.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function titleAfterOptionalWhitespace(code) {
return code === codes.eof || markdownLineEnding(code) ? ok(code) : nok(code)
}
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"hard-break-escape.d.ts","sourceRoot":"","sources":["hard-break-escape.js"],"names":[],"mappings":"AAaA,wBAAwB;AACxB,8BADW,SAAS,CAInB;+BAXS,sBAAsB"}

View File

@@ -0,0 +1,989 @@
/**
* @import {
* Code,
* Construct,
* Resolver,
* State,
* TokenizeContext,
* Tokenizer
* } from 'micromark-util-types'
*/
import {ok as assert} from 'devlop'
import {
asciiAlphanumeric,
asciiAlpha,
markdownLineEndingOrSpace,
markdownLineEnding,
markdownSpace
} from 'micromark-util-character'
import {htmlBlockNames, htmlRawNames} from 'micromark-util-html-tag-name'
import {codes, constants, types} from 'micromark-util-symbol'
import {blankLine} from './blank-line.js'
/** @type {Construct} */
export const htmlFlow = {
concrete: true,
name: 'htmlFlow',
resolveTo: resolveToHtmlFlow,
tokenize: tokenizeHtmlFlow
}
/** @type {Construct} */
const blankLineBefore = {partial: true, tokenize: tokenizeBlankLineBefore}
const nonLazyContinuationStart = {
partial: true,
tokenize: tokenizeNonLazyContinuationStart
}
/** @type {Resolver} */
function resolveToHtmlFlow(events) {
let index = events.length
while (index--) {
if (
events[index][0] === 'enter' &&
events[index][1].type === types.htmlFlow
) {
break
}
}
if (index > 1 && events[index - 2][1].type === types.linePrefix) {
// Add the prefix start to the HTML token.
events[index][1].start = events[index - 2][1].start
// Add the prefix start to the HTML line token.
events[index + 1][1].start = events[index - 2][1].start
// Remove the line prefix.
events.splice(index - 2, 2)
}
return events
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeHtmlFlow(effects, ok, nok) {
const self = this
/** @type {number} */
let marker
/** @type {boolean} */
let closingTag
/** @type {string} */
let buffer
/** @type {number} */
let index
/** @type {Code} */
let markerB
return start
/**
* Start of HTML (flow).
*
* ```markdown
* > | <x />
* ^
* ```
*
* @type {State}
*/
function start(code) {
// To do: parse indent like `markdown-rs`.
return before(code)
}
/**
* At `<`, after optional whitespace.
*
* ```markdown
* > | <x />
* ^
* ```
*
* @type {State}
*/
function before(code) {
assert(code === codes.lessThan, 'expected `<`')
effects.enter(types.htmlFlow)
effects.enter(types.htmlFlowData)
effects.consume(code)
return open
}
/**
* After `<`, at tag name or other stuff.
*
* ```markdown
* > | <x />
* ^
* > | <!doctype>
* ^
* > | <!--xxx-->
* ^
* ```
*
* @type {State}
*/
function open(code) {
if (code === codes.exclamationMark) {
effects.consume(code)
return declarationOpen
}
if (code === codes.slash) {
effects.consume(code)
closingTag = true
return tagCloseStart
}
if (code === codes.questionMark) {
effects.consume(code)
marker = constants.htmlInstruction
// To do:
// tokenizer.concrete = true
// To do: use `markdown-rs` style interrupt.
// While were in an instruction instead of a declaration, were on a `?`
// right now, so we do need to search for `>`, similar to declarations.
return self.interrupt ? ok : continuationDeclarationInside
}
// ASCII alphabetical.
if (asciiAlpha(code)) {
assert(code !== null) // Always the case.
effects.consume(code)
buffer = String.fromCharCode(code)
return tagName
}
return nok(code)
}
/**
* After `<!`, at declaration, comment, or CDATA.
*
* ```markdown
* > | <!doctype>
* ^
* > | <!--xxx-->
* ^
* > | <![CDATA[>&<]]>
* ^
* ```
*
* @type {State}
*/
function declarationOpen(code) {
if (code === codes.dash) {
effects.consume(code)
marker = constants.htmlComment
return commentOpenInside
}
if (code === codes.leftSquareBracket) {
effects.consume(code)
marker = constants.htmlCdata
index = 0
return cdataOpenInside
}
// ASCII alphabetical.
if (asciiAlpha(code)) {
effects.consume(code)
marker = constants.htmlDeclaration
// // Do not form containers.
// tokenizer.concrete = true
return self.interrupt ? ok : continuationDeclarationInside
}
return nok(code)
}
/**
* After `<!-`, inside a comment, at another `-`.
*
* ```markdown
* > | <!--xxx-->
* ^
* ```
*
* @type {State}
*/
function commentOpenInside(code) {
if (code === codes.dash) {
effects.consume(code)
// // Do not form containers.
// tokenizer.concrete = true
return self.interrupt ? ok : continuationDeclarationInside
}
return nok(code)
}
/**
* After `<![`, inside CDATA, expecting `CDATA[`.
*
* ```markdown
* > | <![CDATA[>&<]]>
* ^^^^^^
* ```
*
* @type {State}
*/
function cdataOpenInside(code) {
const value = constants.cdataOpeningString
if (code === value.charCodeAt(index++)) {
effects.consume(code)
if (index === value.length) {
// // Do not form containers.
// tokenizer.concrete = true
return self.interrupt ? ok : continuation
}
return cdataOpenInside
}
return nok(code)
}
/**
* After `</`, in closing tag, at tag name.
*
* ```markdown
* > | </x>
* ^
* ```
*
* @type {State}
*/
function tagCloseStart(code) {
if (asciiAlpha(code)) {
assert(code !== null) // Always the case.
effects.consume(code)
buffer = String.fromCharCode(code)
return tagName
}
return nok(code)
}
/**
* In tag name.
*
* ```markdown
* > | <ab>
* ^^
* > | </ab>
* ^^
* ```
*
* @type {State}
*/
function tagName(code) {
if (
code === codes.eof ||
code === codes.slash ||
code === codes.greaterThan ||
markdownLineEndingOrSpace(code)
) {
const slash = code === codes.slash
const name = buffer.toLowerCase()
if (!slash && !closingTag && htmlRawNames.includes(name)) {
marker = constants.htmlRaw
// // Do not form containers.
// tokenizer.concrete = true
return self.interrupt ? ok(code) : continuation(code)
}
if (htmlBlockNames.includes(buffer.toLowerCase())) {
marker = constants.htmlBasic
if (slash) {
effects.consume(code)
return basicSelfClosing
}
// // Do not form containers.
// tokenizer.concrete = true
return self.interrupt ? ok(code) : continuation(code)
}
marker = constants.htmlComplete
// Do not support complete HTML when interrupting.
return self.interrupt && !self.parser.lazy[self.now().line]
? nok(code)
: closingTag
? completeClosingTagAfter(code)
: completeAttributeNameBefore(code)
}
// ASCII alphanumerical and `-`.
if (code === codes.dash || asciiAlphanumeric(code)) {
effects.consume(code)
buffer += String.fromCharCode(code)
return tagName
}
return nok(code)
}
/**
* After closing slash of a basic tag name.
*
* ```markdown
* > | <div/>
* ^
* ```
*
* @type {State}
*/
function basicSelfClosing(code) {
if (code === codes.greaterThan) {
effects.consume(code)
// // Do not form containers.
// tokenizer.concrete = true
return self.interrupt ? ok : continuation
}
return nok(code)
}
/**
* After closing slash of a complete tag name.
*
* ```markdown
* > | <x/>
* ^
* ```
*
* @type {State}
*/
function completeClosingTagAfter(code) {
if (markdownSpace(code)) {
effects.consume(code)
return completeClosingTagAfter
}
return completeEnd(code)
}
/**
* At an attribute name.
*
* At first, this state is used after a complete tag name, after whitespace,
* where it expects optional attributes or the end of the tag.
* It is also reused after attributes, when expecting more optional
* attributes.
*
* ```markdown
* > | <a />
* ^
* > | <a :b>
* ^
* > | <a _b>
* ^
* > | <a b>
* ^
* > | <a >
* ^
* ```
*
* @type {State}
*/
function completeAttributeNameBefore(code) {
if (code === codes.slash) {
effects.consume(code)
return completeEnd
}
// ASCII alphanumerical and `:` and `_`.
if (code === codes.colon || code === codes.underscore || asciiAlpha(code)) {
effects.consume(code)
return completeAttributeName
}
if (markdownSpace(code)) {
effects.consume(code)
return completeAttributeNameBefore
}
return completeEnd(code)
}
/**
* In attribute name.
*
* ```markdown
* > | <a :b>
* ^
* > | <a _b>
* ^
* > | <a b>
* ^
* ```
*
* @type {State}
*/
function completeAttributeName(code) {
// ASCII alphanumerical and `-`, `.`, `:`, and `_`.
if (
code === codes.dash ||
code === codes.dot ||
code === codes.colon ||
code === codes.underscore ||
asciiAlphanumeric(code)
) {
effects.consume(code)
return completeAttributeName
}
return completeAttributeNameAfter(code)
}
/**
* After attribute name, at an optional initializer, the end of the tag, or
* whitespace.
*
* ```markdown
* > | <a b>
* ^
* > | <a b=c>
* ^
* ```
*
* @type {State}
*/
function completeAttributeNameAfter(code) {
if (code === codes.equalsTo) {
effects.consume(code)
return completeAttributeValueBefore
}
if (markdownSpace(code)) {
effects.consume(code)
return completeAttributeNameAfter
}
return completeAttributeNameBefore(code)
}
/**
* Before unquoted, double quoted, or single quoted attribute value, allowing
* whitespace.
*
* ```markdown
* > | <a b=c>
* ^
* > | <a b="c">
* ^
* ```
*
* @type {State}
*/
function completeAttributeValueBefore(code) {
if (
code === codes.eof ||
code === codes.lessThan ||
code === codes.equalsTo ||
code === codes.greaterThan ||
code === codes.graveAccent
) {
return nok(code)
}
if (code === codes.quotationMark || code === codes.apostrophe) {
effects.consume(code)
markerB = code
return completeAttributeValueQuoted
}
if (markdownSpace(code)) {
effects.consume(code)
return completeAttributeValueBefore
}
return completeAttributeValueUnquoted(code)
}
/**
* In double or single quoted attribute value.
*
* ```markdown
* > | <a b="c">
* ^
* > | <a b='c'>
* ^
* ```
*
* @type {State}
*/
function completeAttributeValueQuoted(code) {
if (code === markerB) {
effects.consume(code)
markerB = null
return completeAttributeValueQuotedAfter
}
if (code === codes.eof || markdownLineEnding(code)) {
return nok(code)
}
effects.consume(code)
return completeAttributeValueQuoted
}
/**
* In unquoted attribute value.
*
* ```markdown
* > | <a b=c>
* ^
* ```
*
* @type {State}
*/
function completeAttributeValueUnquoted(code) {
if (
code === codes.eof ||
code === codes.quotationMark ||
code === codes.apostrophe ||
code === codes.slash ||
code === codes.lessThan ||
code === codes.equalsTo ||
code === codes.greaterThan ||
code === codes.graveAccent ||
markdownLineEndingOrSpace(code)
) {
return completeAttributeNameAfter(code)
}
effects.consume(code)
return completeAttributeValueUnquoted
}
/**
* After double or single quoted attribute value, before whitespace or the
* end of the tag.
*
* ```markdown
* > | <a b="c">
* ^
* ```
*
* @type {State}
*/
function completeAttributeValueQuotedAfter(code) {
if (
code === codes.slash ||
code === codes.greaterThan ||
markdownSpace(code)
) {
return completeAttributeNameBefore(code)
}
return nok(code)
}
/**
* In certain circumstances of a complete tag where only an `>` is allowed.
*
* ```markdown
* > | <a b="c">
* ^
* ```
*
* @type {State}
*/
function completeEnd(code) {
if (code === codes.greaterThan) {
effects.consume(code)
return completeAfter
}
return nok(code)
}
/**
* After `>` in a complete tag.
*
* ```markdown
* > | <x>
* ^
* ```
*
* @type {State}
*/
function completeAfter(code) {
if (code === codes.eof || markdownLineEnding(code)) {
// // Do not form containers.
// tokenizer.concrete = true
return continuation(code)
}
if (markdownSpace(code)) {
effects.consume(code)
return completeAfter
}
return nok(code)
}
/**
* In continuation of any HTML kind.
*
* ```markdown
* > | <!--xxx-->
* ^
* ```
*
* @type {State}
*/
function continuation(code) {
if (code === codes.dash && marker === constants.htmlComment) {
effects.consume(code)
return continuationCommentInside
}
if (code === codes.lessThan && marker === constants.htmlRaw) {
effects.consume(code)
return continuationRawTagOpen
}
if (code === codes.greaterThan && marker === constants.htmlDeclaration) {
effects.consume(code)
return continuationClose
}
if (code === codes.questionMark && marker === constants.htmlInstruction) {
effects.consume(code)
return continuationDeclarationInside
}
if (code === codes.rightSquareBracket && marker === constants.htmlCdata) {
effects.consume(code)
return continuationCdataInside
}
if (
markdownLineEnding(code) &&
(marker === constants.htmlBasic || marker === constants.htmlComplete)
) {
effects.exit(types.htmlFlowData)
return effects.check(
blankLineBefore,
continuationAfter,
continuationStart
)(code)
}
if (code === codes.eof || markdownLineEnding(code)) {
effects.exit(types.htmlFlowData)
return continuationStart(code)
}
effects.consume(code)
return continuation
}
/**
* In continuation, at eol.
*
* ```markdown
* > | <x>
* ^
* | asd
* ```
*
* @type {State}
*/
function continuationStart(code) {
return effects.check(
nonLazyContinuationStart,
continuationStartNonLazy,
continuationAfter
)(code)
}
/**
* In continuation, at eol, before non-lazy content.
*
* ```markdown
* > | <x>
* ^
* | asd
* ```
*
* @type {State}
*/
function continuationStartNonLazy(code) {
assert(markdownLineEnding(code))
effects.enter(types.lineEnding)
effects.consume(code)
effects.exit(types.lineEnding)
return continuationBefore
}
/**
* In continuation, before non-lazy content.
*
* ```markdown
* | <x>
* > | asd
* ^
* ```
*
* @type {State}
*/
function continuationBefore(code) {
if (code === codes.eof || markdownLineEnding(code)) {
return continuationStart(code)
}
effects.enter(types.htmlFlowData)
return continuation(code)
}
/**
* In comment continuation, after one `-`, expecting another.
*
* ```markdown
* > | <!--xxx-->
* ^
* ```
*
* @type {State}
*/
function continuationCommentInside(code) {
if (code === codes.dash) {
effects.consume(code)
return continuationDeclarationInside
}
return continuation(code)
}
/**
* In raw continuation, after `<`, at `/`.
*
* ```markdown
* > | <script>console.log(1)</script>
* ^
* ```
*
* @type {State}
*/
function continuationRawTagOpen(code) {
if (code === codes.slash) {
effects.consume(code)
buffer = ''
return continuationRawEndTag
}
return continuation(code)
}
/**
* In raw continuation, after `</`, in a raw tag name.
*
* ```markdown
* > | <script>console.log(1)</script>
* ^^^^^^
* ```
*
* @type {State}
*/
function continuationRawEndTag(code) {
if (code === codes.greaterThan) {
const name = buffer.toLowerCase()
if (htmlRawNames.includes(name)) {
effects.consume(code)
return continuationClose
}
return continuation(code)
}
if (asciiAlpha(code) && buffer.length < constants.htmlRawSizeMax) {
assert(code !== null) // Always the case.
effects.consume(code)
buffer += String.fromCharCode(code)
return continuationRawEndTag
}
return continuation(code)
}
/**
* In cdata continuation, after `]`, expecting `]>`.
*
* ```markdown
* > | <![CDATA[>&<]]>
* ^
* ```
*
* @type {State}
*/
function continuationCdataInside(code) {
if (code === codes.rightSquareBracket) {
effects.consume(code)
return continuationDeclarationInside
}
return continuation(code)
}
/**
* In declaration or instruction continuation, at `>`.
*
* ```markdown
* > | <!-->
* ^
* > | <?>
* ^
* > | <!q>
* ^
* > | <!--ab-->
* ^
* > | <![CDATA[>&<]]>
* ^
* ```
*
* @type {State}
*/
function continuationDeclarationInside(code) {
if (code === codes.greaterThan) {
effects.consume(code)
return continuationClose
}
// More dashes.
if (code === codes.dash && marker === constants.htmlComment) {
effects.consume(code)
return continuationDeclarationInside
}
return continuation(code)
}
/**
* In closed continuation: everything we get until the eol/eof is part of it.
*
* ```markdown
* > | <!doctype>
* ^
* ```
*
* @type {State}
*/
function continuationClose(code) {
if (code === codes.eof || markdownLineEnding(code)) {
effects.exit(types.htmlFlowData)
return continuationAfter(code)
}
effects.consume(code)
return continuationClose
}
/**
* Done.
*
* ```markdown
* > | <!doctype>
* ^
* ```
*
* @type {State}
*/
function continuationAfter(code) {
effects.exit(types.htmlFlow)
// // Feel free to interrupt.
// tokenizer.interrupt = false
// // No longer concrete.
// tokenizer.concrete = false
return ok(code)
}
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeNonLazyContinuationStart(effects, ok, nok) {
const self = this
return start
/**
* At eol, before continuation.
*
* ```markdown
* > | * ```js
* ^
* | b
* ```
*
* @type {State}
*/
function start(code) {
if (markdownLineEnding(code)) {
effects.enter(types.lineEnding)
effects.consume(code)
effects.exit(types.lineEnding)
return after
}
return nok(code)
}
/**
* A continuation.
*
* ```markdown
* | * ```js
* > | b
* ^
* ```
*
* @type {State}
*/
function after(code) {
return self.parser.lazy[self.now().line] ? nok(code) : ok(code)
}
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeBlankLineBefore(effects, ok, nok) {
return start
/**
* Before eol, expecting blank line.
*
* ```markdown
* > | <div>
* ^
* |
* ```
*
* @type {State}
*/
function start(code) {
assert(markdownLineEnding(code), 'expected a line ending')
effects.enter(types.lineEnding)
effects.consume(code)
effects.exit(types.lineEnding)
return effects.attempt(blankLine, ok, nok)
}
}

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const htmlText: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=html-text.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"html-text.d.ts","sourceRoot":"","sources":["html-text.js"],"names":[],"mappings":"AAqBA,wBAAwB;AACxB,uBADW,SAAS,CACkD;+BAf5D,sBAAsB"}

View File

@@ -0,0 +1,62 @@
/**
* @import {
* Construct,
* State,
* TokenizeContext,
* Tokenizer
* } from 'micromark-util-types'
*/
import {ok as assert} from 'devlop'
import {codes, types} from 'micromark-util-symbol'
import {labelEnd} from './label-end.js'
/** @type {Construct} */
export const labelStartLink = {
name: 'labelStartLink',
resolveAll: labelEnd.resolveAll,
tokenize: tokenizeLabelStartLink
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeLabelStartLink(effects, ok, nok) {
const self = this
return start
/**
* Start of label (link) start.
*
* ```markdown
* > | a [b] c
* ^
* ```
*
* @type {State}
*/
function start(code) {
assert(code === codes.leftSquareBracket, 'expected `[`')
effects.enter(types.labelLink)
effects.enter(types.labelMarker)
effects.consume(code)
effects.exit(types.labelMarker)
effects.exit(types.labelLink)
return after
}
/** @type {State} */
function after(code) {
// To do: this isnt needed in `micromark-extension-gfm-footnote`,
// remove.
// Hidden footnotes hook.
/* c8 ignore next 3 */
return code === codes.caret &&
'_hiddenFootnoteSupport' in self.parser.constructs
? nok(code)
: ok(code)
}
}

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const lineEnding: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=line-ending.d.ts.map

View File

@@ -0,0 +1,210 @@
/**
* @import {
* Code,
* Construct,
* Resolver,
* State,
* TokenizeContext,
* Tokenizer
* } from 'micromark-util-types'
*/
import {ok as assert} from 'devlop'
import {factorySpace} from 'micromark-factory-space'
import {markdownLineEnding, markdownSpace} from 'micromark-util-character'
import {codes, types} from 'micromark-util-symbol'
/** @type {Construct} */
export const setextUnderline = {
name: 'setextUnderline',
resolveTo: resolveToSetextUnderline,
tokenize: tokenizeSetextUnderline
}
/** @type {Resolver} */
function resolveToSetextUnderline(events, context) {
// To do: resolve like `markdown-rs`.
let index = events.length
/** @type {number | undefined} */
let content
/** @type {number | undefined} */
let text
/** @type {number | undefined} */
let definition
// Find the opening of the content.
// Itll always exist: we dont tokenize if it isnt there.
while (index--) {
if (events[index][0] === 'enter') {
if (events[index][1].type === types.content) {
content = index
break
}
if (events[index][1].type === types.paragraph) {
text = index
}
}
// Exit
else {
if (events[index][1].type === types.content) {
// Remove the content end (if needed well add it later)
events.splice(index, 1)
}
if (!definition && events[index][1].type === types.definition) {
definition = index
}
}
}
assert(text !== undefined, 'expected a `text` index to be found')
assert(content !== undefined, 'expected a `text` index to be found')
assert(events[content][2] === context, 'enter context should be same')
assert(
events[events.length - 1][2] === context,
'enter context should be same'
)
const heading = {
type: types.setextHeading,
start: {...events[content][1].start},
end: {...events[events.length - 1][1].end}
}
// Change the paragraph to setext heading text.
events[text][1].type = types.setextHeadingText
// If we have definitions in the content, well keep on having content,
// but we need move it.
if (definition) {
events.splice(text, 0, ['enter', heading, context])
events.splice(definition + 1, 0, ['exit', events[content][1], context])
events[content][1].end = {...events[definition][1].end}
} else {
events[content][1] = heading
}
// Add the heading exit at the end.
events.push(['exit', heading, context])
return events
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeSetextUnderline(effects, ok, nok) {
const self = this
/** @type {NonNullable<Code>} */
let marker
return start
/**
* At start of heading (setext) underline.
*
* ```markdown
* | aa
* > | ==
* ^
* ```
*
* @type {State}
*/
function start(code) {
let index = self.events.length
/** @type {boolean | undefined} */
let paragraph
assert(
code === codes.dash || code === codes.equalsTo,
'expected `=` or `-`'
)
// Find an opening.
while (index--) {
// Skip enter/exit of line ending, line prefix, and content.
// We can now either have a definition or a paragraph.
if (
self.events[index][1].type !== types.lineEnding &&
self.events[index][1].type !== types.linePrefix &&
self.events[index][1].type !== types.content
) {
paragraph = self.events[index][1].type === types.paragraph
break
}
}
// To do: handle lazy/pierce like `markdown-rs`.
// To do: parse indent like `markdown-rs`.
if (!self.parser.lazy[self.now().line] && (self.interrupt || paragraph)) {
effects.enter(types.setextHeadingLine)
marker = code
return before(code)
}
return nok(code)
}
/**
* After optional whitespace, at `-` or `=`.
*
* ```markdown
* | aa
* > | ==
* ^
* ```
*
* @type {State}
*/
function before(code) {
effects.enter(types.setextHeadingLineSequence)
return inside(code)
}
/**
* In sequence.
*
* ```markdown
* | aa
* > | ==
* ^
* ```
*
* @type {State}
*/
function inside(code) {
if (code === marker) {
effects.consume(code)
return inside
}
effects.exit(types.setextHeadingLineSequence)
return markdownSpace(code)
? factorySpace(effects, after, types.lineSuffix)(code)
: after(code)
}
/**
* After sequence, after optional whitespace.
*
* ```markdown
* | aa
* > | ==
* ^
* ```
*
* @type {State}
*/
function after(code) {
if (code === codes.eof || markdownLineEnding(code)) {
effects.exit(types.setextHeadingLine)
return ok(code)
}
return nok(code)
}
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"thematic-break.d.ts","sourceRoot":"","sources":["thematic-break.js"],"names":[],"mappings":"AAeA,wBAAwB;AACxB,4BADW,SAAS,CAInB;+BAZS,sBAAsB"}

View File

@@ -0,0 +1,23 @@
export { attention } from "./lib/attention.js";
export { autolink } from "./lib/autolink.js";
export { blankLine } from "./lib/blank-line.js";
export { blockQuote } from "./lib/block-quote.js";
export { characterEscape } from "./lib/character-escape.js";
export { characterReference } from "./lib/character-reference.js";
export { codeFenced } from "./lib/code-fenced.js";
export { codeIndented } from "./lib/code-indented.js";
export { codeText } from "./lib/code-text.js";
export { content } from "./lib/content.js";
export { definition } from "./lib/definition.js";
export { hardBreakEscape } from "./lib/hard-break-escape.js";
export { headingAtx } from "./lib/heading-atx.js";
export { htmlFlow } from "./lib/html-flow.js";
export { htmlText } from "./lib/html-text.js";
export { labelEnd } from "./lib/label-end.js";
export { labelStartImage } from "./lib/label-start-image.js";
export { labelStartLink } from "./lib/label-start-link.js";
export { lineEnding } from "./lib/line-ending.js";
export { list } from "./lib/list.js";
export { setextUnderline } from "./lib/setext-underline.js";
export { thematicBreak } from "./lib/thematic-break.js";
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1,22 @@
export { attention } from './lib/attention.js';
export { autolink } from './lib/autolink.js';
export { blankLine } from './lib/blank-line.js';
export { blockQuote } from './lib/block-quote.js';
export { characterEscape } from './lib/character-escape.js';
export { characterReference } from './lib/character-reference.js';
export { codeFenced } from './lib/code-fenced.js';
export { codeIndented } from './lib/code-indented.js';
export { codeText } from './lib/code-text.js';
export { content } from './lib/content.js';
export { definition } from './lib/definition.js';
export { hardBreakEscape } from './lib/hard-break-escape.js';
export { headingAtx } from './lib/heading-atx.js';
export { htmlFlow } from './lib/html-flow.js';
export { htmlText } from './lib/html-text.js';
export { labelEnd } from './lib/label-end.js';
export { labelStartImage } from './lib/label-start-image.js';
export { labelStartLink } from './lib/label-start-link.js';
export { lineEnding } from './lib/line-ending.js';
export { list } from './lib/list.js';
export { setextUnderline } from './lib/setext-underline.js';
export { thematicBreak } from './lib/thematic-break.js';

View File

@@ -0,0 +1 @@
{"version":3,"file":"attention.d.ts","sourceRoot":"","sources":["attention.js"],"names":[],"mappings":"AAoBA,wBAAwB;AACxB,wBADW,SAAS,CAKnB;+BAdS,sBAAsB"}

View File

@@ -0,0 +1 @@
{"version":3,"file":"autolink.d.ts","sourceRoot":"","sources":["autolink.js"],"names":[],"mappings":"AAkBA,wBAAwB;AACxB,uBADW,SAAS,CACkD;+BAb5D,sBAAsB"}

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const blankLine: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=blank-line.d.ts.map

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const blockQuote: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=block-quote.d.ts.map

View File

@@ -0,0 +1,143 @@
/**
* @import {
* Construct,
* Exiter,
* State,
* TokenizeContext,
* Tokenizer
* } from 'micromark-util-types'
*/
import { factorySpace } from 'micromark-factory-space';
import { markdownSpace } from 'micromark-util-character';
/** @type {Construct} */
export const blockQuote = {
continuation: {
tokenize: tokenizeBlockQuoteContinuation
},
exit,
name: 'blockQuote',
tokenize: tokenizeBlockQuoteStart
};
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeBlockQuoteStart(effects, ok, nok) {
const self = this;
return start;
/**
* Start of block quote.
*
* ```markdown
* > | > a
* ^
* ```
*
* @type {State}
*/
function start(code) {
if (code === 62) {
const state = self.containerState;
if (!state.open) {
effects.enter("blockQuote", {
_container: true
});
state.open = true;
}
effects.enter("blockQuotePrefix");
effects.enter("blockQuoteMarker");
effects.consume(code);
effects.exit("blockQuoteMarker");
return after;
}
return nok(code);
}
/**
* After `>`, before optional whitespace.
*
* ```markdown
* > | > a
* ^
* ```
*
* @type {State}
*/
function after(code) {
if (markdownSpace(code)) {
effects.enter("blockQuotePrefixWhitespace");
effects.consume(code);
effects.exit("blockQuotePrefixWhitespace");
effects.exit("blockQuotePrefix");
return ok;
}
effects.exit("blockQuotePrefix");
return ok(code);
}
}
/**
* Start of block quote continuation.
*
* ```markdown
* | > a
* > | > b
* ^
* ```
*
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeBlockQuoteContinuation(effects, ok, nok) {
const self = this;
return contStart;
/**
* Start of block quote continuation.
*
* Also used to parse the first block quote opening.
*
* ```markdown
* | > a
* > | > b
* ^
* ```
*
* @type {State}
*/
function contStart(code) {
if (markdownSpace(code)) {
// Always populated by defaults.
return factorySpace(effects, contBefore, "linePrefix", self.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4)(code);
}
return contBefore(code);
}
/**
* At `>`, after optional whitespace.
*
* Also used to parse the first block quote opening.
*
* ```markdown
* | > a
* > | > b
* ^
* ```
*
* @type {State}
*/
function contBefore(code) {
return effects.attempt(blockQuote, ok, nok)(code);
}
}
/** @type {Exiter} */
function exit(effects) {
effects.exit("blockQuote");
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"character-escape.d.ts","sourceRoot":"","sources":["character-escape.js"],"names":[],"mappings":"AAaA,wBAAwB;AACxB,8BADW,SAAS,CAInB;+BAXS,sBAAsB"}

View File

@@ -0,0 +1,460 @@
/**
* @import {
* Code,
* Construct,
* State,
* TokenizeContext,
* Tokenizer
* } from 'micromark-util-types'
*/
import { factorySpace } from 'micromark-factory-space';
import { markdownLineEnding, markdownSpace } from 'micromark-util-character';
/** @type {Construct} */
const nonLazyContinuation = {
partial: true,
tokenize: tokenizeNonLazyContinuation
};
/** @type {Construct} */
export const codeFenced = {
concrete: true,
name: 'codeFenced',
tokenize: tokenizeCodeFenced
};
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeCodeFenced(effects, ok, nok) {
const self = this;
/** @type {Construct} */
const closeStart = {
partial: true,
tokenize: tokenizeCloseStart
};
let initialPrefix = 0;
let sizeOpen = 0;
/** @type {NonNullable<Code>} */
let marker;
return start;
/**
* Start of code.
*
* ```markdown
* > | ~~~js
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function start(code) {
// To do: parse whitespace like `markdown-rs`.
return beforeSequenceOpen(code);
}
/**
* In opening fence, after prefix, at sequence.
*
* ```markdown
* > | ~~~js
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function beforeSequenceOpen(code) {
const tail = self.events[self.events.length - 1];
initialPrefix = tail && tail[1].type === "linePrefix" ? tail[2].sliceSerialize(tail[1], true).length : 0;
marker = code;
effects.enter("codeFenced");
effects.enter("codeFencedFence");
effects.enter("codeFencedFenceSequence");
return sequenceOpen(code);
}
/**
* In opening fence sequence.
*
* ```markdown
* > | ~~~js
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function sequenceOpen(code) {
if (code === marker) {
sizeOpen++;
effects.consume(code);
return sequenceOpen;
}
if (sizeOpen < 3) {
return nok(code);
}
effects.exit("codeFencedFenceSequence");
return markdownSpace(code) ? factorySpace(effects, infoBefore, "whitespace")(code) : infoBefore(code);
}
/**
* In opening fence, after the sequence (and optional whitespace), before info.
*
* ```markdown
* > | ~~~js
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function infoBefore(code) {
if (code === null || markdownLineEnding(code)) {
effects.exit("codeFencedFence");
return self.interrupt ? ok(code) : effects.check(nonLazyContinuation, atNonLazyBreak, after)(code);
}
effects.enter("codeFencedFenceInfo");
effects.enter("chunkString", {
contentType: "string"
});
return info(code);
}
/**
* In info.
*
* ```markdown
* > | ~~~js
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function info(code) {
if (code === null || markdownLineEnding(code)) {
effects.exit("chunkString");
effects.exit("codeFencedFenceInfo");
return infoBefore(code);
}
if (markdownSpace(code)) {
effects.exit("chunkString");
effects.exit("codeFencedFenceInfo");
return factorySpace(effects, metaBefore, "whitespace")(code);
}
if (code === 96 && code === marker) {
return nok(code);
}
effects.consume(code);
return info;
}
/**
* In opening fence, after info and whitespace, before meta.
*
* ```markdown
* > | ~~~js eval
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function metaBefore(code) {
if (code === null || markdownLineEnding(code)) {
return infoBefore(code);
}
effects.enter("codeFencedFenceMeta");
effects.enter("chunkString", {
contentType: "string"
});
return meta(code);
}
/**
* In meta.
*
* ```markdown
* > | ~~~js eval
* ^
* | alert(1)
* | ~~~
* ```
*
* @type {State}
*/
function meta(code) {
if (code === null || markdownLineEnding(code)) {
effects.exit("chunkString");
effects.exit("codeFencedFenceMeta");
return infoBefore(code);
}
if (code === 96 && code === marker) {
return nok(code);
}
effects.consume(code);
return meta;
}
/**
* At eol/eof in code, before a non-lazy closing fence or content.
*
* ```markdown
* > | ~~~js
* ^
* > | alert(1)
* ^
* | ~~~
* ```
*
* @type {State}
*/
function atNonLazyBreak(code) {
return effects.attempt(closeStart, after, contentBefore)(code);
}
/**
* Before code content, not a closing fence, at eol.
*
* ```markdown
* | ~~~js
* > | alert(1)
* ^
* | ~~~
* ```
*
* @type {State}
*/
function contentBefore(code) {
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return contentStart;
}
/**
* Before code content, not a closing fence.
*
* ```markdown
* | ~~~js
* > | alert(1)
* ^
* | ~~~
* ```
*
* @type {State}
*/
function contentStart(code) {
return initialPrefix > 0 && markdownSpace(code) ? factorySpace(effects, beforeContentChunk, "linePrefix", initialPrefix + 1)(code) : beforeContentChunk(code);
}
/**
* Before code content, after optional prefix.
*
* ```markdown
* | ~~~js
* > | alert(1)
* ^
* | ~~~
* ```
*
* @type {State}
*/
function beforeContentChunk(code) {
if (code === null || markdownLineEnding(code)) {
return effects.check(nonLazyContinuation, atNonLazyBreak, after)(code);
}
effects.enter("codeFlowValue");
return contentChunk(code);
}
/**
* In code content.
*
* ```markdown
* | ~~~js
* > | alert(1)
* ^^^^^^^^
* | ~~~
* ```
*
* @type {State}
*/
function contentChunk(code) {
if (code === null || markdownLineEnding(code)) {
effects.exit("codeFlowValue");
return beforeContentChunk(code);
}
effects.consume(code);
return contentChunk;
}
/**
* After code.
*
* ```markdown
* | ~~~js
* | alert(1)
* > | ~~~
* ^
* ```
*
* @type {State}
*/
function after(code) {
effects.exit("codeFenced");
return ok(code);
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeCloseStart(effects, ok, nok) {
let size = 0;
return startBefore;
/**
*
*
* @type {State}
*/
function startBefore(code) {
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return start;
}
/**
* Before closing fence, at optional whitespace.
*
* ```markdown
* | ~~~js
* | alert(1)
* > | ~~~
* ^
* ```
*
* @type {State}
*/
function start(code) {
// Always populated by defaults.
// To do: `enter` here or in next state?
effects.enter("codeFencedFence");
return markdownSpace(code) ? factorySpace(effects, beforeSequenceClose, "linePrefix", self.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4)(code) : beforeSequenceClose(code);
}
/**
* In closing fence, after optional whitespace, at sequence.
*
* ```markdown
* | ~~~js
* | alert(1)
* > | ~~~
* ^
* ```
*
* @type {State}
*/
function beforeSequenceClose(code) {
if (code === marker) {
effects.enter("codeFencedFenceSequence");
return sequenceClose(code);
}
return nok(code);
}
/**
* In closing fence sequence.
*
* ```markdown
* | ~~~js
* | alert(1)
* > | ~~~
* ^
* ```
*
* @type {State}
*/
function sequenceClose(code) {
if (code === marker) {
size++;
effects.consume(code);
return sequenceClose;
}
if (size >= sizeOpen) {
effects.exit("codeFencedFenceSequence");
return markdownSpace(code) ? factorySpace(effects, sequenceCloseAfter, "whitespace")(code) : sequenceCloseAfter(code);
}
return nok(code);
}
/**
* After closing fence sequence, after optional whitespace.
*
* ```markdown
* | ~~~js
* | alert(1)
* > | ~~~
* ^
* ```
*
* @type {State}
*/
function sequenceCloseAfter(code) {
if (code === null || markdownLineEnding(code)) {
effects.exit("codeFencedFence");
return ok(code);
}
return nok(code);
}
}
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeNonLazyContinuation(effects, ok, nok) {
const self = this;
return start;
/**
*
*
* @type {State}
*/
function start(code) {
if (code === null) {
return nok(code);
}
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return lineStart;
}
/**
*
*
* @type {State}
*/
function lineStart(code) {
return self.parser.lazy[self.now().line] ? nok(code) : ok(code);
}
}

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const codeText: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=code-text.d.ts.map

View File

@@ -0,0 +1,7 @@
/**
* No name because it must not be turned off.
* @type {Construct}
*/
export const content: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=content.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["content.js"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,sBAFU,SAAS,CAEwD;+BAbjE,sBAAsB"}

View File

@@ -0,0 +1,163 @@
/**
* @import {
* Construct,
* Resolver,
* State,
* TokenizeContext,
* Tokenizer,
* Token
* } from 'micromark-util-types'
*/
import { factorySpace } from 'micromark-factory-space';
import { markdownLineEnding } from 'micromark-util-character';
import { subtokenize } from 'micromark-util-subtokenize';
/**
* No name because it must not be turned off.
* @type {Construct}
*/
export const content = {
resolve: resolveContent,
tokenize: tokenizeContent
};
/** @type {Construct} */
const continuationConstruct = {
partial: true,
tokenize: tokenizeContinuation
};
/**
* Content is transparent: its parsed right now. That way, definitions are also
* parsed right now: before text in paragraphs (specifically, media) are parsed.
*
* @type {Resolver}
*/
function resolveContent(events) {
subtokenize(events);
return events;
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeContent(effects, ok) {
/** @type {Token | undefined} */
let previous;
return chunkStart;
/**
* Before a content chunk.
*
* ```markdown
* > | abc
* ^
* ```
*
* @type {State}
*/
function chunkStart(code) {
effects.enter("content");
previous = effects.enter("chunkContent", {
contentType: "content"
});
return chunkInside(code);
}
/**
* In a content chunk.
*
* ```markdown
* > | abc
* ^^^
* ```
*
* @type {State}
*/
function chunkInside(code) {
if (code === null) {
return contentEnd(code);
}
// To do: in `markdown-rs`, each line is parsed on its own, and everything
// is stitched together resolving.
if (markdownLineEnding(code)) {
return effects.check(continuationConstruct, contentContinue, contentEnd)(code);
}
// Data.
effects.consume(code);
return chunkInside;
}
/**
*
*
* @type {State}
*/
function contentEnd(code) {
effects.exit("chunkContent");
effects.exit("content");
return ok(code);
}
/**
*
*
* @type {State}
*/
function contentContinue(code) {
effects.consume(code);
effects.exit("chunkContent");
previous.next = effects.enter("chunkContent", {
contentType: "content",
previous
});
previous = previous.next;
return chunkInside;
}
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeContinuation(effects, ok, nok) {
const self = this;
return startLookahead;
/**
*
*
* @type {State}
*/
function startLookahead(code) {
effects.exit("chunkContent");
effects.enter("lineEnding");
effects.consume(code);
effects.exit("lineEnding");
return factorySpace(effects, prefixed, "linePrefix");
}
/**
*
*
* @type {State}
*/
function prefixed(code) {
if (code === null || markdownLineEnding(code)) {
return nok(code);
}
// Always populated by defaults.
const tail = self.events[self.events.length - 1];
if (!self.parser.constructs.disable.null.includes('codeIndented') && tail && tail[1].type === "linePrefix" && tail[2].sliceSerialize(tail[1], true).length >= 4) {
return ok(code);
}
return effects.interrupt(self.parser.constructs.flow, nok, ok)(code);
}
}

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const definition: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=definition.d.ts.map

View File

@@ -0,0 +1,254 @@
/**
* @import {
* Construct,
* State,
* TokenizeContext,
* Tokenizer
* } from 'micromark-util-types'
*/
import { factoryDestination } from 'micromark-factory-destination';
import { factoryLabel } from 'micromark-factory-label';
import { factorySpace } from 'micromark-factory-space';
import { factoryTitle } from 'micromark-factory-title';
import { factoryWhitespace } from 'micromark-factory-whitespace';
import { markdownLineEndingOrSpace, markdownLineEnding, markdownSpace } from 'micromark-util-character';
import { normalizeIdentifier } from 'micromark-util-normalize-identifier';
/** @type {Construct} */
export const definition = {
name: 'definition',
tokenize: tokenizeDefinition
};
/** @type {Construct} */
const titleBefore = {
partial: true,
tokenize: tokenizeTitleBefore
};
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeDefinition(effects, ok, nok) {
const self = this;
/** @type {string} */
let identifier;
return start;
/**
* At start of a definition.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function start(code) {
// Do not interrupt paragraphs (but do follow definitions).
// To do: do `interrupt` the way `markdown-rs` does.
// To do: parse whitespace the way `markdown-rs` does.
effects.enter("definition");
return before(code);
}
/**
* After optional whitespace, at `[`.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function before(code) {
// To do: parse whitespace the way `markdown-rs` does.
return factoryLabel.call(self, effects, labelAfter,
// Note: we dont need to reset the way `markdown-rs` does.
nok, "definitionLabel", "definitionLabelMarker", "definitionLabelString")(code);
}
/**
* After label.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function labelAfter(code) {
identifier = normalizeIdentifier(self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1));
if (code === 58) {
effects.enter("definitionMarker");
effects.consume(code);
effects.exit("definitionMarker");
return markerAfter;
}
return nok(code);
}
/**
* After marker.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function markerAfter(code) {
// Note: whitespace is optional.
return markdownLineEndingOrSpace(code) ? factoryWhitespace(effects, destinationBefore)(code) : destinationBefore(code);
}
/**
* Before destination.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function destinationBefore(code) {
return factoryDestination(effects, destinationAfter,
// Note: we dont need to reset the way `markdown-rs` does.
nok, "definitionDestination", "definitionDestinationLiteral", "definitionDestinationLiteralMarker", "definitionDestinationRaw", "definitionDestinationString")(code);
}
/**
* After destination.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function destinationAfter(code) {
return effects.attempt(titleBefore, after, after)(code);
}
/**
* After definition.
*
* ```markdown
* > | [a]: b
* ^
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function after(code) {
return markdownSpace(code) ? factorySpace(effects, afterWhitespace, "whitespace")(code) : afterWhitespace(code);
}
/**
* After definition, after optional whitespace.
*
* ```markdown
* > | [a]: b
* ^
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function afterWhitespace(code) {
if (code === null || markdownLineEnding(code)) {
effects.exit("definition");
// Note: we dont care about uniqueness.
// Its likely that that doesnt happen very frequently.
// It is more likely that it wastes precious time.
self.parser.defined.push(identifier);
// To do: `markdown-rs` interrupt.
// // Youd be interrupting.
// tokenizer.interrupt = true
return ok(code);
}
return nok(code);
}
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeTitleBefore(effects, ok, nok) {
return titleBefore;
/**
* After destination, at whitespace.
*
* ```markdown
* > | [a]: b
* ^
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function titleBefore(code) {
return markdownLineEndingOrSpace(code) ? factoryWhitespace(effects, beforeMarker)(code) : nok(code);
}
/**
* At title.
*
* ```markdown
* | [a]: b
* > | "c"
* ^
* ```
*
* @type {State}
*/
function beforeMarker(code) {
return factoryTitle(effects, titleAfter, nok, "definitionTitle", "definitionTitleMarker", "definitionTitleString")(code);
}
/**
* After title.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function titleAfter(code) {
return markdownSpace(code) ? factorySpace(effects, titleAfterOptionalWhitespace, "whitespace")(code) : titleAfterOptionalWhitespace(code);
}
/**
* After title, after optional whitespace.
*
* ```markdown
* > | [a]: b "c"
* ^
* ```
*
* @type {State}
*/
function titleAfterOptionalWhitespace(code) {
return code === null || markdownLineEnding(code) ? ok(code) : nok(code);
}
}

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const headingAtx: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=heading-atx.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"html-flow.d.ts","sourceRoot":"","sources":["html-flow.js"],"names":[],"mappings":"AAuBA,wBAAwB;AACxB,uBADW,SAAS,CAMnB;+BArBS,sBAAsB"}

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const htmlText: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=html-text.d.ts.map

View File

@@ -0,0 +1,560 @@
/**
* @import {
* Construct,
* Event,
* Resolver,
* State,
* TokenizeContext,
* Tokenizer,
* Token
* } from 'micromark-util-types'
*/
import { factoryDestination } from 'micromark-factory-destination';
import { factoryLabel } from 'micromark-factory-label';
import { factoryTitle } from 'micromark-factory-title';
import { factoryWhitespace } from 'micromark-factory-whitespace';
import { markdownLineEndingOrSpace } from 'micromark-util-character';
import { push, splice } from 'micromark-util-chunked';
import { normalizeIdentifier } from 'micromark-util-normalize-identifier';
import { resolveAll } from 'micromark-util-resolve-all';
/** @type {Construct} */
export const labelEnd = {
name: 'labelEnd',
resolveAll: resolveAllLabelEnd,
resolveTo: resolveToLabelEnd,
tokenize: tokenizeLabelEnd
};
/** @type {Construct} */
const resourceConstruct = {
tokenize: tokenizeResource
};
/** @type {Construct} */
const referenceFullConstruct = {
tokenize: tokenizeReferenceFull
};
/** @type {Construct} */
const referenceCollapsedConstruct = {
tokenize: tokenizeReferenceCollapsed
};
/** @type {Resolver} */
function resolveAllLabelEnd(events) {
let index = -1;
/** @type {Array<Event>} */
const newEvents = [];
while (++index < events.length) {
const token = events[index][1];
newEvents.push(events[index]);
if (token.type === "labelImage" || token.type === "labelLink" || token.type === "labelEnd") {
// Remove the marker.
const offset = token.type === "labelImage" ? 4 : 2;
token.type = "data";
index += offset;
}
}
// If the events are equal, we don't have to copy newEvents to events
if (events.length !== newEvents.length) {
splice(events, 0, events.length, newEvents);
}
return events;
}
/** @type {Resolver} */
function resolveToLabelEnd(events, context) {
let index = events.length;
let offset = 0;
/** @type {Token} */
let token;
/** @type {number | undefined} */
let open;
/** @type {number | undefined} */
let close;
/** @type {Array<Event>} */
let media;
// Find an opening.
while (index--) {
token = events[index][1];
if (open) {
// If we see another link, or inactive link label, weve been here before.
if (token.type === "link" || token.type === "labelLink" && token._inactive) {
break;
}
// Mark other link openings as inactive, as we cant have links in
// links.
if (events[index][0] === 'enter' && token.type === "labelLink") {
token._inactive = true;
}
} else if (close) {
if (events[index][0] === 'enter' && (token.type === "labelImage" || token.type === "labelLink") && !token._balanced) {
open = index;
if (token.type !== "labelLink") {
offset = 2;
break;
}
}
} else if (token.type === "labelEnd") {
close = index;
}
}
const group = {
type: events[open][1].type === "labelLink" ? "link" : "image",
start: {
...events[open][1].start
},
end: {
...events[events.length - 1][1].end
}
};
const label = {
type: "label",
start: {
...events[open][1].start
},
end: {
...events[close][1].end
}
};
const text = {
type: "labelText",
start: {
...events[open + offset + 2][1].end
},
end: {
...events[close - 2][1].start
}
};
media = [['enter', group, context], ['enter', label, context]];
// Opening marker.
media = push(media, events.slice(open + 1, open + offset + 3));
// Text open.
media = push(media, [['enter', text, context]]);
// Always populated by defaults.
// Between.
media = push(media, resolveAll(context.parser.constructs.insideSpan.null, events.slice(open + offset + 4, close - 3), context));
// Text close, marker close, label close.
media = push(media, [['exit', text, context], events[close - 2], events[close - 1], ['exit', label, context]]);
// Reference, resource, or so.
media = push(media, events.slice(close + 1));
// Media close.
media = push(media, [['exit', group, context]]);
splice(events, open, events.length, media);
return events;
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeLabelEnd(effects, ok, nok) {
const self = this;
let index = self.events.length;
/** @type {Token} */
let labelStart;
/** @type {boolean} */
let defined;
// Find an opening.
while (index--) {
if ((self.events[index][1].type === "labelImage" || self.events[index][1].type === "labelLink") && !self.events[index][1]._balanced) {
labelStart = self.events[index][1];
break;
}
}
return start;
/**
* Start of label end.
*
* ```markdown
* > | [a](b) c
* ^
* > | [a][b] c
* ^
* > | [a][] b
* ^
* > | [a] b
* ```
*
* @type {State}
*/
function start(code) {
// If there is not an okay opening.
if (!labelStart) {
return nok(code);
}
// If the corresponding label (link) start is marked as inactive,
// it means wed be wrapping a link, like this:
//
// ```markdown
// > | a [b [c](d) e](f) g.
// ^
// ```
//
// We cant have that, so its just balanced brackets.
if (labelStart._inactive) {
return labelEndNok(code);
}
defined = self.parser.defined.includes(normalizeIdentifier(self.sliceSerialize({
start: labelStart.end,
end: self.now()
})));
effects.enter("labelEnd");
effects.enter("labelMarker");
effects.consume(code);
effects.exit("labelMarker");
effects.exit("labelEnd");
return after;
}
/**
* After `]`.
*
* ```markdown
* > | [a](b) c
* ^
* > | [a][b] c
* ^
* > | [a][] b
* ^
* > | [a] b
* ^
* ```
*
* @type {State}
*/
function after(code) {
// Note: `markdown-rs` also parses GFM footnotes here, which for us is in
// an extension.
// Resource (`[asd](fgh)`)?
if (code === 40) {
return effects.attempt(resourceConstruct, labelEndOk, defined ? labelEndOk : labelEndNok)(code);
}
// Full (`[asd][fgh]`) or collapsed (`[asd][]`) reference?
if (code === 91) {
return effects.attempt(referenceFullConstruct, labelEndOk, defined ? referenceNotFull : labelEndNok)(code);
}
// Shortcut (`[asd]`) reference?
return defined ? labelEndOk(code) : labelEndNok(code);
}
/**
* After `]`, at `[`, but not at a full reference.
*
* > 👉 **Note**: we only get here if the label is defined.
*
* ```markdown
* > | [a][] b
* ^
* > | [a] b
* ^
* ```
*
* @type {State}
*/
function referenceNotFull(code) {
return effects.attempt(referenceCollapsedConstruct, labelEndOk, labelEndNok)(code);
}
/**
* Done, we found something.
*
* ```markdown
* > | [a](b) c
* ^
* > | [a][b] c
* ^
* > | [a][] b
* ^
* > | [a] b
* ^
* ```
*
* @type {State}
*/
function labelEndOk(code) {
// Note: `markdown-rs` does a bunch of stuff here.
return ok(code);
}
/**
* Done, its nothing.
*
* There was an okay opening, but we didnt match anything.
*
* ```markdown
* > | [a](b c
* ^
* > | [a][b c
* ^
* > | [a] b
* ^
* ```
*
* @type {State}
*/
function labelEndNok(code) {
labelStart._balanced = true;
return nok(code);
}
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeResource(effects, ok, nok) {
return resourceStart;
/**
* At a resource.
*
* ```markdown
* > | [a](b) c
* ^
* ```
*
* @type {State}
*/
function resourceStart(code) {
effects.enter("resource");
effects.enter("resourceMarker");
effects.consume(code);
effects.exit("resourceMarker");
return resourceBefore;
}
/**
* In resource, after `(`, at optional whitespace.
*
* ```markdown
* > | [a](b) c
* ^
* ```
*
* @type {State}
*/
function resourceBefore(code) {
return markdownLineEndingOrSpace(code) ? factoryWhitespace(effects, resourceOpen)(code) : resourceOpen(code);
}
/**
* In resource, after optional whitespace, at `)` or a destination.
*
* ```markdown
* > | [a](b) c
* ^
* ```
*
* @type {State}
*/
function resourceOpen(code) {
if (code === 41) {
return resourceEnd(code);
}
return factoryDestination(effects, resourceDestinationAfter, resourceDestinationMissing, "resourceDestination", "resourceDestinationLiteral", "resourceDestinationLiteralMarker", "resourceDestinationRaw", "resourceDestinationString", 32)(code);
}
/**
* In resource, after destination, at optional whitespace.
*
* ```markdown
* > | [a](b) c
* ^
* ```
*
* @type {State}
*/
function resourceDestinationAfter(code) {
return markdownLineEndingOrSpace(code) ? factoryWhitespace(effects, resourceBetween)(code) : resourceEnd(code);
}
/**
* At invalid destination.
*
* ```markdown
* > | [a](<<) b
* ^
* ```
*
* @type {State}
*/
function resourceDestinationMissing(code) {
return nok(code);
}
/**
* In resource, after destination and whitespace, at `(` or title.
*
* ```markdown
* > | [a](b ) c
* ^
* ```
*
* @type {State}
*/
function resourceBetween(code) {
if (code === 34 || code === 39 || code === 40) {
return factoryTitle(effects, resourceTitleAfter, nok, "resourceTitle", "resourceTitleMarker", "resourceTitleString")(code);
}
return resourceEnd(code);
}
/**
* In resource, after title, at optional whitespace.
*
* ```markdown
* > | [a](b "c") d
* ^
* ```
*
* @type {State}
*/
function resourceTitleAfter(code) {
return markdownLineEndingOrSpace(code) ? factoryWhitespace(effects, resourceEnd)(code) : resourceEnd(code);
}
/**
* In resource, at `)`.
*
* ```markdown
* > | [a](b) d
* ^
* ```
*
* @type {State}
*/
function resourceEnd(code) {
if (code === 41) {
effects.enter("resourceMarker");
effects.consume(code);
effects.exit("resourceMarker");
effects.exit("resource");
return ok;
}
return nok(code);
}
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeReferenceFull(effects, ok, nok) {
const self = this;
return referenceFull;
/**
* In a reference (full), at the `[`.
*
* ```markdown
* > | [a][b] d
* ^
* ```
*
* @type {State}
*/
function referenceFull(code) {
return factoryLabel.call(self, effects, referenceFullAfter, referenceFullMissing, "reference", "referenceMarker", "referenceString")(code);
}
/**
* In a reference (full), after `]`.
*
* ```markdown
* > | [a][b] d
* ^
* ```
*
* @type {State}
*/
function referenceFullAfter(code) {
return self.parser.defined.includes(normalizeIdentifier(self.sliceSerialize(self.events[self.events.length - 1][1]).slice(1, -1))) ? ok(code) : nok(code);
}
/**
* In reference (full) that was missing.
*
* ```markdown
* > | [a][b d
* ^
* ```
*
* @type {State}
*/
function referenceFullMissing(code) {
return nok(code);
}
}
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeReferenceCollapsed(effects, ok, nok) {
return referenceCollapsedStart;
/**
* In reference (collapsed), at `[`.
*
* > 👉 **Note**: we only get here if the label is defined.
*
* ```markdown
* > | [a][] d
* ^
* ```
*
* @type {State}
*/
function referenceCollapsedStart(code) {
// We only attempt a collapsed label if theres a `[`.
effects.enter("reference");
effects.enter("referenceMarker");
effects.consume(code);
effects.exit("referenceMarker");
return referenceCollapsedOpen;
}
/**
* In reference (collapsed), at `]`.
*
* > 👉 **Note**: we only get here if the label is defined.
*
* ```markdown
* > | [a][] d
* ^
* ```
*
* @type {State}
*/
function referenceCollapsedOpen(code) {
if (code === 93) {
effects.enter("referenceMarker");
effects.consume(code);
effects.exit("referenceMarker");
effects.exit("reference");
return ok;
}
return nok(code);
}
}

View File

@@ -0,0 +1 @@
{"version":3,"file":"label-start-image.d.ts","sourceRoot":"","sources":["label-start-image.js"],"names":[],"mappings":"AAaA,wBAAwB;AACxB,8BADW,SAAS,CAKnB;+BAZS,sBAAsB"}

View File

@@ -0,0 +1,102 @@
/**
* @import {
* Construct,
* State,
* TokenizeContext,
* Tokenizer
* } from 'micromark-util-types'
*/
import { labelEnd } from './label-end.js';
/** @type {Construct} */
export const labelStartImage = {
name: 'labelStartImage',
resolveAll: labelEnd.resolveAll,
tokenize: tokenizeLabelStartImage
};
/**
* @this {TokenizeContext}
* Context.
* @type {Tokenizer}
*/
function tokenizeLabelStartImage(effects, ok, nok) {
const self = this;
return start;
/**
* Start of label (image) start.
*
* ```markdown
* > | a ![b] c
* ^
* ```
*
* @type {State}
*/
function start(code) {
effects.enter("labelImage");
effects.enter("labelImageMarker");
effects.consume(code);
effects.exit("labelImageMarker");
return open;
}
/**
* After `!`, at `[`.
*
* ```markdown
* > | a ![b] c
* ^
* ```
*
* @type {State}
*/
function open(code) {
if (code === 91) {
effects.enter("labelMarker");
effects.consume(code);
effects.exit("labelMarker");
effects.exit("labelImage");
return after;
}
return nok(code);
}
/**
* After `![`.
*
* ```markdown
* > | a ![b] c
* ^
* ```
*
* This is needed in because, when GFM footnotes are enabled, images never
* form when started with a `^`.
* Instead, links form:
*
* ```markdown
* ![^a](b)
*
* ![^a][b]
*
* [b]: c
* ```
*
* ```html
* <p>!<a href=\"b\">^a</a></p>
* <p>!<a href=\"c\">^a</a></p>
* ```
*
* @type {State}
*/
function after(code) {
// To do: use a new field to do this, this is still needed for
// `micromark-extension-gfm-footnote`, but the `label-start-link`
// behavior isnt.
// Hidden footnotes hook.
/* c8 ignore next 3 */
return code === 94 && '_hiddenFootnoteSupport' in self.parser.constructs ? nok(code) : ok(code);
}
}

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const labelStartLink: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=label-start-link.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"line-ending.d.ts","sourceRoot":"","sources":["line-ending.js"],"names":[],"mappings":"AAcA,wBAAwB;AACxB,yBADW,SAAS,CACwD;+BATlE,sBAAsB"}

View File

@@ -0,0 +1,4 @@
/** @type {Construct} */
export const thematicBreak: Construct;
import type { Construct } from 'micromark-util-types';
//# sourceMappingURL=thematic-break.d.ts.map

View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) Titus Wormer <tituswormer@gmail.com>
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.

View File

@@ -0,0 +1,171 @@
# micromark-core-commonmark
[![Build][build-badge]][build]
[![Coverage][coverage-badge]][coverage]
[![Downloads][downloads-badge]][downloads]
[![Size][bundle-size-badge]][bundle-size]
[![Sponsors][sponsors-badge]][opencollective]
[![Backers][backers-badge]][opencollective]
[![Chat][chat-badge]][chat]
[micromark][] constructs that make up the core of CommonMark.
Some of these can be [turned off][disable], but they are often essential to
markdown and weird things might happen.
## Contents
* [What is this?](#what-is-this)
* [When should I use this?](#when-should-i-use-this)
* [Install](#install)
* [Use](#use)
* [API](#api)
* [Types](#types)
* [Compatibility](#compatibility)
* [Security](#security)
* [Contribute](#contribute)
* [License](#license)
## What is this?
This package exposes the default constructs.
## When should I use this?
This package is useful when you are making your own micromark extensions.
## Install
This package is [ESM only][esm].
In Node.js (version 16+), install with [npm][]:
```sh
npm install micromark-core-commonmark
```
In Deno with [`esm.sh`][esmsh]:
```js
import * as core from 'https://esm.sh/micromark-core-commonmark@1'
```
In browsers with [`esm.sh`][esmsh]:
```html
<script type="module">
import * as core from 'https://esm.sh/micromark-core-commonmark@1?bundle'
</script>
```
## Use
```js
import {autolink} from 'micromark-core-commonmark'
console.log(autolink) // Do things with `autolink`.
```
## API
This module exports the following identifiers: `attention`, `autolink`,
`blankLine`, `blockQuote`, `characterEscape`, `characterReference`,
`codeFenced`, `codeIndented`, `codeText`, `content`, `definition`,
`hardBreakEscape`, `headingAtx`, `htmlFlow`, `htmlText`, `labelEnd`,
`labelStartImage`, `labelStartLink`, `lineEnding`, `list`, `setextUnderline`,
`thematicBreak`.
There is no default export.
Each identifier refers to a [construct][].
See the code for more on the exported constructs.
## Types
This package is fully typed with [TypeScript][].
It exports no additional types.
## Compatibility
Projects maintained by the unified collective are compatible with maintained
versions of Node.js.
When we cut a new major release, we drop support for unmaintained versions of
Node.
This means we try to keep the current release line,
`micromark-core-commonmark@2`, compatible with Node.js 16.
This package works with `micromark@3`.
## Security
This package is safe.
See [`security.md`][securitymd] in [`micromark/.github`][health] for how to
submit a security report.
## Contribute
See [`contributing.md`][contributing] in [`micromark/.github`][health] for ways
to get started.
See [`support.md`][support] for ways to get help.
This project has a [code of conduct][coc].
By interacting with this repository, organisation, or community you agree to
abide by its terms.
## License
[MIT][license] © [Titus Wormer][author]
<!-- Definitions -->
[author]: https://wooorm.com
[backers-badge]: https://opencollective.com/unified/backers/badge.svg
[build]: https://github.com/micromark/micromark/actions
[build-badge]: https://github.com/micromark/micromark/workflows/main/badge.svg
[bundle-size]: https://bundlejs.com/?q=micromark-core-commonmark
[bundle-size-badge]: https://img.shields.io/badge/dynamic/json?label=minzipped%20size&query=$.size.compressedSize&url=https://deno.bundlejs.com/?q=micromark-core-commonmark
[chat]: https://github.com/micromark/micromark/discussions
[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg
[coc]: https://github.com/micromark/.github/blob/main/code-of-conduct.md
[construct]: https://github.com/micromark/micromark#constructs
[contributing]: https://github.com/micromark/.github/blob/main/contributing.md
[coverage]: https://codecov.io/github/micromark/micromark
[coverage-badge]: https://img.shields.io/codecov/c/github/micromark/micromark.svg
[disable]: https://github.com/micromark/micromark#case-turn-off-constructs
[downloads]: https://www.npmjs.com/package/micromark-core-commonmark
[downloads-badge]: https://img.shields.io/npm/dm/micromark-core-commonmark.svg
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
[esmsh]: https://esm.sh
[health]: https://github.com/micromark/.github
[license]: https://github.com/micromark/micromark/blob/main/license
[micromark]: https://github.com/micromark/micromark
[npm]: https://docs.npmjs.com/cli/install
[opencollective]: https://opencollective.com/unified
[securitymd]: https://github.com/micromark/.github/blob/main/security.md
[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
[support]: https://github.com/micromark/.github/blob/main/support.md
[typescript]: https://www.typescriptlang.org