feat: use go tool
This commit is contained in:
+156
@@ -0,0 +1,156 @@
|
||||
import type {CompileContext} from 'micromark-util-types'
|
||||
|
||||
export {directive} from './lib/syntax.js'
|
||||
export {directiveHtml} from './lib/html.js'
|
||||
|
||||
/**
|
||||
* Internal tuple representing an attribute.
|
||||
*/
|
||||
type AttributeTuple = [key: string, value: string]
|
||||
|
||||
/**
|
||||
* Directive attribute.
|
||||
*/
|
||||
interface Attributes {
|
||||
/**
|
||||
* Key to value.
|
||||
*/
|
||||
[key: string]: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure representing a directive.
|
||||
*/
|
||||
export interface Directive {
|
||||
/**
|
||||
* Private :)
|
||||
*/
|
||||
_fenceCount?: number | undefined
|
||||
/**
|
||||
* Object w/ HTML attributes.
|
||||
*/
|
||||
attributes?: Attributes | undefined
|
||||
/**
|
||||
* Compiled HTML content inside container directive.
|
||||
*/
|
||||
content?: string | undefined
|
||||
/**
|
||||
* Compiled HTML content that was in `[brackets]`.
|
||||
*/
|
||||
label?: string | undefined
|
||||
/**
|
||||
* Name of directive.
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* Kind.
|
||||
*/
|
||||
type: 'containerDirective' | 'leafDirective' | 'textDirective'
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a directive.
|
||||
*
|
||||
* @param this
|
||||
* Current context.
|
||||
* @param directive
|
||||
* Directive.
|
||||
* @returns
|
||||
* Signal whether the directive was handled.
|
||||
*
|
||||
* Yield `false` to let the fallback (a special handle for `'*'`) handle it.
|
||||
*/
|
||||
export type Handle = (
|
||||
this: CompileContext,
|
||||
directive: Directive
|
||||
) => boolean | undefined
|
||||
|
||||
/**
|
||||
* Configuration.
|
||||
*
|
||||
* > 👉 **Note**: the special field `'*'` can be used to specify a fallback
|
||||
* > handle to handle all otherwise unhandled directives.
|
||||
*/
|
||||
export interface HtmlOptions {
|
||||
[name: string]: Handle
|
||||
}
|
||||
|
||||
/**
|
||||
* Augment types.
|
||||
*/
|
||||
declare module 'micromark-util-types' {
|
||||
/**
|
||||
* Compile data.
|
||||
*/
|
||||
interface CompileData {
|
||||
directiveAttributes?: Array<AttributeTuple>
|
||||
directiveStack?: Array<Directive>
|
||||
}
|
||||
|
||||
/**
|
||||
* Token types.
|
||||
*/
|
||||
interface TokenTypeMap {
|
||||
directiveContainer: 'directiveContainer'
|
||||
directiveContainerAttributes: 'directiveContainerAttributes'
|
||||
directiveContainerAttributesMarker: 'directiveContainerAttributesMarker'
|
||||
directiveContainerAttribute: 'directiveContainerAttribute'
|
||||
directiveContainerAttributeId: 'directiveContainerAttributeId'
|
||||
directiveContainerAttributeIdValue: 'directiveContainerAttributeIdValue'
|
||||
directiveContainerAttributeClass: 'directiveContainerAttributeClass'
|
||||
directiveContainerAttributeClassValue: 'directiveContainerAttributeClassValue'
|
||||
directiveContainerAttributeName: 'directiveContainerAttributeName'
|
||||
directiveContainerAttributeInitializerMarker: 'directiveContainerAttributeInitializerMarker'
|
||||
directiveContainerAttributeValueLiteral: 'directiveContainerAttributeValueLiteral'
|
||||
directiveContainerAttributeValue: 'directiveContainerAttributeValue'
|
||||
directiveContainerAttributeValueMarker: 'directiveContainerAttributeValueMarker'
|
||||
directiveContainerAttributeValueData: 'directiveContainerAttributeValueData'
|
||||
directiveContainerContent: 'directiveContainerContent'
|
||||
directiveContainerFence: 'directiveContainerFence'
|
||||
directiveContainerLabel: 'directiveContainerLabel'
|
||||
directiveContainerLabelMarker: 'directiveContainerLabelMarker'
|
||||
directiveContainerLabelString: 'directiveContainerLabelString'
|
||||
directiveContainerName: 'directiveContainerName'
|
||||
directiveContainerSequence: 'directiveContainerSequence'
|
||||
|
||||
directiveLeaf: 'directiveLeaf'
|
||||
directiveLeafAttributes: 'directiveLeafAttributes'
|
||||
directiveLeafAttributesMarker: 'directiveLeafAttributesMarker'
|
||||
directiveLeafAttribute: 'directiveLeafAttribute'
|
||||
directiveLeafAttributeId: 'directiveLeafAttributeId'
|
||||
directiveLeafAttributeIdValue: 'directiveLeafAttributeIdValue'
|
||||
directiveLeafAttributeClass: 'directiveLeafAttributeClass'
|
||||
directiveLeafAttributeClassValue: 'directiveLeafAttributeClassValue'
|
||||
directiveLeafAttributeName: 'directiveLeafAttributeName'
|
||||
directiveLeafAttributeInitializerMarker: 'directiveLeafAttributeInitializerMarker'
|
||||
directiveLeafAttributeValueLiteral: 'directiveLeafAttributeValueLiteral'
|
||||
directiveLeafAttributeValue: 'directiveLeafAttributeValue'
|
||||
directiveLeafAttributeValueMarker: 'directiveLeafAttributeValueMarker'
|
||||
directiveLeafAttributeValueData: 'directiveLeafAttributeValueData'
|
||||
directiveLeafLabel: 'directiveLeafLabel'
|
||||
directiveLeafLabelMarker: 'directiveLeafLabelMarker'
|
||||
directiveLeafLabelString: 'directiveLeafLabelString'
|
||||
directiveLeafName: 'directiveLeafName'
|
||||
directiveLeafSequence: 'directiveLeafSequence'
|
||||
|
||||
directiveText: 'directiveText'
|
||||
directiveTextAttributes: 'directiveTextAttributes'
|
||||
directiveTextAttributesMarker: 'directiveTextAttributesMarker'
|
||||
directiveTextAttribute: 'directiveTextAttribute'
|
||||
directiveTextAttributeId: 'directiveTextAttributeId'
|
||||
directiveTextAttributeIdValue: 'directiveTextAttributeIdValue'
|
||||
directiveTextAttributeClass: 'directiveTextAttributeClass'
|
||||
directiveTextAttributeClassValue: 'directiveTextAttributeClassValue'
|
||||
directiveTextAttributeName: 'directiveTextAttributeName'
|
||||
directiveTextAttributeInitializerMarker: 'directiveTextAttributeInitializerMarker'
|
||||
directiveTextAttributeValueLiteral: 'directiveTextAttributeValueLiteral'
|
||||
directiveTextAttributeValue: 'directiveTextAttributeValue'
|
||||
directiveTextAttributeValueMarker: 'directiveTextAttributeValueMarker'
|
||||
directiveTextAttributeValueData: 'directiveTextAttributeValueData'
|
||||
directiveTextLabel: 'directiveTextLabel'
|
||||
directiveTextLabelMarker: 'directiveTextLabelMarker'
|
||||
directiveTextLabelString: 'directiveTextLabelString'
|
||||
directiveTextMarker: 'directiveTextMarker'
|
||||
directiveTextName: 'directiveTextName'
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// Note: more types exported from `index.d.ts`.
|
||||
export {directive} from './lib/syntax.js'
|
||||
export {directiveHtml} from './lib/html.js'
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
/** @type {Construct} */
|
||||
export const directiveContainer: Construct;
|
||||
import type { Construct } from 'micromark-util-types';
|
||||
//# sourceMappingURL=directive-container.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"directive-container.d.ts","sourceRoot":"","sources":["directive-container.js"],"names":[],"mappings":"AAYA,wBAAwB;AACxB,iCADW,SAAS,CAInB;+BAfqE,sBAAsB"}
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
/**
|
||||
* @import {Construct, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import {ok as assert} from 'devlop'
|
||||
import {factorySpace} from 'micromark-factory-space'
|
||||
import {markdownLineEnding} from 'micromark-util-character'
|
||||
import {codes, constants, types} from 'micromark-util-symbol'
|
||||
import {factoryAttributes} from './factory-attributes.js'
|
||||
import {factoryLabel} from './factory-label.js'
|
||||
import {factoryName} from './factory-name.js'
|
||||
|
||||
/** @type {Construct} */
|
||||
export const directiveContainer = {
|
||||
tokenize: tokenizeDirectiveContainer,
|
||||
concrete: true
|
||||
}
|
||||
|
||||
const label = {tokenize: tokenizeLabel, partial: true}
|
||||
const attributes = {tokenize: tokenizeAttributes, partial: true}
|
||||
const nonLazyLine = {tokenize: tokenizeNonLazyLine, partial: true}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeDirectiveContainer(effects, ok, nok) {
|
||||
const self = this
|
||||
const tail = self.events[self.events.length - 1]
|
||||
const initialSize =
|
||||
tail && tail[1].type === types.linePrefix
|
||||
? tail[2].sliceSerialize(tail[1], true).length
|
||||
: 0
|
||||
let sizeOpen = 0
|
||||
/** @type {Token} */
|
||||
let previous
|
||||
|
||||
return start
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
assert(code === codes.colon, 'expected `:`')
|
||||
effects.enter('directiveContainer')
|
||||
effects.enter('directiveContainerFence')
|
||||
effects.enter('directiveContainerSequence')
|
||||
return sequenceOpen(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function sequenceOpen(code) {
|
||||
if (code === codes.colon) {
|
||||
effects.consume(code)
|
||||
sizeOpen++
|
||||
return sequenceOpen
|
||||
}
|
||||
|
||||
if (sizeOpen < constants.codeFencedSequenceSizeMin) {
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
effects.exit('directiveContainerSequence')
|
||||
return factoryName.call(
|
||||
self,
|
||||
effects,
|
||||
afterName,
|
||||
nok,
|
||||
'directiveContainerName'
|
||||
)(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterName(code) {
|
||||
return code === codes.leftSquareBracket
|
||||
? effects.attempt(label, afterLabel, afterLabel)(code)
|
||||
: afterLabel(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterLabel(code) {
|
||||
return code === codes.leftCurlyBrace
|
||||
? effects.attempt(attributes, afterAttributes, afterAttributes)(code)
|
||||
: afterAttributes(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterAttributes(code) {
|
||||
return factorySpace(effects, openAfter, types.whitespace)(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function openAfter(code) {
|
||||
effects.exit('directiveContainerFence')
|
||||
|
||||
if (code === codes.eof) {
|
||||
return after(code)
|
||||
}
|
||||
|
||||
if (markdownLineEnding(code)) {
|
||||
if (self.interrupt) {
|
||||
return ok(code)
|
||||
}
|
||||
|
||||
return effects.attempt(nonLazyLine, contentStart, after)(code)
|
||||
}
|
||||
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function contentStart(code) {
|
||||
if (code === codes.eof) {
|
||||
return after(code)
|
||||
}
|
||||
|
||||
if (markdownLineEnding(code)) {
|
||||
return effects.check(
|
||||
nonLazyLine,
|
||||
emptyContentNonLazyLineAfter,
|
||||
after
|
||||
)(code)
|
||||
}
|
||||
|
||||
effects.enter('directiveContainerContent')
|
||||
return lineStart(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function lineStart(code) {
|
||||
return effects.attempt(
|
||||
{tokenize: tokenizeClosingFence, partial: true},
|
||||
afterContent,
|
||||
initialSize
|
||||
? factorySpace(effects, chunkStart, types.linePrefix, initialSize + 1)
|
||||
: chunkStart
|
||||
)(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function chunkStart(code) {
|
||||
if (code === codes.eof) {
|
||||
return afterContent(code)
|
||||
}
|
||||
|
||||
if (markdownLineEnding(code)) {
|
||||
return effects.check(nonLazyLine, chunkNonLazyStart, afterContent)(code)
|
||||
}
|
||||
|
||||
return chunkNonLazyStart(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function contentContinue(code) {
|
||||
if (code === codes.eof) {
|
||||
const t = effects.exit(types.chunkDocument)
|
||||
self.parser.lazy[t.start.line] = false
|
||||
return afterContent(code)
|
||||
}
|
||||
|
||||
if (markdownLineEnding(code)) {
|
||||
return effects.check(nonLazyLine, nonLazyLineAfter, lineAfter)(code)
|
||||
}
|
||||
|
||||
effects.consume(code)
|
||||
return contentContinue
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function chunkNonLazyStart(code) {
|
||||
const token = effects.enter(types.chunkDocument, {
|
||||
contentType: constants.contentTypeDocument,
|
||||
previous
|
||||
})
|
||||
if (previous) previous.next = token
|
||||
previous = token
|
||||
return contentContinue(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function emptyContentNonLazyLineAfter(code) {
|
||||
effects.enter('directiveContainerContent')
|
||||
return lineStart(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function nonLazyLineAfter(code) {
|
||||
effects.consume(code)
|
||||
const t = effects.exit(types.chunkDocument)
|
||||
self.parser.lazy[t.start.line] = false
|
||||
return lineStart
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function lineAfter(code) {
|
||||
const t = effects.exit(types.chunkDocument)
|
||||
self.parser.lazy[t.start.line] = false
|
||||
return afterContent(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterContent(code) {
|
||||
effects.exit('directiveContainerContent')
|
||||
return after(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function after(code) {
|
||||
effects.exit('directiveContainer')
|
||||
return ok(code)
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeClosingFence(effects, ok, nok) {
|
||||
let size = 0
|
||||
assert(self.parser.constructs.disable.null, 'expected `disable.null`')
|
||||
return factorySpace(
|
||||
effects,
|
||||
closingPrefixAfter,
|
||||
types.linePrefix,
|
||||
self.parser.constructs.disable.null.includes('codeIndented')
|
||||
? undefined
|
||||
: constants.tabSize
|
||||
)
|
||||
|
||||
/** @type {State} */
|
||||
function closingPrefixAfter(code) {
|
||||
effects.enter('directiveContainerFence')
|
||||
effects.enter('directiveContainerSequence')
|
||||
return closingSequence(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function closingSequence(code) {
|
||||
if (code === codes.colon) {
|
||||
effects.consume(code)
|
||||
size++
|
||||
return closingSequence
|
||||
}
|
||||
|
||||
if (size < sizeOpen) return nok(code)
|
||||
effects.exit('directiveContainerSequence')
|
||||
return factorySpace(effects, closingSequenceEnd, types.whitespace)(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function closingSequenceEnd(code) {
|
||||
if (code === codes.eof || markdownLineEnding(code)) {
|
||||
effects.exit('directiveContainerFence')
|
||||
return ok(code)
|
||||
}
|
||||
|
||||
return nok(code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeLabel(effects, ok, nok) {
|
||||
// Always a `[`
|
||||
return factoryLabel(
|
||||
effects,
|
||||
ok,
|
||||
nok,
|
||||
'directiveContainerLabel',
|
||||
'directiveContainerLabelMarker',
|
||||
'directiveContainerLabelString',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeAttributes(effects, ok, nok) {
|
||||
// Always a `{`
|
||||
return factoryAttributes(
|
||||
effects,
|
||||
ok,
|
||||
nok,
|
||||
'directiveContainerAttributes',
|
||||
'directiveContainerAttributesMarker',
|
||||
'directiveContainerAttribute',
|
||||
'directiveContainerAttributeId',
|
||||
'directiveContainerAttributeClass',
|
||||
'directiveContainerAttributeName',
|
||||
'directiveContainerAttributeInitializerMarker',
|
||||
'directiveContainerAttributeValueLiteral',
|
||||
'directiveContainerAttributeValue',
|
||||
'directiveContainerAttributeValueMarker',
|
||||
'directiveContainerAttributeValueData',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeNonLazyLine(effects, ok, nok) {
|
||||
const self = this
|
||||
|
||||
return start
|
||||
|
||||
/** @type {State} */
|
||||
function start(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)
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
/** @type {Construct} */
|
||||
export const directiveLeaf: Construct;
|
||||
import type { Construct } from 'micromark-util-types';
|
||||
//# sourceMappingURL=directive-leaf.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"directive-leaf.d.ts","sourceRoot":"","sources":["directive-leaf.js"],"names":[],"mappings":"AAYA,wBAAwB;AACxB,4BADW,SAAS,CAC0C;+BAZC,sBAAsB"}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* @import {Construct, State, TokenizeContext, Tokenizer} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import {ok as assert} from 'devlop'
|
||||
import {factorySpace} from 'micromark-factory-space'
|
||||
import {markdownLineEnding} from 'micromark-util-character'
|
||||
import {codes, types} from 'micromark-util-symbol'
|
||||
import {factoryAttributes} from './factory-attributes.js'
|
||||
import {factoryLabel} from './factory-label.js'
|
||||
import {factoryName} from './factory-name.js'
|
||||
|
||||
/** @type {Construct} */
|
||||
export const directiveLeaf = {tokenize: tokenizeDirectiveLeaf}
|
||||
|
||||
const label = {tokenize: tokenizeLabel, partial: true}
|
||||
const attributes = {tokenize: tokenizeAttributes, partial: true}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeDirectiveLeaf(effects, ok, nok) {
|
||||
const self = this
|
||||
|
||||
return start
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
assert(code === codes.colon, 'expected `:`')
|
||||
effects.enter('directiveLeaf')
|
||||
effects.enter('directiveLeafSequence')
|
||||
effects.consume(code)
|
||||
return inStart
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function inStart(code) {
|
||||
if (code === codes.colon) {
|
||||
effects.consume(code)
|
||||
effects.exit('directiveLeafSequence')
|
||||
return factoryName.call(
|
||||
self,
|
||||
effects,
|
||||
afterName,
|
||||
nok,
|
||||
'directiveLeafName'
|
||||
)
|
||||
}
|
||||
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterName(code) {
|
||||
return code === codes.leftSquareBracket
|
||||
? effects.attempt(label, afterLabel, afterLabel)(code)
|
||||
: afterLabel(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterLabel(code) {
|
||||
return code === codes.leftCurlyBrace
|
||||
? effects.attempt(attributes, afterAttributes, afterAttributes)(code)
|
||||
: afterAttributes(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterAttributes(code) {
|
||||
return factorySpace(effects, end, types.whitespace)(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function end(code) {
|
||||
if (code === codes.eof || markdownLineEnding(code)) {
|
||||
effects.exit('directiveLeaf')
|
||||
return ok(code)
|
||||
}
|
||||
|
||||
return nok(code)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeLabel(effects, ok, nok) {
|
||||
// Always a `[`
|
||||
return factoryLabel(
|
||||
effects,
|
||||
ok,
|
||||
nok,
|
||||
'directiveLeafLabel',
|
||||
'directiveLeafLabelMarker',
|
||||
'directiveLeafLabelString',
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeAttributes(effects, ok, nok) {
|
||||
// Always a `{`
|
||||
return factoryAttributes(
|
||||
effects,
|
||||
ok,
|
||||
nok,
|
||||
'directiveLeafAttributes',
|
||||
'directiveLeafAttributesMarker',
|
||||
'directiveLeafAttribute',
|
||||
'directiveLeafAttributeId',
|
||||
'directiveLeafAttributeClass',
|
||||
'directiveLeafAttributeName',
|
||||
'directiveLeafAttributeInitializerMarker',
|
||||
'directiveLeafAttributeValueLiteral',
|
||||
'directiveLeafAttributeValue',
|
||||
'directiveLeafAttributeValueMarker',
|
||||
'directiveLeafAttributeValueData',
|
||||
true
|
||||
)
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
/** @type {Construct} */
|
||||
export const directiveText: Construct;
|
||||
import type { Construct } from 'micromark-util-types';
|
||||
//# sourceMappingURL=directive-text.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"directive-text.d.ts","sourceRoot":"","sources":["directive-text.js"],"names":[],"mappings":"AAUA,wBAAwB;AACxB,4BADW,SAAS,CAInB;+BAbwE,sBAAsB"}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* @import {Construct, Previous, State, TokenizeContext, Tokenizer} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import {ok as assert} from 'devlop'
|
||||
import {codes, types} from 'micromark-util-symbol'
|
||||
import {factoryAttributes} from './factory-attributes.js'
|
||||
import {factoryLabel} from './factory-label.js'
|
||||
import {factoryName} from './factory-name.js'
|
||||
|
||||
/** @type {Construct} */
|
||||
export const directiveText = {
|
||||
tokenize: tokenizeDirectiveText,
|
||||
previous
|
||||
}
|
||||
|
||||
const label = {tokenize: tokenizeLabel, partial: true}
|
||||
const attributes = {tokenize: tokenizeAttributes, partial: true}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Previous}
|
||||
*/
|
||||
function previous(code) {
|
||||
// If there is a previous code, there will always be a tail.
|
||||
return (
|
||||
code !== codes.colon ||
|
||||
this.events[this.events.length - 1][1].type === types.characterEscape
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeDirectiveText(effects, ok, nok) {
|
||||
const self = this
|
||||
|
||||
return start
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
assert(code === codes.colon, 'expected `:`')
|
||||
assert(previous.call(self, self.previous), 'expected correct previous')
|
||||
effects.enter('directiveText')
|
||||
effects.enter('directiveTextMarker')
|
||||
effects.consume(code)
|
||||
effects.exit('directiveTextMarker')
|
||||
return factoryName.call(self, effects, afterName, nok, 'directiveTextName')
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterName(code) {
|
||||
return code === codes.colon
|
||||
? nok(code)
|
||||
: code === codes.leftSquareBracket
|
||||
? effects.attempt(label, afterLabel, afterLabel)(code)
|
||||
: afterLabel(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterLabel(code) {
|
||||
return code === codes.leftCurlyBrace
|
||||
? effects.attempt(attributes, afterAttributes, afterAttributes)(code)
|
||||
: afterAttributes(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterAttributes(code) {
|
||||
effects.exit('directiveText')
|
||||
return ok(code)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeLabel(effects, ok, nok) {
|
||||
// Always a `[`
|
||||
return factoryLabel(
|
||||
effects,
|
||||
ok,
|
||||
nok,
|
||||
'directiveTextLabel',
|
||||
'directiveTextLabelMarker',
|
||||
'directiveTextLabelString'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeAttributes(effects, ok, nok) {
|
||||
// Always a `{`
|
||||
return factoryAttributes(
|
||||
effects,
|
||||
ok,
|
||||
nok,
|
||||
'directiveTextAttributes',
|
||||
'directiveTextAttributesMarker',
|
||||
'directiveTextAttribute',
|
||||
'directiveTextAttributeId',
|
||||
'directiveTextAttributeClass',
|
||||
'directiveTextAttributeName',
|
||||
'directiveTextAttributeInitializerMarker',
|
||||
'directiveTextAttributeValueLiteral',
|
||||
'directiveTextAttributeValue',
|
||||
'directiveTextAttributeValueMarker',
|
||||
'directiveTextAttributeValueData'
|
||||
)
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} attributesType
|
||||
* @param {TokenType} attributesMarkerType
|
||||
* @param {TokenType} attributeType
|
||||
* @param {TokenType} attributeIdType
|
||||
* @param {TokenType} attributeClassType
|
||||
* @param {TokenType} attributeNameType
|
||||
* @param {TokenType} attributeInitializerType
|
||||
* @param {TokenType} attributeValueLiteralType
|
||||
* @param {TokenType} attributeValueType
|
||||
* @param {TokenType} attributeValueMarker
|
||||
* @param {TokenType} attributeValueData
|
||||
* @param {boolean | undefined} [disallowEol=false]
|
||||
*/
|
||||
export function factoryAttributes(effects: Effects, ok: State, nok: State, attributesType: TokenType, attributesMarkerType: TokenType, attributeType: TokenType, attributeIdType: TokenType, attributeClassType: TokenType, attributeNameType: TokenType, attributeInitializerType: TokenType, attributeValueLiteralType: TokenType, attributeValueType: TokenType, attributeValueMarker: TokenType, attributeValueData: TokenType, disallowEol?: boolean | undefined): (code: Code) => State | undefined;
|
||||
import type { Effects } from 'micromark-util-types';
|
||||
import type { State } from 'micromark-util-types';
|
||||
import type { TokenType } from 'micromark-util-types';
|
||||
import type { Code } from 'micromark-util-types';
|
||||
//# sourceMappingURL=factory-attributes.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"factory-attributes.d.ts","sourceRoot":"","sources":["factory-attributes.js"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;GAgBG;AACH,2CAhBW,OAAO,MACP,KAAK,OACL,KAAK,kBACL,SAAS,wBACT,SAAS,iBACT,SAAS,mBACT,SAAS,sBACT,SAAS,qBACT,SAAS,4BACT,SAAS,6BACT,SAAS,sBACT,SAAS,wBACT,SAAS,sBACT,SAAS,gBACT,OAAO,GAAG,SAAS,qCA4T7B;6BA1ViD,sBAAsB;2BAAtB,sBAAsB;+BAAtB,sBAAsB;0BAAtB,sBAAsB"}
|
||||
+348
@@ -0,0 +1,348 @@
|
||||
/**
|
||||
* @import {Code, Effects, State, TokenType} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import {ok as assert} from 'devlop'
|
||||
import {factorySpace} from 'micromark-factory-space'
|
||||
import {factoryWhitespace} from 'micromark-factory-whitespace'
|
||||
import {
|
||||
markdownLineEnding,
|
||||
markdownLineEndingOrSpace,
|
||||
markdownSpace,
|
||||
unicodePunctuation,
|
||||
unicodeWhitespace
|
||||
} from 'micromark-util-character'
|
||||
import {codes, types} from 'micromark-util-symbol'
|
||||
|
||||
/**
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} attributesType
|
||||
* @param {TokenType} attributesMarkerType
|
||||
* @param {TokenType} attributeType
|
||||
* @param {TokenType} attributeIdType
|
||||
* @param {TokenType} attributeClassType
|
||||
* @param {TokenType} attributeNameType
|
||||
* @param {TokenType} attributeInitializerType
|
||||
* @param {TokenType} attributeValueLiteralType
|
||||
* @param {TokenType} attributeValueType
|
||||
* @param {TokenType} attributeValueMarker
|
||||
* @param {TokenType} attributeValueData
|
||||
* @param {boolean | undefined} [disallowEol=false]
|
||||
*/
|
||||
export function factoryAttributes(
|
||||
effects,
|
||||
ok,
|
||||
nok,
|
||||
attributesType,
|
||||
attributesMarkerType,
|
||||
attributeType,
|
||||
attributeIdType,
|
||||
attributeClassType,
|
||||
attributeNameType,
|
||||
attributeInitializerType,
|
||||
attributeValueLiteralType,
|
||||
attributeValueType,
|
||||
attributeValueMarker,
|
||||
attributeValueData,
|
||||
disallowEol
|
||||
) {
|
||||
/** @type {TokenType} */
|
||||
let type
|
||||
/** @type {Code | undefined} */
|
||||
let marker
|
||||
|
||||
return start
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
assert(code === codes.leftCurlyBrace, 'expected `{`')
|
||||
effects.enter(attributesType)
|
||||
effects.enter(attributesMarkerType)
|
||||
effects.consume(code)
|
||||
effects.exit(attributesMarkerType)
|
||||
return between
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function between(code) {
|
||||
if (code === codes.numberSign) {
|
||||
type = attributeIdType
|
||||
return shortcutStart(code)
|
||||
}
|
||||
|
||||
if (code === codes.dot) {
|
||||
type = attributeClassType
|
||||
return shortcutStart(code)
|
||||
}
|
||||
|
||||
if (disallowEol && markdownSpace(code)) {
|
||||
return factorySpace(effects, between, types.whitespace)(code)
|
||||
}
|
||||
|
||||
if (!disallowEol && markdownLineEndingOrSpace(code)) {
|
||||
return factoryWhitespace(effects, between)(code)
|
||||
}
|
||||
|
||||
if (
|
||||
code === codes.eof ||
|
||||
markdownLineEnding(code) ||
|
||||
unicodeWhitespace(code) ||
|
||||
(unicodePunctuation(code) &&
|
||||
code !== codes.dash &&
|
||||
code !== codes.underscore)
|
||||
) {
|
||||
return end(code)
|
||||
}
|
||||
|
||||
effects.enter(attributeType)
|
||||
effects.enter(attributeNameType)
|
||||
effects.consume(code)
|
||||
return name
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function shortcutStart(code) {
|
||||
// Assume it’s registered.
|
||||
const markerType = /** @type {TokenType} */ (type + 'Marker')
|
||||
effects.enter(attributeType)
|
||||
effects.enter(type)
|
||||
effects.enter(markerType)
|
||||
effects.consume(code)
|
||||
effects.exit(markerType)
|
||||
return shortcutStartAfter
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function shortcutStartAfter(code) {
|
||||
if (
|
||||
code === codes.eof ||
|
||||
code === codes.quotationMark ||
|
||||
code === codes.numberSign ||
|
||||
code === codes.apostrophe ||
|
||||
code === codes.dot ||
|
||||
code === codes.lessThan ||
|
||||
code === codes.equalsTo ||
|
||||
code === codes.greaterThan ||
|
||||
code === codes.graveAccent ||
|
||||
code === codes.rightCurlyBrace ||
|
||||
markdownLineEndingOrSpace(code)
|
||||
) {
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
// Assume it’s registered.
|
||||
const valueType = /** @type {TokenType} */ (type + 'Value')
|
||||
effects.enter(valueType)
|
||||
effects.consume(code)
|
||||
return shortcut
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function shortcut(code) {
|
||||
if (
|
||||
code === codes.eof ||
|
||||
code === codes.quotationMark ||
|
||||
code === codes.apostrophe ||
|
||||
code === codes.lessThan ||
|
||||
code === codes.equalsTo ||
|
||||
code === codes.greaterThan ||
|
||||
code === codes.graveAccent
|
||||
) {
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
if (
|
||||
code === codes.numberSign ||
|
||||
code === codes.dot ||
|
||||
code === codes.rightCurlyBrace ||
|
||||
markdownLineEndingOrSpace(code)
|
||||
) {
|
||||
// Assume it’s registered.
|
||||
const valueType = /** @type {TokenType} */ (type + 'Value')
|
||||
effects.exit(valueType)
|
||||
effects.exit(type)
|
||||
effects.exit(attributeType)
|
||||
return between(code)
|
||||
}
|
||||
|
||||
effects.consume(code)
|
||||
return shortcut
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function name(code) {
|
||||
if (
|
||||
code === codes.eof ||
|
||||
markdownLineEnding(code) ||
|
||||
unicodeWhitespace(code) ||
|
||||
(unicodePunctuation(code) &&
|
||||
code !== codes.dash &&
|
||||
code !== codes.dot &&
|
||||
code !== codes.colon &&
|
||||
code !== codes.underscore)
|
||||
) {
|
||||
effects.exit(attributeNameType)
|
||||
|
||||
if (disallowEol && markdownSpace(code)) {
|
||||
return factorySpace(effects, nameAfter, types.whitespace)(code)
|
||||
}
|
||||
|
||||
if (!disallowEol && markdownLineEndingOrSpace(code)) {
|
||||
return factoryWhitespace(effects, nameAfter)(code)
|
||||
}
|
||||
|
||||
return nameAfter(code)
|
||||
}
|
||||
|
||||
effects.consume(code)
|
||||
return name
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function nameAfter(code) {
|
||||
if (code === codes.equalsTo) {
|
||||
effects.enter(attributeInitializerType)
|
||||
effects.consume(code)
|
||||
effects.exit(attributeInitializerType)
|
||||
return valueBefore
|
||||
}
|
||||
|
||||
// Attribute w/o value.
|
||||
effects.exit(attributeType)
|
||||
return between(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueBefore(code) {
|
||||
if (
|
||||
code === codes.eof ||
|
||||
code === codes.lessThan ||
|
||||
code === codes.equalsTo ||
|
||||
code === codes.greaterThan ||
|
||||
code === codes.graveAccent ||
|
||||
code === codes.rightCurlyBrace ||
|
||||
(disallowEol && markdownLineEnding(code))
|
||||
) {
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
if (code === codes.quotationMark || code === codes.apostrophe) {
|
||||
effects.enter(attributeValueLiteralType)
|
||||
effects.enter(attributeValueMarker)
|
||||
effects.consume(code)
|
||||
effects.exit(attributeValueMarker)
|
||||
marker = code
|
||||
return valueQuotedStart
|
||||
}
|
||||
|
||||
if (disallowEol && markdownSpace(code)) {
|
||||
return factorySpace(effects, valueBefore, types.whitespace)(code)
|
||||
}
|
||||
|
||||
if (!disallowEol && markdownLineEndingOrSpace(code)) {
|
||||
return factoryWhitespace(effects, valueBefore)(code)
|
||||
}
|
||||
|
||||
effects.enter(attributeValueType)
|
||||
effects.enter(attributeValueData)
|
||||
effects.consume(code)
|
||||
marker = undefined
|
||||
return valueUnquoted
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueUnquoted(code) {
|
||||
if (
|
||||
code === codes.eof ||
|
||||
code === codes.quotationMark ||
|
||||
code === codes.apostrophe ||
|
||||
code === codes.lessThan ||
|
||||
code === codes.equalsTo ||
|
||||
code === codes.greaterThan ||
|
||||
code === codes.graveAccent
|
||||
) {
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
if (code === codes.rightCurlyBrace || markdownLineEndingOrSpace(code)) {
|
||||
effects.exit(attributeValueData)
|
||||
effects.exit(attributeValueType)
|
||||
effects.exit(attributeType)
|
||||
return between(code)
|
||||
}
|
||||
|
||||
effects.consume(code)
|
||||
return valueUnquoted
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueQuotedStart(code) {
|
||||
if (code === marker) {
|
||||
effects.enter(attributeValueMarker)
|
||||
effects.consume(code)
|
||||
effects.exit(attributeValueMarker)
|
||||
effects.exit(attributeValueLiteralType)
|
||||
effects.exit(attributeType)
|
||||
return valueQuotedAfter
|
||||
}
|
||||
|
||||
effects.enter(attributeValueType)
|
||||
return valueQuotedBetween(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueQuotedBetween(code) {
|
||||
if (code === marker) {
|
||||
effects.exit(attributeValueType)
|
||||
return valueQuotedStart(code)
|
||||
}
|
||||
|
||||
if (code === codes.eof) {
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
// Note: blank lines can’t exist in content.
|
||||
if (markdownLineEnding(code)) {
|
||||
return disallowEol
|
||||
? nok(code)
|
||||
: factoryWhitespace(effects, valueQuotedBetween)(code)
|
||||
}
|
||||
|
||||
effects.enter(attributeValueData)
|
||||
effects.consume(code)
|
||||
return valueQuoted
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueQuoted(code) {
|
||||
if (code === marker || code === codes.eof || markdownLineEnding(code)) {
|
||||
effects.exit(attributeValueData)
|
||||
return valueQuotedBetween(code)
|
||||
}
|
||||
|
||||
effects.consume(code)
|
||||
return valueQuoted
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueQuotedAfter(code) {
|
||||
return code === codes.rightCurlyBrace || markdownLineEndingOrSpace(code)
|
||||
? between(code)
|
||||
: end(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function end(code) {
|
||||
if (code === codes.rightCurlyBrace) {
|
||||
effects.enter(attributesMarkerType)
|
||||
effects.consume(code)
|
||||
effects.exit(attributesMarkerType)
|
||||
effects.exit(attributesType)
|
||||
return ok
|
||||
}
|
||||
|
||||
return nok(code)
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} type
|
||||
* @param {TokenType} markerType
|
||||
* @param {TokenType} stringType
|
||||
* @param {boolean | undefined} [disallowEol=false]
|
||||
*/
|
||||
export function factoryLabel(effects: Effects, ok: State, nok: State, type: TokenType, markerType: TokenType, stringType: TokenType, disallowEol?: boolean | undefined): (code: Code) => State | undefined;
|
||||
import type { Effects } from 'micromark-util-types';
|
||||
import type { State } from 'micromark-util-types';
|
||||
import type { TokenType } from 'micromark-util-types';
|
||||
import type { Code } from 'micromark-util-types';
|
||||
//# sourceMappingURL=factory-label.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"factory-label.d.ts","sourceRoot":"","sources":["factory-label.js"],"names":[],"mappings":"AAaA;;;;;;;;GAQG;AACH,sCARW,OAAO,MACP,KAAK,OACL,KAAK,QACL,SAAS,cACT,SAAS,cACT,SAAS,gBACT,OAAO,GAAG,SAAS,qCAkH7B;6BArIwD,sBAAsB;2BAAtB,sBAAsB;+BAAtB,sBAAsB;0BAAtB,sBAAsB"}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* @import {Code, Effects, State, Token, TokenType} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import {ok as assert} from 'devlop'
|
||||
import {markdownLineEnding} from 'micromark-util-character'
|
||||
import {codes, constants, types} from 'micromark-util-symbol'
|
||||
|
||||
// This is a fork of:
|
||||
// <https://github.com/micromark/micromark/tree/main/packages/micromark-factory-label>
|
||||
// to allow empty labels, balanced brackets (such as for nested directives),
|
||||
// text instead of strings, and optionally disallows EOLs.
|
||||
|
||||
/**
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} type
|
||||
* @param {TokenType} markerType
|
||||
* @param {TokenType} stringType
|
||||
* @param {boolean | undefined} [disallowEol=false]
|
||||
*/
|
||||
export function factoryLabel(
|
||||
effects,
|
||||
ok,
|
||||
nok,
|
||||
type,
|
||||
markerType,
|
||||
stringType,
|
||||
disallowEol
|
||||
) {
|
||||
let size = 0
|
||||
let balance = 0
|
||||
/** @type {Token | undefined} */
|
||||
let previous
|
||||
|
||||
return start
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
assert(code === codes.leftSquareBracket, 'expected `[`')
|
||||
effects.enter(type)
|
||||
effects.enter(markerType)
|
||||
effects.consume(code)
|
||||
effects.exit(markerType)
|
||||
return afterStart
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterStart(code) {
|
||||
if (code === codes.rightSquareBracket) {
|
||||
effects.enter(markerType)
|
||||
effects.consume(code)
|
||||
effects.exit(markerType)
|
||||
effects.exit(type)
|
||||
return ok
|
||||
}
|
||||
|
||||
effects.enter(stringType)
|
||||
return lineStart(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function lineStart(code) {
|
||||
if (code === codes.rightSquareBracket && !balance) {
|
||||
return atClosingBrace(code)
|
||||
}
|
||||
|
||||
const token = effects.enter(types.chunkText, {
|
||||
_contentTypeTextTrailing: true,
|
||||
contentType: constants.contentTypeText,
|
||||
previous
|
||||
})
|
||||
if (previous) previous.next = token
|
||||
previous = token
|
||||
return data(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function data(code) {
|
||||
if (code === codes.eof || size > constants.linkReferenceSizeMax) {
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
if (
|
||||
code === codes.leftSquareBracket &&
|
||||
++balance > constants.linkResourceDestinationBalanceMax
|
||||
) {
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
if (code === codes.rightSquareBracket && !balance--) {
|
||||
effects.exit(types.chunkText)
|
||||
return atClosingBrace(code)
|
||||
}
|
||||
|
||||
if (markdownLineEnding(code)) {
|
||||
if (disallowEol) {
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
effects.consume(code)
|
||||
effects.exit(types.chunkText)
|
||||
return lineStart
|
||||
}
|
||||
|
||||
effects.consume(code)
|
||||
return code === codes.backslash ? dataEscape : data
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function dataEscape(code) {
|
||||
if (
|
||||
code === codes.leftSquareBracket ||
|
||||
code === codes.backslash ||
|
||||
code === codes.rightSquareBracket
|
||||
) {
|
||||
effects.consume(code)
|
||||
size++
|
||||
return data
|
||||
}
|
||||
|
||||
return data(code)
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function atClosingBrace(code) {
|
||||
effects.exit(stringType)
|
||||
effects.enter(markerType)
|
||||
effects.consume(code)
|
||||
effects.exit(markerType)
|
||||
effects.exit(type)
|
||||
return ok
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} type
|
||||
*/
|
||||
export function factoryName(this: TokenizeContext, effects: Effects, ok: State, nok: State, type: TokenType): (code: Code) => State | undefined;
|
||||
import type { Effects } from 'micromark-util-types';
|
||||
import type { State } from 'micromark-util-types';
|
||||
import type { TokenType } from 'micromark-util-types';
|
||||
import type { TokenizeContext } from 'micromark-util-types';
|
||||
import type { Code } from 'micromark-util-types';
|
||||
//# sourceMappingURL=factory-name.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"factory-name.d.ts","sourceRoot":"","sources":["factory-name.js"],"names":[],"mappings":"AAWA;;;;;;GAMG;AACH,4DALW,OAAO,MACP,KAAK,OACL,KAAK,QACL,SAAS,qCA0CnB;6BAzDkE,sBAAsB;2BAAtB,sBAAsB;+BAAtB,sBAAsB;qCAAtB,sBAAsB;0BAAtB,sBAAsB"}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @import {Code, Effects, State, TokenizeContext, TokenType} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import {
|
||||
markdownLineEnding,
|
||||
unicodePunctuation,
|
||||
unicodeWhitespace
|
||||
} from 'micromark-util-character'
|
||||
import {codes} from 'micromark-util-symbol'
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} type
|
||||
*/
|
||||
export function factoryName(effects, ok, nok, type) {
|
||||
const self = this
|
||||
|
||||
return start
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
if (
|
||||
code === codes.eof ||
|
||||
markdownLineEnding(code) ||
|
||||
unicodePunctuation(code) ||
|
||||
unicodeWhitespace(code)
|
||||
) {
|
||||
return nok(code)
|
||||
}
|
||||
|
||||
effects.enter(type)
|
||||
effects.consume(code)
|
||||
return name
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function name(code) {
|
||||
if (
|
||||
code === codes.eof ||
|
||||
markdownLineEnding(code) ||
|
||||
unicodeWhitespace(code) ||
|
||||
(unicodePunctuation(code) &&
|
||||
code !== codes.dash &&
|
||||
code !== codes.underscore)
|
||||
) {
|
||||
effects.exit(type)
|
||||
return self.previous === codes.dash || self.previous === codes.underscore
|
||||
? nok(code)
|
||||
: ok(code)
|
||||
}
|
||||
|
||||
effects.consume(code)
|
||||
return name
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Create an extension for `micromark` to support directives when serializing
|
||||
* to HTML.
|
||||
*
|
||||
* @param {HtmlOptions | null | undefined} [options={}]
|
||||
* Configuration (default: `{}`).
|
||||
* @returns {HtmlExtension}
|
||||
* Extension for `micromark` that can be passed in `htmlExtensions`, to
|
||||
* support directives when serializing to HTML.
|
||||
*/
|
||||
export function directiveHtml(options?: HtmlOptions | null | undefined): HtmlExtension;
|
||||
import type { HtmlOptions } from 'micromark-extension-directive';
|
||||
import type { HtmlExtension } from 'micromark-util-types';
|
||||
//# sourceMappingURL=html.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["html.js"],"names":[],"mappings":"AAUA;;;;;;;;;GASG;AACH,wCANW,WAAW,GAAG,IAAI,GAAG,SAAS,GAE5B,aAAa,CAwPzB;iCAvQwC,+BAA+B;mCACG,sBAAsB"}
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* @import {Directive, HtmlOptions} from 'micromark-extension-directive'
|
||||
* @import {CompileContext, Handle as MicromarkHandle, HtmlExtension} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import {ok as assert} from 'devlop'
|
||||
import {parseEntities} from 'parse-entities'
|
||||
|
||||
const own = {}.hasOwnProperty
|
||||
|
||||
/**
|
||||
* Create an extension for `micromark` to support directives when serializing
|
||||
* to HTML.
|
||||
*
|
||||
* @param {HtmlOptions | null | undefined} [options={}]
|
||||
* Configuration (default: `{}`).
|
||||
* @returns {HtmlExtension}
|
||||
* Extension for `micromark` that can be passed in `htmlExtensions`, to
|
||||
* support directives when serializing to HTML.
|
||||
*/
|
||||
export function directiveHtml(options) {
|
||||
const options_ = options || {}
|
||||
return {
|
||||
enter: {
|
||||
directiveContainer() {
|
||||
enter.call(this, 'containerDirective')
|
||||
},
|
||||
directiveContainerAttributes: enterAttributes,
|
||||
directiveContainerLabel: enterLabel,
|
||||
directiveContainerContent() {
|
||||
this.buffer()
|
||||
},
|
||||
|
||||
directiveLeaf() {
|
||||
enter.call(this, 'leafDirective')
|
||||
},
|
||||
directiveLeafAttributes: enterAttributes,
|
||||
directiveLeafLabel: enterLabel,
|
||||
|
||||
directiveText() {
|
||||
enter.call(this, 'textDirective')
|
||||
},
|
||||
directiveTextAttributes: enterAttributes,
|
||||
directiveTextLabel: enterLabel
|
||||
},
|
||||
exit: {
|
||||
directiveContainer: exit,
|
||||
directiveContainerAttributeClassValue: exitAttributeClassValue,
|
||||
directiveContainerAttributeIdValue: exitAttributeIdValue,
|
||||
directiveContainerAttributeName: exitAttributeName,
|
||||
directiveContainerAttributeValue: exitAttributeValue,
|
||||
directiveContainerAttributes: exitAttributes,
|
||||
directiveContainerContent: exitContainerContent,
|
||||
directiveContainerFence: exitContainerFence,
|
||||
directiveContainerLabel: exitLabel,
|
||||
directiveContainerName: exitName,
|
||||
|
||||
directiveLeaf: exit,
|
||||
directiveLeafAttributeClassValue: exitAttributeClassValue,
|
||||
directiveLeafAttributeIdValue: exitAttributeIdValue,
|
||||
directiveLeafAttributeName: exitAttributeName,
|
||||
directiveLeafAttributeValue: exitAttributeValue,
|
||||
directiveLeafAttributes: exitAttributes,
|
||||
directiveLeafLabel: exitLabel,
|
||||
directiveLeafName: exitName,
|
||||
|
||||
directiveText: exit,
|
||||
directiveTextAttributeClassValue: exitAttributeClassValue,
|
||||
directiveTextAttributeIdValue: exitAttributeIdValue,
|
||||
directiveTextAttributeName: exitAttributeName,
|
||||
directiveTextAttributeValue: exitAttributeValue,
|
||||
directiveTextAttributes: exitAttributes,
|
||||
directiveTextLabel: exitLabel,
|
||||
directiveTextName: exitName
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @param {Directive['type']} type
|
||||
*/
|
||||
function enter(type) {
|
||||
let stack = this.getData('directiveStack')
|
||||
if (!stack) this.setData('directiveStack', (stack = []))
|
||||
stack.push({type, name: ''})
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitName(token) {
|
||||
const stack = this.getData('directiveStack')
|
||||
assert(stack, 'expected directive stack')
|
||||
stack[stack.length - 1].name = this.sliceSerialize(token)
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function enterLabel() {
|
||||
this.buffer()
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitLabel() {
|
||||
const data = this.resume()
|
||||
const stack = this.getData('directiveStack')
|
||||
assert(stack, 'expected directive stack')
|
||||
stack[stack.length - 1].label = data
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function enterAttributes() {
|
||||
this.buffer()
|
||||
this.setData('directiveAttributes', [])
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitAttributeIdValue(token) {
|
||||
const attributes = this.getData('directiveAttributes')
|
||||
assert(attributes, 'expected attributes')
|
||||
attributes.push([
|
||||
'id',
|
||||
parseEntities(this.sliceSerialize(token), {
|
||||
attribute: true
|
||||
})
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitAttributeClassValue(token) {
|
||||
const attributes = this.getData('directiveAttributes')
|
||||
assert(attributes, 'expected attributes')
|
||||
|
||||
attributes.push([
|
||||
'class',
|
||||
parseEntities(this.sliceSerialize(token), {
|
||||
attribute: true
|
||||
})
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitAttributeName(token) {
|
||||
// Attribute names in CommonMark are significantly limited, so character
|
||||
// references can’t exist.
|
||||
const attributes = this.getData('directiveAttributes')
|
||||
assert(attributes, 'expected attributes')
|
||||
|
||||
attributes.push([this.sliceSerialize(token), ''])
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitAttributeValue(token) {
|
||||
const attributes = this.getData('directiveAttributes')
|
||||
assert(attributes, 'expected attributes')
|
||||
attributes[attributes.length - 1][1] = parseEntities(
|
||||
this.sliceSerialize(token),
|
||||
{attribute: true}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitAttributes() {
|
||||
const stack = this.getData('directiveStack')
|
||||
assert(stack, 'expected directive stack')
|
||||
const attributes = this.getData('directiveAttributes')
|
||||
assert(attributes, 'expected attributes')
|
||||
/** @type {Record<string, string>} */
|
||||
const cleaned = {}
|
||||
let index = -1
|
||||
|
||||
while (++index < attributes.length) {
|
||||
const attribute = attributes[index]
|
||||
|
||||
if (attribute[0] === 'class' && cleaned.class) {
|
||||
cleaned.class += ' ' + attribute[1]
|
||||
} else {
|
||||
cleaned[attribute[0]] = attribute[1]
|
||||
}
|
||||
}
|
||||
|
||||
this.resume()
|
||||
this.setData('directiveAttributes')
|
||||
stack[stack.length - 1].attributes = cleaned
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitContainerContent() {
|
||||
const data = this.resume()
|
||||
const stack = this.getData('directiveStack')
|
||||
assert(stack, 'expected directive stack')
|
||||
stack[stack.length - 1].content = data
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitContainerFence() {
|
||||
const stack = this.getData('directiveStack')
|
||||
assert(stack, 'expected directive stack')
|
||||
const directive = stack[stack.length - 1]
|
||||
if (!directive._fenceCount) directive._fenceCount = 0
|
||||
directive._fenceCount++
|
||||
if (directive._fenceCount === 1) this.setData('slurpOneLineEnding', true)
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exit() {
|
||||
const stack = this.getData('directiveStack')
|
||||
assert(stack, 'expected directive stack')
|
||||
const directive = stack.pop()
|
||||
assert(directive, 'expected directive')
|
||||
/** @type {boolean | undefined} */
|
||||
let found
|
||||
/** @type {boolean | undefined} */
|
||||
let result
|
||||
|
||||
assert(directive.name, 'expected `name`')
|
||||
|
||||
if (own.call(options_, directive.name)) {
|
||||
result = options_[directive.name].call(this, directive)
|
||||
found = result !== false
|
||||
}
|
||||
|
||||
if (!found && own.call(options_, '*')) {
|
||||
result = options_['*'].call(this, directive)
|
||||
found = result !== false
|
||||
}
|
||||
|
||||
if (!found && directive.type !== 'textDirective') {
|
||||
this.setData('slurpOneLineEnding', true)
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Create an extension for `micromark` to enable directive syntax.
|
||||
*
|
||||
* @returns {Extension}
|
||||
* Extension for `micromark` that can be passed in `extensions`, to
|
||||
* enable directive syntax.
|
||||
*/
|
||||
export function directive(): Extension;
|
||||
import type { Extension } from 'micromark-util-types';
|
||||
//# sourceMappingURL=syntax.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"syntax.d.ts","sourceRoot":"","sources":["syntax.js"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,6BAJa,SAAS,CASrB;+BApB2B,sBAAsB"}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @import {Extension} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import {codes} from 'micromark-util-symbol'
|
||||
import {directiveContainer} from './directive-container.js'
|
||||
import {directiveLeaf} from './directive-leaf.js'
|
||||
import {directiveText} from './directive-text.js'
|
||||
|
||||
/**
|
||||
* Create an extension for `micromark` to enable directive syntax.
|
||||
*
|
||||
* @returns {Extension}
|
||||
* Extension for `micromark` that can be passed in `extensions`, to
|
||||
* enable directive syntax.
|
||||
*/
|
||||
export function directive() {
|
||||
return {
|
||||
text: {[codes.colon]: directiveText},
|
||||
flow: {[codes.colon]: [directiveContainer, directiveLeaf]}
|
||||
}
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
import type {CompileContext} from 'micromark-util-types'
|
||||
|
||||
export {directive} from './lib/syntax.js'
|
||||
export {directiveHtml} from './lib/html.js'
|
||||
|
||||
/**
|
||||
* Internal tuple representing an attribute.
|
||||
*/
|
||||
type AttributeTuple = [key: string, value: string]
|
||||
|
||||
/**
|
||||
* Directive attribute.
|
||||
*/
|
||||
interface Attributes {
|
||||
/**
|
||||
* Key to value.
|
||||
*/
|
||||
[key: string]: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure representing a directive.
|
||||
*/
|
||||
export interface Directive {
|
||||
/**
|
||||
* Private :)
|
||||
*/
|
||||
_fenceCount?: number | undefined
|
||||
/**
|
||||
* Object w/ HTML attributes.
|
||||
*/
|
||||
attributes?: Attributes | undefined
|
||||
/**
|
||||
* Compiled HTML content inside container directive.
|
||||
*/
|
||||
content?: string | undefined
|
||||
/**
|
||||
* Compiled HTML content that was in `[brackets]`.
|
||||
*/
|
||||
label?: string | undefined
|
||||
/**
|
||||
* Name of directive.
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* Kind.
|
||||
*/
|
||||
type: 'containerDirective' | 'leafDirective' | 'textDirective'
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a directive.
|
||||
*
|
||||
* @param this
|
||||
* Current context.
|
||||
* @param directive
|
||||
* Directive.
|
||||
* @returns
|
||||
* Signal whether the directive was handled.
|
||||
*
|
||||
* Yield `false` to let the fallback (a special handle for `'*'`) handle it.
|
||||
*/
|
||||
export type Handle = (
|
||||
this: CompileContext,
|
||||
directive: Directive
|
||||
) => boolean | undefined
|
||||
|
||||
/**
|
||||
* Configuration.
|
||||
*
|
||||
* > 👉 **Note**: the special field `'*'` can be used to specify a fallback
|
||||
* > handle to handle all otherwise unhandled directives.
|
||||
*/
|
||||
export interface HtmlOptions {
|
||||
[name: string]: Handle
|
||||
}
|
||||
|
||||
/**
|
||||
* Augment types.
|
||||
*/
|
||||
declare module 'micromark-util-types' {
|
||||
/**
|
||||
* Compile data.
|
||||
*/
|
||||
interface CompileData {
|
||||
directiveAttributes?: Array<AttributeTuple>
|
||||
directiveStack?: Array<Directive>
|
||||
}
|
||||
|
||||
/**
|
||||
* Token types.
|
||||
*/
|
||||
interface TokenTypeMap {
|
||||
directiveContainer: 'directiveContainer'
|
||||
directiveContainerAttributes: 'directiveContainerAttributes'
|
||||
directiveContainerAttributesMarker: 'directiveContainerAttributesMarker'
|
||||
directiveContainerAttribute: 'directiveContainerAttribute'
|
||||
directiveContainerAttributeId: 'directiveContainerAttributeId'
|
||||
directiveContainerAttributeIdValue: 'directiveContainerAttributeIdValue'
|
||||
directiveContainerAttributeClass: 'directiveContainerAttributeClass'
|
||||
directiveContainerAttributeClassValue: 'directiveContainerAttributeClassValue'
|
||||
directiveContainerAttributeName: 'directiveContainerAttributeName'
|
||||
directiveContainerAttributeInitializerMarker: 'directiveContainerAttributeInitializerMarker'
|
||||
directiveContainerAttributeValueLiteral: 'directiveContainerAttributeValueLiteral'
|
||||
directiveContainerAttributeValue: 'directiveContainerAttributeValue'
|
||||
directiveContainerAttributeValueMarker: 'directiveContainerAttributeValueMarker'
|
||||
directiveContainerAttributeValueData: 'directiveContainerAttributeValueData'
|
||||
directiveContainerContent: 'directiveContainerContent'
|
||||
directiveContainerFence: 'directiveContainerFence'
|
||||
directiveContainerLabel: 'directiveContainerLabel'
|
||||
directiveContainerLabelMarker: 'directiveContainerLabelMarker'
|
||||
directiveContainerLabelString: 'directiveContainerLabelString'
|
||||
directiveContainerName: 'directiveContainerName'
|
||||
directiveContainerSequence: 'directiveContainerSequence'
|
||||
|
||||
directiveLeaf: 'directiveLeaf'
|
||||
directiveLeafAttributes: 'directiveLeafAttributes'
|
||||
directiveLeafAttributesMarker: 'directiveLeafAttributesMarker'
|
||||
directiveLeafAttribute: 'directiveLeafAttribute'
|
||||
directiveLeafAttributeId: 'directiveLeafAttributeId'
|
||||
directiveLeafAttributeIdValue: 'directiveLeafAttributeIdValue'
|
||||
directiveLeafAttributeClass: 'directiveLeafAttributeClass'
|
||||
directiveLeafAttributeClassValue: 'directiveLeafAttributeClassValue'
|
||||
directiveLeafAttributeName: 'directiveLeafAttributeName'
|
||||
directiveLeafAttributeInitializerMarker: 'directiveLeafAttributeInitializerMarker'
|
||||
directiveLeafAttributeValueLiteral: 'directiveLeafAttributeValueLiteral'
|
||||
directiveLeafAttributeValue: 'directiveLeafAttributeValue'
|
||||
directiveLeafAttributeValueMarker: 'directiveLeafAttributeValueMarker'
|
||||
directiveLeafAttributeValueData: 'directiveLeafAttributeValueData'
|
||||
directiveLeafLabel: 'directiveLeafLabel'
|
||||
directiveLeafLabelMarker: 'directiveLeafLabelMarker'
|
||||
directiveLeafLabelString: 'directiveLeafLabelString'
|
||||
directiveLeafName: 'directiveLeafName'
|
||||
directiveLeafSequence: 'directiveLeafSequence'
|
||||
|
||||
directiveText: 'directiveText'
|
||||
directiveTextAttributes: 'directiveTextAttributes'
|
||||
directiveTextAttributesMarker: 'directiveTextAttributesMarker'
|
||||
directiveTextAttribute: 'directiveTextAttribute'
|
||||
directiveTextAttributeId: 'directiveTextAttributeId'
|
||||
directiveTextAttributeIdValue: 'directiveTextAttributeIdValue'
|
||||
directiveTextAttributeClass: 'directiveTextAttributeClass'
|
||||
directiveTextAttributeClassValue: 'directiveTextAttributeClassValue'
|
||||
directiveTextAttributeName: 'directiveTextAttributeName'
|
||||
directiveTextAttributeInitializerMarker: 'directiveTextAttributeInitializerMarker'
|
||||
directiveTextAttributeValueLiteral: 'directiveTextAttributeValueLiteral'
|
||||
directiveTextAttributeValue: 'directiveTextAttributeValue'
|
||||
directiveTextAttributeValueMarker: 'directiveTextAttributeValueMarker'
|
||||
directiveTextAttributeValueData: 'directiveTextAttributeValueData'
|
||||
directiveTextLabel: 'directiveTextLabel'
|
||||
directiveTextLabelMarker: 'directiveTextLabelMarker'
|
||||
directiveTextLabelString: 'directiveTextLabelString'
|
||||
directiveTextMarker: 'directiveTextMarker'
|
||||
directiveTextName: 'directiveTextName'
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
// Note: more types exported from `index.d.ts`.
|
||||
export { directive } from './lib/syntax.js';
|
||||
export { directiveHtml } from './lib/html.js';
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
/** @type {Construct} */
|
||||
export const directiveContainer: Construct;
|
||||
import type { Construct } from 'micromark-util-types';
|
||||
//# sourceMappingURL=directive-container.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"directive-container.d.ts","sourceRoot":"","sources":["directive-container.js"],"names":[],"mappings":"AAYA,wBAAwB;AACxB,iCADW,SAAS,CAInB;+BAfqE,sBAAsB"}
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* @import {Construct, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import { factorySpace } from 'micromark-factory-space';
|
||||
import { markdownLineEnding } from 'micromark-util-character';
|
||||
import { factoryAttributes } from './factory-attributes.js';
|
||||
import { factoryLabel } from './factory-label.js';
|
||||
import { factoryName } from './factory-name.js';
|
||||
|
||||
/** @type {Construct} */
|
||||
export const directiveContainer = {
|
||||
tokenize: tokenizeDirectiveContainer,
|
||||
concrete: true
|
||||
};
|
||||
const label = {
|
||||
tokenize: tokenizeLabel,
|
||||
partial: true
|
||||
};
|
||||
const attributes = {
|
||||
tokenize: tokenizeAttributes,
|
||||
partial: true
|
||||
};
|
||||
const nonLazyLine = {
|
||||
tokenize: tokenizeNonLazyLine,
|
||||
partial: true
|
||||
};
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeDirectiveContainer(effects, ok, nok) {
|
||||
const self = this;
|
||||
const tail = self.events[self.events.length - 1];
|
||||
const initialSize = tail && tail[1].type === "linePrefix" ? tail[2].sliceSerialize(tail[1], true).length : 0;
|
||||
let sizeOpen = 0;
|
||||
/** @type {Token} */
|
||||
let previous;
|
||||
return start;
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
effects.enter('directiveContainer');
|
||||
effects.enter('directiveContainerFence');
|
||||
effects.enter('directiveContainerSequence');
|
||||
return sequenceOpen(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function sequenceOpen(code) {
|
||||
if (code === 58) {
|
||||
effects.consume(code);
|
||||
sizeOpen++;
|
||||
return sequenceOpen;
|
||||
}
|
||||
if (sizeOpen < 3) {
|
||||
return nok(code);
|
||||
}
|
||||
effects.exit('directiveContainerSequence');
|
||||
return factoryName.call(self, effects, afterName, nok, 'directiveContainerName')(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterName(code) {
|
||||
return code === 91 ? effects.attempt(label, afterLabel, afterLabel)(code) : afterLabel(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterLabel(code) {
|
||||
return code === 123 ? effects.attempt(attributes, afterAttributes, afterAttributes)(code) : afterAttributes(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterAttributes(code) {
|
||||
return factorySpace(effects, openAfter, "whitespace")(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function openAfter(code) {
|
||||
effects.exit('directiveContainerFence');
|
||||
if (code === null) {
|
||||
return after(code);
|
||||
}
|
||||
if (markdownLineEnding(code)) {
|
||||
if (self.interrupt) {
|
||||
return ok(code);
|
||||
}
|
||||
return effects.attempt(nonLazyLine, contentStart, after)(code);
|
||||
}
|
||||
return nok(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function contentStart(code) {
|
||||
if (code === null) {
|
||||
return after(code);
|
||||
}
|
||||
if (markdownLineEnding(code)) {
|
||||
return effects.check(nonLazyLine, emptyContentNonLazyLineAfter, after)(code);
|
||||
}
|
||||
effects.enter('directiveContainerContent');
|
||||
return lineStart(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function lineStart(code) {
|
||||
return effects.attempt({
|
||||
tokenize: tokenizeClosingFence,
|
||||
partial: true
|
||||
}, afterContent, initialSize ? factorySpace(effects, chunkStart, "linePrefix", initialSize + 1) : chunkStart)(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function chunkStart(code) {
|
||||
if (code === null) {
|
||||
return afterContent(code);
|
||||
}
|
||||
if (markdownLineEnding(code)) {
|
||||
return effects.check(nonLazyLine, chunkNonLazyStart, afterContent)(code);
|
||||
}
|
||||
return chunkNonLazyStart(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function contentContinue(code) {
|
||||
if (code === null) {
|
||||
const t = effects.exit("chunkDocument");
|
||||
self.parser.lazy[t.start.line] = false;
|
||||
return afterContent(code);
|
||||
}
|
||||
if (markdownLineEnding(code)) {
|
||||
return effects.check(nonLazyLine, nonLazyLineAfter, lineAfter)(code);
|
||||
}
|
||||
effects.consume(code);
|
||||
return contentContinue;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function chunkNonLazyStart(code) {
|
||||
const token = effects.enter("chunkDocument", {
|
||||
contentType: "document",
|
||||
previous
|
||||
});
|
||||
if (previous) previous.next = token;
|
||||
previous = token;
|
||||
return contentContinue(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function emptyContentNonLazyLineAfter(code) {
|
||||
effects.enter('directiveContainerContent');
|
||||
return lineStart(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function nonLazyLineAfter(code) {
|
||||
effects.consume(code);
|
||||
const t = effects.exit("chunkDocument");
|
||||
self.parser.lazy[t.start.line] = false;
|
||||
return lineStart;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function lineAfter(code) {
|
||||
const t = effects.exit("chunkDocument");
|
||||
self.parser.lazy[t.start.line] = false;
|
||||
return afterContent(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterContent(code) {
|
||||
effects.exit('directiveContainerContent');
|
||||
return after(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function after(code) {
|
||||
effects.exit('directiveContainer');
|
||||
return ok(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeClosingFence(effects, ok, nok) {
|
||||
let size = 0;
|
||||
return factorySpace(effects, closingPrefixAfter, "linePrefix", self.parser.constructs.disable.null.includes('codeIndented') ? undefined : 4);
|
||||
|
||||
/** @type {State} */
|
||||
function closingPrefixAfter(code) {
|
||||
effects.enter('directiveContainerFence');
|
||||
effects.enter('directiveContainerSequence');
|
||||
return closingSequence(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function closingSequence(code) {
|
||||
if (code === 58) {
|
||||
effects.consume(code);
|
||||
size++;
|
||||
return closingSequence;
|
||||
}
|
||||
if (size < sizeOpen) return nok(code);
|
||||
effects.exit('directiveContainerSequence');
|
||||
return factorySpace(effects, closingSequenceEnd, "whitespace")(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function closingSequenceEnd(code) {
|
||||
if (code === null || markdownLineEnding(code)) {
|
||||
effects.exit('directiveContainerFence');
|
||||
return ok(code);
|
||||
}
|
||||
return nok(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeLabel(effects, ok, nok) {
|
||||
// Always a `[`
|
||||
return factoryLabel(effects, ok, nok, 'directiveContainerLabel', 'directiveContainerLabelMarker', 'directiveContainerLabelString', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeAttributes(effects, ok, nok) {
|
||||
// Always a `{`
|
||||
return factoryAttributes(effects, ok, nok, 'directiveContainerAttributes', 'directiveContainerAttributesMarker', 'directiveContainerAttribute', 'directiveContainerAttributeId', 'directiveContainerAttributeClass', 'directiveContainerAttributeName', 'directiveContainerAttributeInitializerMarker', 'directiveContainerAttributeValueLiteral', 'directiveContainerAttributeValue', 'directiveContainerAttributeValueMarker', 'directiveContainerAttributeValueData', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeNonLazyLine(effects, ok, nok) {
|
||||
const self = this;
|
||||
return start;
|
||||
|
||||
/** @type {State} */
|
||||
function start(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);
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
/** @type {Construct} */
|
||||
export const directiveLeaf: Construct;
|
||||
import type { Construct } from 'micromark-util-types';
|
||||
//# sourceMappingURL=directive-leaf.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"directive-leaf.d.ts","sourceRoot":"","sources":["directive-leaf.js"],"names":[],"mappings":"AAYA,wBAAwB;AACxB,4BADW,SAAS,CAC0C;+BAZC,sBAAsB"}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @import {Construct, State, TokenizeContext, Tokenizer} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import { factorySpace } from 'micromark-factory-space';
|
||||
import { markdownLineEnding } from 'micromark-util-character';
|
||||
import { factoryAttributes } from './factory-attributes.js';
|
||||
import { factoryLabel } from './factory-label.js';
|
||||
import { factoryName } from './factory-name.js';
|
||||
|
||||
/** @type {Construct} */
|
||||
export const directiveLeaf = {
|
||||
tokenize: tokenizeDirectiveLeaf
|
||||
};
|
||||
const label = {
|
||||
tokenize: tokenizeLabel,
|
||||
partial: true
|
||||
};
|
||||
const attributes = {
|
||||
tokenize: tokenizeAttributes,
|
||||
partial: true
|
||||
};
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeDirectiveLeaf(effects, ok, nok) {
|
||||
const self = this;
|
||||
return start;
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
effects.enter('directiveLeaf');
|
||||
effects.enter('directiveLeafSequence');
|
||||
effects.consume(code);
|
||||
return inStart;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function inStart(code) {
|
||||
if (code === 58) {
|
||||
effects.consume(code);
|
||||
effects.exit('directiveLeafSequence');
|
||||
return factoryName.call(self, effects, afterName, nok, 'directiveLeafName');
|
||||
}
|
||||
return nok(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterName(code) {
|
||||
return code === 91 ? effects.attempt(label, afterLabel, afterLabel)(code) : afterLabel(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterLabel(code) {
|
||||
return code === 123 ? effects.attempt(attributes, afterAttributes, afterAttributes)(code) : afterAttributes(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterAttributes(code) {
|
||||
return factorySpace(effects, end, "whitespace")(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function end(code) {
|
||||
if (code === null || markdownLineEnding(code)) {
|
||||
effects.exit('directiveLeaf');
|
||||
return ok(code);
|
||||
}
|
||||
return nok(code);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeLabel(effects, ok, nok) {
|
||||
// Always a `[`
|
||||
return factoryLabel(effects, ok, nok, 'directiveLeafLabel', 'directiveLeafLabelMarker', 'directiveLeafLabelString', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeAttributes(effects, ok, nok) {
|
||||
// Always a `{`
|
||||
return factoryAttributes(effects, ok, nok, 'directiveLeafAttributes', 'directiveLeafAttributesMarker', 'directiveLeafAttribute', 'directiveLeafAttributeId', 'directiveLeafAttributeClass', 'directiveLeafAttributeName', 'directiveLeafAttributeInitializerMarker', 'directiveLeafAttributeValueLiteral', 'directiveLeafAttributeValue', 'directiveLeafAttributeValueMarker', 'directiveLeafAttributeValueData', true);
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
/** @type {Construct} */
|
||||
export const directiveText: Construct;
|
||||
import type { Construct } from 'micromark-util-types';
|
||||
//# sourceMappingURL=directive-text.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"directive-text.d.ts","sourceRoot":"","sources":["directive-text.js"],"names":[],"mappings":"AAUA,wBAAwB;AACxB,4BADW,SAAS,CAInB;+BAbwE,sBAAsB"}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* @import {Construct, Previous, State, TokenizeContext, Tokenizer} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import { factoryAttributes } from './factory-attributes.js';
|
||||
import { factoryLabel } from './factory-label.js';
|
||||
import { factoryName } from './factory-name.js';
|
||||
|
||||
/** @type {Construct} */
|
||||
export const directiveText = {
|
||||
tokenize: tokenizeDirectiveText,
|
||||
previous
|
||||
};
|
||||
const label = {
|
||||
tokenize: tokenizeLabel,
|
||||
partial: true
|
||||
};
|
||||
const attributes = {
|
||||
tokenize: tokenizeAttributes,
|
||||
partial: true
|
||||
};
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Previous}
|
||||
*/
|
||||
function previous(code) {
|
||||
// If there is a previous code, there will always be a tail.
|
||||
return code !== 58 || this.events[this.events.length - 1][1].type === "characterEscape";
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeDirectiveText(effects, ok, nok) {
|
||||
const self = this;
|
||||
return start;
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
effects.enter('directiveText');
|
||||
effects.enter('directiveTextMarker');
|
||||
effects.consume(code);
|
||||
effects.exit('directiveTextMarker');
|
||||
return factoryName.call(self, effects, afterName, nok, 'directiveTextName');
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterName(code) {
|
||||
return code === 58 ? nok(code) : code === 91 ? effects.attempt(label, afterLabel, afterLabel)(code) : afterLabel(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterLabel(code) {
|
||||
return code === 123 ? effects.attempt(attributes, afterAttributes, afterAttributes)(code) : afterAttributes(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterAttributes(code) {
|
||||
effects.exit('directiveText');
|
||||
return ok(code);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeLabel(effects, ok, nok) {
|
||||
// Always a `[`
|
||||
return factoryLabel(effects, ok, nok, 'directiveTextLabel', 'directiveTextLabelMarker', 'directiveTextLabelString');
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @type {Tokenizer}
|
||||
*/
|
||||
function tokenizeAttributes(effects, ok, nok) {
|
||||
// Always a `{`
|
||||
return factoryAttributes(effects, ok, nok, 'directiveTextAttributes', 'directiveTextAttributesMarker', 'directiveTextAttribute', 'directiveTextAttributeId', 'directiveTextAttributeClass', 'directiveTextAttributeName', 'directiveTextAttributeInitializerMarker', 'directiveTextAttributeValueLiteral', 'directiveTextAttributeValue', 'directiveTextAttributeValueMarker', 'directiveTextAttributeValueData');
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} attributesType
|
||||
* @param {TokenType} attributesMarkerType
|
||||
* @param {TokenType} attributeType
|
||||
* @param {TokenType} attributeIdType
|
||||
* @param {TokenType} attributeClassType
|
||||
* @param {TokenType} attributeNameType
|
||||
* @param {TokenType} attributeInitializerType
|
||||
* @param {TokenType} attributeValueLiteralType
|
||||
* @param {TokenType} attributeValueType
|
||||
* @param {TokenType} attributeValueMarker
|
||||
* @param {TokenType} attributeValueData
|
||||
* @param {boolean | undefined} [disallowEol=false]
|
||||
*/
|
||||
export function factoryAttributes(effects: Effects, ok: State, nok: State, attributesType: TokenType, attributesMarkerType: TokenType, attributeType: TokenType, attributeIdType: TokenType, attributeClassType: TokenType, attributeNameType: TokenType, attributeInitializerType: TokenType, attributeValueLiteralType: TokenType, attributeValueType: TokenType, attributeValueMarker: TokenType, attributeValueData: TokenType, disallowEol?: boolean | undefined): (code: Code) => State | undefined;
|
||||
import type { Effects } from 'micromark-util-types';
|
||||
import type { State } from 'micromark-util-types';
|
||||
import type { TokenType } from 'micromark-util-types';
|
||||
import type { Code } from 'micromark-util-types';
|
||||
//# sourceMappingURL=factory-attributes.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"factory-attributes.d.ts","sourceRoot":"","sources":["factory-attributes.js"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;GAgBG;AACH,2CAhBW,OAAO,MACP,KAAK,OACL,KAAK,kBACL,SAAS,wBACT,SAAS,iBACT,SAAS,mBACT,SAAS,sBACT,SAAS,qBACT,SAAS,4BACT,SAAS,6BACT,SAAS,sBACT,SAAS,wBACT,SAAS,sBACT,SAAS,gBACT,OAAO,GAAG,SAAS,qCA4T7B;6BA1ViD,sBAAsB;2BAAtB,sBAAsB;+BAAtB,sBAAsB;0BAAtB,sBAAsB"}
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* @import {Code, Effects, State, TokenType} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import { factorySpace } from 'micromark-factory-space';
|
||||
import { factoryWhitespace } from 'micromark-factory-whitespace';
|
||||
import { markdownLineEnding, markdownLineEndingOrSpace, markdownSpace, unicodePunctuation, unicodeWhitespace } from 'micromark-util-character';
|
||||
/**
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} attributesType
|
||||
* @param {TokenType} attributesMarkerType
|
||||
* @param {TokenType} attributeType
|
||||
* @param {TokenType} attributeIdType
|
||||
* @param {TokenType} attributeClassType
|
||||
* @param {TokenType} attributeNameType
|
||||
* @param {TokenType} attributeInitializerType
|
||||
* @param {TokenType} attributeValueLiteralType
|
||||
* @param {TokenType} attributeValueType
|
||||
* @param {TokenType} attributeValueMarker
|
||||
* @param {TokenType} attributeValueData
|
||||
* @param {boolean | undefined} [disallowEol=false]
|
||||
*/
|
||||
export function factoryAttributes(effects, ok, nok, attributesType, attributesMarkerType, attributeType, attributeIdType, attributeClassType, attributeNameType, attributeInitializerType, attributeValueLiteralType, attributeValueType, attributeValueMarker, attributeValueData, disallowEol) {
|
||||
/** @type {TokenType} */
|
||||
let type;
|
||||
/** @type {Code | undefined} */
|
||||
let marker;
|
||||
return start;
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
effects.enter(attributesType);
|
||||
effects.enter(attributesMarkerType);
|
||||
effects.consume(code);
|
||||
effects.exit(attributesMarkerType);
|
||||
return between;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function between(code) {
|
||||
if (code === 35) {
|
||||
type = attributeIdType;
|
||||
return shortcutStart(code);
|
||||
}
|
||||
if (code === 46) {
|
||||
type = attributeClassType;
|
||||
return shortcutStart(code);
|
||||
}
|
||||
if (disallowEol && markdownSpace(code)) {
|
||||
return factorySpace(effects, between, "whitespace")(code);
|
||||
}
|
||||
if (!disallowEol && markdownLineEndingOrSpace(code)) {
|
||||
return factoryWhitespace(effects, between)(code);
|
||||
}
|
||||
if (code === null || markdownLineEnding(code) || unicodeWhitespace(code) || unicodePunctuation(code) && code !== 45 && code !== 95) {
|
||||
return end(code);
|
||||
}
|
||||
effects.enter(attributeType);
|
||||
effects.enter(attributeNameType);
|
||||
effects.consume(code);
|
||||
return name;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function shortcutStart(code) {
|
||||
// Assume it’s registered.
|
||||
const markerType = /** @type {TokenType} */type + 'Marker';
|
||||
effects.enter(attributeType);
|
||||
effects.enter(type);
|
||||
effects.enter(markerType);
|
||||
effects.consume(code);
|
||||
effects.exit(markerType);
|
||||
return shortcutStartAfter;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function shortcutStartAfter(code) {
|
||||
if (code === null || code === 34 || code === 35 || code === 39 || code === 46 || code === 60 || code === 61 || code === 62 || code === 96 || code === 125 || markdownLineEndingOrSpace(code)) {
|
||||
return nok(code);
|
||||
}
|
||||
|
||||
// Assume it’s registered.
|
||||
const valueType = /** @type {TokenType} */type + 'Value';
|
||||
effects.enter(valueType);
|
||||
effects.consume(code);
|
||||
return shortcut;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function shortcut(code) {
|
||||
if (code === null || code === 34 || code === 39 || code === 60 || code === 61 || code === 62 || code === 96) {
|
||||
return nok(code);
|
||||
}
|
||||
if (code === 35 || code === 46 || code === 125 || markdownLineEndingOrSpace(code)) {
|
||||
// Assume it’s registered.
|
||||
const valueType = /** @type {TokenType} */type + 'Value';
|
||||
effects.exit(valueType);
|
||||
effects.exit(type);
|
||||
effects.exit(attributeType);
|
||||
return between(code);
|
||||
}
|
||||
effects.consume(code);
|
||||
return shortcut;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function name(code) {
|
||||
if (code === null || markdownLineEnding(code) || unicodeWhitespace(code) || unicodePunctuation(code) && code !== 45 && code !== 46 && code !== 58 && code !== 95) {
|
||||
effects.exit(attributeNameType);
|
||||
if (disallowEol && markdownSpace(code)) {
|
||||
return factorySpace(effects, nameAfter, "whitespace")(code);
|
||||
}
|
||||
if (!disallowEol && markdownLineEndingOrSpace(code)) {
|
||||
return factoryWhitespace(effects, nameAfter)(code);
|
||||
}
|
||||
return nameAfter(code);
|
||||
}
|
||||
effects.consume(code);
|
||||
return name;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function nameAfter(code) {
|
||||
if (code === 61) {
|
||||
effects.enter(attributeInitializerType);
|
||||
effects.consume(code);
|
||||
effects.exit(attributeInitializerType);
|
||||
return valueBefore;
|
||||
}
|
||||
|
||||
// Attribute w/o value.
|
||||
effects.exit(attributeType);
|
||||
return between(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueBefore(code) {
|
||||
if (code === null || code === 60 || code === 61 || code === 62 || code === 96 || code === 125 || disallowEol && markdownLineEnding(code)) {
|
||||
return nok(code);
|
||||
}
|
||||
if (code === 34 || code === 39) {
|
||||
effects.enter(attributeValueLiteralType);
|
||||
effects.enter(attributeValueMarker);
|
||||
effects.consume(code);
|
||||
effects.exit(attributeValueMarker);
|
||||
marker = code;
|
||||
return valueQuotedStart;
|
||||
}
|
||||
if (disallowEol && markdownSpace(code)) {
|
||||
return factorySpace(effects, valueBefore, "whitespace")(code);
|
||||
}
|
||||
if (!disallowEol && markdownLineEndingOrSpace(code)) {
|
||||
return factoryWhitespace(effects, valueBefore)(code);
|
||||
}
|
||||
effects.enter(attributeValueType);
|
||||
effects.enter(attributeValueData);
|
||||
effects.consume(code);
|
||||
marker = undefined;
|
||||
return valueUnquoted;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueUnquoted(code) {
|
||||
if (code === null || code === 34 || code === 39 || code === 60 || code === 61 || code === 62 || code === 96) {
|
||||
return nok(code);
|
||||
}
|
||||
if (code === 125 || markdownLineEndingOrSpace(code)) {
|
||||
effects.exit(attributeValueData);
|
||||
effects.exit(attributeValueType);
|
||||
effects.exit(attributeType);
|
||||
return between(code);
|
||||
}
|
||||
effects.consume(code);
|
||||
return valueUnquoted;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueQuotedStart(code) {
|
||||
if (code === marker) {
|
||||
effects.enter(attributeValueMarker);
|
||||
effects.consume(code);
|
||||
effects.exit(attributeValueMarker);
|
||||
effects.exit(attributeValueLiteralType);
|
||||
effects.exit(attributeType);
|
||||
return valueQuotedAfter;
|
||||
}
|
||||
effects.enter(attributeValueType);
|
||||
return valueQuotedBetween(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueQuotedBetween(code) {
|
||||
if (code === marker) {
|
||||
effects.exit(attributeValueType);
|
||||
return valueQuotedStart(code);
|
||||
}
|
||||
if (code === null) {
|
||||
return nok(code);
|
||||
}
|
||||
|
||||
// Note: blank lines can’t exist in content.
|
||||
if (markdownLineEnding(code)) {
|
||||
return disallowEol ? nok(code) : factoryWhitespace(effects, valueQuotedBetween)(code);
|
||||
}
|
||||
effects.enter(attributeValueData);
|
||||
effects.consume(code);
|
||||
return valueQuoted;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueQuoted(code) {
|
||||
if (code === marker || code === null || markdownLineEnding(code)) {
|
||||
effects.exit(attributeValueData);
|
||||
return valueQuotedBetween(code);
|
||||
}
|
||||
effects.consume(code);
|
||||
return valueQuoted;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function valueQuotedAfter(code) {
|
||||
return code === 125 || markdownLineEndingOrSpace(code) ? between(code) : end(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function end(code) {
|
||||
if (code === 125) {
|
||||
effects.enter(attributesMarkerType);
|
||||
effects.consume(code);
|
||||
effects.exit(attributesMarkerType);
|
||||
effects.exit(attributesType);
|
||||
return ok;
|
||||
}
|
||||
return nok(code);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} type
|
||||
* @param {TokenType} markerType
|
||||
* @param {TokenType} stringType
|
||||
* @param {boolean | undefined} [disallowEol=false]
|
||||
*/
|
||||
export function factoryLabel(effects: Effects, ok: State, nok: State, type: TokenType, markerType: TokenType, stringType: TokenType, disallowEol?: boolean | undefined): (code: Code) => State | undefined;
|
||||
import type { Effects } from 'micromark-util-types';
|
||||
import type { State } from 'micromark-util-types';
|
||||
import type { TokenType } from 'micromark-util-types';
|
||||
import type { Code } from 'micromark-util-types';
|
||||
//# sourceMappingURL=factory-label.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"factory-label.d.ts","sourceRoot":"","sources":["factory-label.js"],"names":[],"mappings":"AAaA;;;;;;;;GAQG;AACH,sCARW,OAAO,MACP,KAAK,OACL,KAAK,QACL,SAAS,cACT,SAAS,cACT,SAAS,gBACT,OAAO,GAAG,SAAS,qCAkH7B;6BArIwD,sBAAsB;2BAAtB,sBAAsB;+BAAtB,sBAAsB;0BAAtB,sBAAsB"}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @import {Code, Effects, State, Token, TokenType} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import { markdownLineEnding } from 'micromark-util-character';
|
||||
// This is a fork of:
|
||||
// <https://github.com/micromark/micromark/tree/main/packages/micromark-factory-label>
|
||||
// to allow empty labels, balanced brackets (such as for nested directives),
|
||||
// text instead of strings, and optionally disallows EOLs.
|
||||
|
||||
/**
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} type
|
||||
* @param {TokenType} markerType
|
||||
* @param {TokenType} stringType
|
||||
* @param {boolean | undefined} [disallowEol=false]
|
||||
*/
|
||||
export function factoryLabel(effects, ok, nok, type, markerType, stringType, disallowEol) {
|
||||
let size = 0;
|
||||
let balance = 0;
|
||||
/** @type {Token | undefined} */
|
||||
let previous;
|
||||
return start;
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
effects.enter(type);
|
||||
effects.enter(markerType);
|
||||
effects.consume(code);
|
||||
effects.exit(markerType);
|
||||
return afterStart;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function afterStart(code) {
|
||||
if (code === 93) {
|
||||
effects.enter(markerType);
|
||||
effects.consume(code);
|
||||
effects.exit(markerType);
|
||||
effects.exit(type);
|
||||
return ok;
|
||||
}
|
||||
effects.enter(stringType);
|
||||
return lineStart(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function lineStart(code) {
|
||||
if (code === 93 && !balance) {
|
||||
return atClosingBrace(code);
|
||||
}
|
||||
const token = effects.enter("chunkText", {
|
||||
_contentTypeTextTrailing: true,
|
||||
contentType: "text",
|
||||
previous
|
||||
});
|
||||
if (previous) previous.next = token;
|
||||
previous = token;
|
||||
return data(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function data(code) {
|
||||
if (code === null || size > 999) {
|
||||
return nok(code);
|
||||
}
|
||||
if (code === 91 && ++balance > 32) {
|
||||
return nok(code);
|
||||
}
|
||||
if (code === 93 && !balance--) {
|
||||
effects.exit("chunkText");
|
||||
return atClosingBrace(code);
|
||||
}
|
||||
if (markdownLineEnding(code)) {
|
||||
if (disallowEol) {
|
||||
return nok(code);
|
||||
}
|
||||
effects.consume(code);
|
||||
effects.exit("chunkText");
|
||||
return lineStart;
|
||||
}
|
||||
effects.consume(code);
|
||||
return code === 92 ? dataEscape : data;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function dataEscape(code) {
|
||||
if (code === 91 || code === 92 || code === 93) {
|
||||
effects.consume(code);
|
||||
size++;
|
||||
return data;
|
||||
}
|
||||
return data(code);
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function atClosingBrace(code) {
|
||||
effects.exit(stringType);
|
||||
effects.enter(markerType);
|
||||
effects.consume(code);
|
||||
effects.exit(markerType);
|
||||
effects.exit(type);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} type
|
||||
*/
|
||||
export function factoryName(this: TokenizeContext, effects: Effects, ok: State, nok: State, type: TokenType): (code: Code) => State | undefined;
|
||||
import type { Effects } from 'micromark-util-types';
|
||||
import type { State } from 'micromark-util-types';
|
||||
import type { TokenType } from 'micromark-util-types';
|
||||
import type { TokenizeContext } from 'micromark-util-types';
|
||||
import type { Code } from 'micromark-util-types';
|
||||
//# sourceMappingURL=factory-name.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"factory-name.d.ts","sourceRoot":"","sources":["factory-name.js"],"names":[],"mappings":"AAWA;;;;;;GAMG;AACH,4DALW,OAAO,MACP,KAAK,OACL,KAAK,QACL,SAAS,qCA0CnB;6BAzDkE,sBAAsB;2BAAtB,sBAAsB;+BAAtB,sBAAsB;qCAAtB,sBAAsB;0BAAtB,sBAAsB"}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @import {Code, Effects, State, TokenizeContext, TokenType} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import { markdownLineEnding, unicodePunctuation, unicodeWhitespace } from 'micromark-util-character';
|
||||
/**
|
||||
* @this {TokenizeContext}
|
||||
* @param {Effects} effects
|
||||
* @param {State} ok
|
||||
* @param {State} nok
|
||||
* @param {TokenType} type
|
||||
*/
|
||||
export function factoryName(effects, ok, nok, type) {
|
||||
const self = this;
|
||||
return start;
|
||||
|
||||
/** @type {State} */
|
||||
function start(code) {
|
||||
if (code === null || markdownLineEnding(code) || unicodePunctuation(code) || unicodeWhitespace(code)) {
|
||||
return nok(code);
|
||||
}
|
||||
effects.enter(type);
|
||||
effects.consume(code);
|
||||
return name;
|
||||
}
|
||||
|
||||
/** @type {State} */
|
||||
function name(code) {
|
||||
if (code === null || markdownLineEnding(code) || unicodeWhitespace(code) || unicodePunctuation(code) && code !== 45 && code !== 95) {
|
||||
effects.exit(type);
|
||||
return self.previous === 45 || self.previous === 95 ? nok(code) : ok(code);
|
||||
}
|
||||
effects.consume(code);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Create an extension for `micromark` to support directives when serializing
|
||||
* to HTML.
|
||||
*
|
||||
* @param {HtmlOptions | null | undefined} [options={}]
|
||||
* Configuration (default: `{}`).
|
||||
* @returns {HtmlExtension}
|
||||
* Extension for `micromark` that can be passed in `htmlExtensions`, to
|
||||
* support directives when serializing to HTML.
|
||||
*/
|
||||
export function directiveHtml(options?: HtmlOptions | null | undefined): HtmlExtension;
|
||||
import type { HtmlOptions } from 'micromark-extension-directive';
|
||||
import type { HtmlExtension } from 'micromark-util-types';
|
||||
//# sourceMappingURL=html.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["html.js"],"names":[],"mappings":"AAUA;;;;;;;;;GASG;AACH,wCANW,WAAW,GAAG,IAAI,GAAG,SAAS,GAE5B,aAAa,CAwPzB;iCAvQwC,+BAA+B;mCACG,sBAAsB"}
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* @import {Directive, HtmlOptions} from 'micromark-extension-directive'
|
||||
* @import {CompileContext, Handle as MicromarkHandle, HtmlExtension} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import { parseEntities } from 'parse-entities';
|
||||
const own = {}.hasOwnProperty;
|
||||
|
||||
/**
|
||||
* Create an extension for `micromark` to support directives when serializing
|
||||
* to HTML.
|
||||
*
|
||||
* @param {HtmlOptions | null | undefined} [options={}]
|
||||
* Configuration (default: `{}`).
|
||||
* @returns {HtmlExtension}
|
||||
* Extension for `micromark` that can be passed in `htmlExtensions`, to
|
||||
* support directives when serializing to HTML.
|
||||
*/
|
||||
export function directiveHtml(options) {
|
||||
const options_ = options || {};
|
||||
return {
|
||||
enter: {
|
||||
directiveContainer() {
|
||||
enter.call(this, 'containerDirective');
|
||||
},
|
||||
directiveContainerAttributes: enterAttributes,
|
||||
directiveContainerLabel: enterLabel,
|
||||
directiveContainerContent() {
|
||||
this.buffer();
|
||||
},
|
||||
directiveLeaf() {
|
||||
enter.call(this, 'leafDirective');
|
||||
},
|
||||
directiveLeafAttributes: enterAttributes,
|
||||
directiveLeafLabel: enterLabel,
|
||||
directiveText() {
|
||||
enter.call(this, 'textDirective');
|
||||
},
|
||||
directiveTextAttributes: enterAttributes,
|
||||
directiveTextLabel: enterLabel
|
||||
},
|
||||
exit: {
|
||||
directiveContainer: exit,
|
||||
directiveContainerAttributeClassValue: exitAttributeClassValue,
|
||||
directiveContainerAttributeIdValue: exitAttributeIdValue,
|
||||
directiveContainerAttributeName: exitAttributeName,
|
||||
directiveContainerAttributeValue: exitAttributeValue,
|
||||
directiveContainerAttributes: exitAttributes,
|
||||
directiveContainerContent: exitContainerContent,
|
||||
directiveContainerFence: exitContainerFence,
|
||||
directiveContainerLabel: exitLabel,
|
||||
directiveContainerName: exitName,
|
||||
directiveLeaf: exit,
|
||||
directiveLeafAttributeClassValue: exitAttributeClassValue,
|
||||
directiveLeafAttributeIdValue: exitAttributeIdValue,
|
||||
directiveLeafAttributeName: exitAttributeName,
|
||||
directiveLeafAttributeValue: exitAttributeValue,
|
||||
directiveLeafAttributes: exitAttributes,
|
||||
directiveLeafLabel: exitLabel,
|
||||
directiveLeafName: exitName,
|
||||
directiveText: exit,
|
||||
directiveTextAttributeClassValue: exitAttributeClassValue,
|
||||
directiveTextAttributeIdValue: exitAttributeIdValue,
|
||||
directiveTextAttributeName: exitAttributeName,
|
||||
directiveTextAttributeValue: exitAttributeValue,
|
||||
directiveTextAttributes: exitAttributes,
|
||||
directiveTextLabel: exitLabel,
|
||||
directiveTextName: exitName
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @param {Directive['type']} type
|
||||
*/
|
||||
function enter(type) {
|
||||
let stack = this.getData('directiveStack');
|
||||
if (!stack) this.setData('directiveStack', stack = []);
|
||||
stack.push({
|
||||
type,
|
||||
name: ''
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitName(token) {
|
||||
const stack = this.getData('directiveStack');
|
||||
stack[stack.length - 1].name = this.sliceSerialize(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function enterLabel() {
|
||||
this.buffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitLabel() {
|
||||
const data = this.resume();
|
||||
const stack = this.getData('directiveStack');
|
||||
stack[stack.length - 1].label = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function enterAttributes() {
|
||||
this.buffer();
|
||||
this.setData('directiveAttributes', []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitAttributeIdValue(token) {
|
||||
const attributes = this.getData('directiveAttributes');
|
||||
attributes.push(['id', parseEntities(this.sliceSerialize(token), {
|
||||
attribute: true
|
||||
})]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitAttributeClassValue(token) {
|
||||
const attributes = this.getData('directiveAttributes');
|
||||
attributes.push(['class', parseEntities(this.sliceSerialize(token), {
|
||||
attribute: true
|
||||
})]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitAttributeName(token) {
|
||||
// Attribute names in CommonMark are significantly limited, so character
|
||||
// references can’t exist.
|
||||
const attributes = this.getData('directiveAttributes');
|
||||
attributes.push([this.sliceSerialize(token), '']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitAttributeValue(token) {
|
||||
const attributes = this.getData('directiveAttributes');
|
||||
attributes[attributes.length - 1][1] = parseEntities(this.sliceSerialize(token), {
|
||||
attribute: true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitAttributes() {
|
||||
const stack = this.getData('directiveStack');
|
||||
const attributes = this.getData('directiveAttributes');
|
||||
/** @type {Record<string, string>} */
|
||||
const cleaned = {};
|
||||
let index = -1;
|
||||
while (++index < attributes.length) {
|
||||
const attribute = attributes[index];
|
||||
if (attribute[0] === 'class' && cleaned.class) {
|
||||
cleaned.class += ' ' + attribute[1];
|
||||
} else {
|
||||
cleaned[attribute[0]] = attribute[1];
|
||||
}
|
||||
}
|
||||
this.resume();
|
||||
this.setData('directiveAttributes');
|
||||
stack[stack.length - 1].attributes = cleaned;
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitContainerContent() {
|
||||
const data = this.resume();
|
||||
const stack = this.getData('directiveStack');
|
||||
stack[stack.length - 1].content = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exitContainerFence() {
|
||||
const stack = this.getData('directiveStack');
|
||||
const directive = stack[stack.length - 1];
|
||||
if (!directive._fenceCount) directive._fenceCount = 0;
|
||||
directive._fenceCount++;
|
||||
if (directive._fenceCount === 1) this.setData('slurpOneLineEnding', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {MicromarkHandle}
|
||||
*/
|
||||
function exit() {
|
||||
const stack = this.getData('directiveStack');
|
||||
const directive = stack.pop();
|
||||
/** @type {boolean | undefined} */
|
||||
let found;
|
||||
/** @type {boolean | undefined} */
|
||||
let result;
|
||||
if (own.call(options_, directive.name)) {
|
||||
result = options_[directive.name].call(this, directive);
|
||||
found = result !== false;
|
||||
}
|
||||
if (!found && own.call(options_, '*')) {
|
||||
result = options_['*'].call(this, directive);
|
||||
found = result !== false;
|
||||
}
|
||||
if (!found && directive.type !== 'textDirective') {
|
||||
this.setData('slurpOneLineEnding', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Create an extension for `micromark` to enable directive syntax.
|
||||
*
|
||||
* @returns {Extension}
|
||||
* Extension for `micromark` that can be passed in `extensions`, to
|
||||
* enable directive syntax.
|
||||
*/
|
||||
export function directive(): Extension;
|
||||
import type { Extension } from 'micromark-util-types';
|
||||
//# sourceMappingURL=syntax.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"syntax.d.ts","sourceRoot":"","sources":["syntax.js"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,6BAJa,SAAS,CASrB;+BApB2B,sBAAsB"}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @import {Extension} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import { directiveContainer } from './directive-container.js';
|
||||
import { directiveLeaf } from './directive-leaf.js';
|
||||
import { directiveText } from './directive-text.js';
|
||||
|
||||
/**
|
||||
* Create an extension for `micromark` to enable directive syntax.
|
||||
*
|
||||
* @returns {Extension}
|
||||
* Extension for `micromark` that can be passed in `extensions`, to
|
||||
* enable directive syntax.
|
||||
*/
|
||||
export function directive() {
|
||||
return {
|
||||
text: {
|
||||
[58]: directiveText
|
||||
},
|
||||
flow: {
|
||||
[58]: [directiveContainer, directiveLeaf]
|
||||
}
|
||||
};
|
||||
}
|
||||
+22
@@ -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.
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
{
|
||||
"author": "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
|
||||
"bugs": "https://github.com/micromark/micromark-extension-directive/issues",
|
||||
"contributors": [
|
||||
"Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)"
|
||||
],
|
||||
"dependencies": {
|
||||
"devlop": "^1.0.0",
|
||||
"micromark-factory-space": "^2.0.0",
|
||||
"micromark-factory-whitespace": "^2.0.0",
|
||||
"micromark-util-character": "^2.0.0",
|
||||
"micromark-util-symbol": "^2.0.0",
|
||||
"micromark-util-types": "^2.0.0",
|
||||
"parse-entities": "^4.0.0"
|
||||
},
|
||||
"description": "micromark extension to support generic directives (`:cite[smith04]`)",
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.0.0",
|
||||
"c8": "^10.0.0",
|
||||
"html-void-elements": "^3.0.0",
|
||||
"micromark": "^4.0.0",
|
||||
"micromark-build": "^2.0.0",
|
||||
"prettier": "^3.0.0",
|
||||
"remark-cli": "^12.0.0",
|
||||
"remark-preset-wooorm": "^11.0.0",
|
||||
"type-coverage": "^2.0.0",
|
||||
"typescript": "^5.0.0",
|
||||
"xo": "^0.60.0"
|
||||
},
|
||||
"exports": {
|
||||
"development": "./dev/index.js",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"files": [
|
||||
"dev/",
|
||||
"index.d.ts",
|
||||
"index.js",
|
||||
"lib/"
|
||||
],
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
},
|
||||
"keywords": [
|
||||
"container",
|
||||
"directive",
|
||||
"extension",
|
||||
"generic",
|
||||
"markdown",
|
||||
"micromark-extension",
|
||||
"micromark",
|
||||
"unified"
|
||||
],
|
||||
"license": "MIT",
|
||||
"name": "micromark-extension-directive",
|
||||
"prettier": {
|
||||
"bracketSpacing": false,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "none",
|
||||
"useTabs": false
|
||||
},
|
||||
"remarkConfig": {
|
||||
"plugins": [
|
||||
"remark-preset-wooorm"
|
||||
]
|
||||
},
|
||||
"repository": "micromark/micromark-extension-directive",
|
||||
"scripts": {
|
||||
"build": "tsc --build --clean && tsc --build && type-coverage && micromark-build",
|
||||
"format": "remark --frail --output --quiet -- . && prettier --log-level warn --write -- . && xo --fix",
|
||||
"test-api-prod": "node --conditions production test/index.js",
|
||||
"test-api-dev": "node --conditions development test/index.js",
|
||||
"test-api": "npm run test-api-dev && npm run test-api-prod",
|
||||
"test-coverage": "c8 --100 --reporter lcov -- npm run test-api",
|
||||
"test": "npm run build && npm run format && npm run test-coverage"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"typeCoverage": {
|
||||
"atLeast": 100,
|
||||
"strict": true
|
||||
},
|
||||
"type": "module",
|
||||
"version": "4.0.0",
|
||||
"xo": {
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"**/*.d.ts"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/array-type": [
|
||||
"error",
|
||||
{
|
||||
"default": "generic"
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/ban-types": [
|
||||
"error",
|
||||
{
|
||||
"extendDefaults": true
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/consistent-indexed-object-style": [
|
||||
"error",
|
||||
"index-signature"
|
||||
],
|
||||
"@typescript-eslint/consistent-type-definitions": [
|
||||
"error",
|
||||
"interface"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"prettier": true,
|
||||
"rules": {
|
||||
"logical-assignment-operators": "off",
|
||||
"max-params": "off",
|
||||
"unicorn/no-this-assignment": "off",
|
||||
"unicorn/prefer-at": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
+451
@@ -0,0 +1,451 @@
|
||||
# micromark-extension-directive
|
||||
|
||||
[![Build][build-badge]][build]
|
||||
[![Coverage][coverage-badge]][coverage]
|
||||
[![Downloads][downloads-badge]][downloads]
|
||||
[![Size][size-badge]][size]
|
||||
[![Sponsors][sponsors-badge]][collective]
|
||||
[![Backers][backers-badge]][collective]
|
||||
[![Chat][chat-badge]][chat]
|
||||
|
||||
[micromark][] extensions to support [directives][prop] (`:cite[smith04]` and
|
||||
such).
|
||||
|
||||
## Contents
|
||||
|
||||
* [What is this?](#what-is-this)
|
||||
* [When to use this](#when-to-use-this)
|
||||
* [Install](#install)
|
||||
* [Use](#use)
|
||||
* [API](#api)
|
||||
* [`directive()`](#directive)
|
||||
* [`directiveHtml(options?)`](#directivehtmloptions)
|
||||
* [`Directive`](#directive-1)
|
||||
* [`Handle`](#handle)
|
||||
* [`HtmlOptions`](#htmloptions)
|
||||
* [Authoring](#authoring)
|
||||
* [HTML](#html)
|
||||
* [CSS](#css)
|
||||
* [Syntax](#syntax)
|
||||
* [Compatibility](#compatibility)
|
||||
* [Security](#security)
|
||||
* [Related](#related)
|
||||
* [Contribute](#contribute)
|
||||
* [License](#license)
|
||||
|
||||
## What is this?
|
||||
|
||||
This package contains two extensions that add support for directive syntax in
|
||||
markdown to [`micromark`][micromark].
|
||||
|
||||
## When to use this
|
||||
|
||||
This project is useful when you want to solve the need for an infinite number
|
||||
of potential extensions to markdown in a single markdown-esque way.
|
||||
|
||||
You can use these extensions when you are working with [`micromark`][micromark]
|
||||
already.
|
||||
|
||||
When you need a syntax tree,
|
||||
you can combine this package with
|
||||
[`mdast-util-directive`][mdast-util-directive].
|
||||
|
||||
All these packages are used [`remark-directive`][remark-directive],
|
||||
which focusses on making it easier to transform content by abstracting these
|
||||
internals away.
|
||||
|
||||
## Install
|
||||
|
||||
This package is [ESM only][esm].
|
||||
In Node.js (version 16+),
|
||||
install with [npm][]:
|
||||
|
||||
[npm][]:
|
||||
|
||||
```sh
|
||||
npm install micromark-extension-directive
|
||||
```
|
||||
|
||||
In Deno with [`esm.sh`][esmsh]:
|
||||
|
||||
```js
|
||||
import {directive, directiveHtml} from 'https://esm.sh/micromark-extension-directive@4'
|
||||
```
|
||||
|
||||
In browsers with [`esm.sh`][esmsh]:
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import {directive, directiveHtml} from 'https://esm.sh/micromark-extension-directive@4?bundle'
|
||||
</script>
|
||||
```
|
||||
|
||||
## Use
|
||||
|
||||
Say our document `example.md` contains:
|
||||
|
||||
```markdown
|
||||
A lovely language know as :abbr[HTML]{title="HyperText Markup Language"}.
|
||||
```
|
||||
|
||||
…and our module `example.js` looks as follows:
|
||||
|
||||
```js
|
||||
/**
|
||||
* @import {Handle} from 'micromark-extension-directive'
|
||||
* @import {CompileContext} from 'micromark-util-types'
|
||||
*/
|
||||
|
||||
import fs from 'node:fs/promises'
|
||||
import {micromark} from 'micromark'
|
||||
import {directive, directiveHtml} from 'micromark-extension-directive'
|
||||
|
||||
const output = micromark(await fs.readFile('example.md'), {
|
||||
extensions: [directive()],
|
||||
htmlExtensions: [directiveHtml({abbr})]
|
||||
})
|
||||
|
||||
console.log(output)
|
||||
|
||||
/**
|
||||
* @this {CompileContext}
|
||||
* @type {Handle}
|
||||
* @returns {false | undefined}
|
||||
*/
|
||||
function abbr(d) {
|
||||
if (d.type !== 'textDirective') return false
|
||||
|
||||
this.tag('<abbr')
|
||||
|
||||
if (d.attributes && 'title' in d.attributes) {
|
||||
this.tag(' title="' + this.encode(d.attributes.title) + '"')
|
||||
}
|
||||
|
||||
this.tag('>')
|
||||
this.raw(d.label || '')
|
||||
this.tag('</abbr>')
|
||||
}
|
||||
```
|
||||
|
||||
…now running `node example.js` yields:
|
||||
|
||||
```html
|
||||
<p>A lovely language know as <abbr title="HyperText Markup Language">HTML</abbr>.</p>
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
This package exports the identifiers [`directive`][api-directive] and
|
||||
[`directiveHtml`][api-directive-html].
|
||||
There is no default export.
|
||||
It exports the [TypeScript][] types
|
||||
[`Directive`][api-directive-type],
|
||||
[`Handle`][api-handle],
|
||||
and [`HtmlOptions`][api-html-options].
|
||||
|
||||
The export map supports the [`development` condition][development].
|
||||
Run `node --conditions development module.js` to get instrumented dev code.
|
||||
Without this condition,
|
||||
production code is loaded.
|
||||
|
||||
### `directive()`
|
||||
|
||||
Create an extension for `micromark` to enable directive syntax.
|
||||
|
||||
###### Returns
|
||||
|
||||
Extension for `micromark` that can be passed in `extensions`,
|
||||
to enable directive syntax
|
||||
([`Extension`][micromark-extension]).
|
||||
|
||||
### `directiveHtml(options?)`
|
||||
|
||||
Create an extension for `micromark` to support directives when serializing to
|
||||
HTML.
|
||||
|
||||
> 👉 **Note**:
|
||||
> this uses KaTeX to render math.
|
||||
|
||||
###### Parameters
|
||||
|
||||
* `options`
|
||||
([`HtmlOptions`][api-html-options], default: `{}`)
|
||||
— configuration
|
||||
|
||||
###### Returns
|
||||
|
||||
Extension for `micromark` that can be passed in `htmlExtensions`,
|
||||
to support directives when serializing to HTML
|
||||
([`HtmlExtension`][micromark-html-extension]).
|
||||
|
||||
### `Directive`
|
||||
|
||||
Structure representing a directive (TypeScript type).
|
||||
|
||||
###### Fields
|
||||
|
||||
* `type`
|
||||
(`'containerDirective'`, `'leafDirective'`, or `'textDirective'`)
|
||||
— kind
|
||||
* `name`
|
||||
(`string`)
|
||||
— name of directive
|
||||
* `label`
|
||||
(`string` or `undefined`)
|
||||
— compiled HTML content that was in `[brackets]`
|
||||
* `attributes`
|
||||
(`Record<string, string>` or `undefined`)
|
||||
— object w/ HTML attributes
|
||||
* `content`
|
||||
(`string` or `undefined`)
|
||||
— compiled HTML content inside container directive
|
||||
|
||||
### `Handle`
|
||||
|
||||
Handle a directive (TypeScript type).
|
||||
|
||||
###### Parameters
|
||||
|
||||
* `this` ([`CompileContext`][micromark-compile-context])
|
||||
— current context
|
||||
* `directive` ([`Directive`][api-directive-type])
|
||||
— directive
|
||||
|
||||
###### Returns
|
||||
|
||||
Signal whether the directive was handled
|
||||
(`boolean`, default: `true`).
|
||||
Yield `false` to let the fallback (a special handle for `'*'`) handle it.
|
||||
|
||||
### `HtmlOptions`
|
||||
|
||||
Configuration (TypeScript type).
|
||||
|
||||
> 👉 **Note**:
|
||||
> the special field `'*'` can be used to specify a fallback handle to handle
|
||||
> all otherwise unhandled directives.
|
||||
|
||||
###### Type
|
||||
|
||||
```ts
|
||||
type HtmlOptions = Record<string, Handle>
|
||||
```
|
||||
|
||||
## Authoring
|
||||
|
||||
When authoring markdown with directives,
|
||||
keep in mind that they don’t work in most places.
|
||||
On your own site it can be great!
|
||||
|
||||
## HTML
|
||||
|
||||
You can define how directives are turned into HTML.
|
||||
If directives are not handled,
|
||||
they do not emit anything.
|
||||
|
||||
## CSS
|
||||
|
||||
How to display directives is left as an exercise for the reader.
|
||||
|
||||
## Syntax
|
||||
|
||||
The syntax looks like this:
|
||||
|
||||
```markdown
|
||||
Directives in text can form with a single colon,
|
||||
such as :cite[smith04].
|
||||
Their syntax is `:name[label]{attributes}`.
|
||||
|
||||
Leafs (block without content) can form by using two colons:
|
||||
|
||||
::youtube[Video of a cat in a box]{vid=01ab2cd3efg}
|
||||
|
||||
Their syntax is `::name[label]{attributes}` on its own line.
|
||||
|
||||
Containers (blocks with content) can form by using three colons:
|
||||
|
||||
:::spoiler
|
||||
He dies.
|
||||
:::
|
||||
|
||||
The `name` part is required.
|
||||
The first character must be a letter,
|
||||
other characters can be alphanumerical, `-`, and `_`.
|
||||
`-` or `_` cannot end a name.
|
||||
|
||||
The `[label]` part is optional (`:x` and `:x[]` are equivalent)†.
|
||||
When used,
|
||||
it can include text constructs such as emphasis and so on: `x[a *b* c]`.
|
||||
|
||||
The `{attributes}` part is optional (`:x` and `:x{}` are equivalent)†.
|
||||
When used,
|
||||
it is handled like HTML attributes, such as that `{a}`, `{a=""}`, and `{a=''}`
|
||||
but also `{a=b}`, `{a="b"}`, and `{a='b'}` are equivalent.
|
||||
Shortcuts are available for `id=` (`{#readme}` for `{id=readme}`) and
|
||||
`class` (`{.big}` for `{class=big}`).
|
||||
When multiple ids are found,
|
||||
the last is used; when multiple classes are found,
|
||||
they are combined:
|
||||
`{.red class=green .blue}` is equivalent to
|
||||
`{.red .green .blue}` and `{class="red green blue"}`.
|
||||
|
||||
† there is one case where a name must be followed by an empty label or empty
|
||||
attributes:
|
||||
a *text* directive that only has a name,
|
||||
cannot be followed by a colon.
|
||||
So,
|
||||
`:red:` doesn’t work.
|
||||
Use either `:red[]` or `:red{}` instead.
|
||||
The reason for this is to allow GitHub emoji (gemoji) and directives to coexist.
|
||||
|
||||
Containers can be nested by using more colons outside:
|
||||
|
||||
::::spoiler
|
||||
He dies.
|
||||
|
||||
:::spoiler
|
||||
She is born.
|
||||
:::
|
||||
::::
|
||||
|
||||
The closing fence must include the same or more colons as the opening.
|
||||
If no closing is found,
|
||||
the container runs to the end of its parent container
|
||||
(block quote, list item, document, or other container).
|
||||
|
||||
::::spoiler
|
||||
These three are not enough to close
|
||||
:::
|
||||
So this line is also part of the container.
|
||||
```
|
||||
|
||||
Note that while other implementations are sometimes loose in what they allow,
|
||||
this implementation mimics CommonMark as closely as possible:
|
||||
|
||||
* whitespace is not allowed between colons and name (~~`: a`~~),
|
||||
name and label (~~`:a []`~~),
|
||||
name and attributes (~~`:a {}`~~),
|
||||
or label and attributes (~~`:a[] {}`~~)
|
||||
— because it’s not allowed in links either
|
||||
(~~`[] ()`~~)
|
||||
* no trailing colons allowed on the opening fence of a container
|
||||
(~~`:::a:::`~~)
|
||||
— because it’s not allowed in fenced code either
|
||||
* the label and attributes in a leaf or container cannot include line endings
|
||||
(~~`::a[b\nc]`~~)
|
||||
— because it’s not allowed in fenced code either
|
||||
|
||||
## 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-extension-directive@4`,
|
||||
compatible with Node.js 16.
|
||||
|
||||
This package works with `micromark` version `4` and later.
|
||||
|
||||
## Security
|
||||
|
||||
This package is safe assuming that you write safe handlers.
|
||||
Any vulnerability in your code could open you to a
|
||||
[cross-site scripting (XSS)][xss] attack.
|
||||
|
||||
## Related
|
||||
|
||||
* [`remark-directive`][remark-directive]
|
||||
— remark plugin to support directives
|
||||
* [`mdast-util-directive`][mdast-util-directive]
|
||||
— mdast utility to support directives
|
||||
|
||||
## Contribute
|
||||
|
||||
See [`contributing.md` in `micromark/.github`][contributing] 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,
|
||||
organization,
|
||||
or community you agree to abide by its terms.
|
||||
|
||||
## License
|
||||
|
||||
[MIT][license] © [Titus Wormer][author]
|
||||
|
||||
<!-- Definitions -->
|
||||
|
||||
[api-directive]: #directive
|
||||
|
||||
[api-directive-html]: #directivehtmloptions
|
||||
|
||||
[api-directive-type]: #directive-1
|
||||
|
||||
[api-handle]: #handle
|
||||
|
||||
[api-html-options]: #htmloptions
|
||||
|
||||
[author]: https://wooorm.com
|
||||
|
||||
[backers-badge]: https://opencollective.com/unified/backers/badge.svg
|
||||
|
||||
[build]: https://github.com/micromark/micromark-extension-directive/actions
|
||||
|
||||
[build-badge]: https://github.com/micromark/micromark-extension-directive/workflows/main/badge.svg
|
||||
|
||||
[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
|
||||
|
||||
[collective]: https://opencollective.com/unified
|
||||
|
||||
[contributing]: https://github.com/micromark/.github/blob/main/contributing.md
|
||||
|
||||
[coverage]: https://codecov.io/github/micromark/micromark-extension-directive
|
||||
|
||||
[coverage-badge]: https://img.shields.io/codecov/c/github/micromark/micromark-extension-directive.svg
|
||||
|
||||
[development]: https://nodejs.org/api/packages.html#packages_resolving_user_conditions
|
||||
|
||||
[downloads]: https://www.npmjs.com/package/micromark-extension-directive
|
||||
|
||||
[downloads-badge]: https://img.shields.io/npm/dm/micromark-extension-directive.svg
|
||||
|
||||
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
|
||||
|
||||
[esmsh]: https://esm.sh
|
||||
|
||||
[license]: license
|
||||
|
||||
[mdast-util-directive]: https://github.com/syntax-tree/mdast-util-directive
|
||||
|
||||
[micromark]: https://github.com/micromark/micromark
|
||||
|
||||
[micromark-compile-context]: https://github.com/micromark/micromark/blob/41e3c4c/packages/micromark-util-types/index.js#L457
|
||||
|
||||
[micromark-extension]: https://github.com/micromark/micromark#syntaxextension
|
||||
|
||||
[micromark-html-extension]: https://github.com/micromark/micromark#htmlextension
|
||||
|
||||
[npm]: https://docs.npmjs.com/cli/install
|
||||
|
||||
[prop]: https://talk.commonmark.org/t/generic-directives-plugins-syntax/444
|
||||
|
||||
[remark-directive]: https://github.com/remarkjs/remark-directive
|
||||
|
||||
[size]: https://bundlejs.com/?q=micromark-extension-directive
|
||||
|
||||
[size-badge]: https://img.shields.io/badge/dynamic/json?label=minzipped%20size&query=$.size.compressedSize&url=https://deno.bundlejs.com/?q=micromark-extension-directive
|
||||
|
||||
[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
|
||||
|
||||
[support]: https://github.com/micromark/.github/blob/main/support.md
|
||||
|
||||
[typescript]: https://www.typescriptlang.org
|
||||
|
||||
[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting
|
||||
Reference in New Issue
Block a user