mirror of
https://github.com/Snigdha-OS/documentation.git
synced 2025-09-09 19:44:56 +02:00
315 lines
7.6 KiB
JavaScript
315 lines
7.6 KiB
JavaScript
/**
|
||
* @typedef {import('micromark-util-types').Code} Code
|
||
* @typedef {import('micromark-util-types').Effects} Effects
|
||
* @typedef {import('micromark-util-types').State} State
|
||
* @typedef {import('micromark-util-types').TokenType} TokenType
|
||
*/
|
||
|
||
import {factorySpace} from 'micromark-factory-space'
|
||
import {factoryWhitespace} from 'micromark-factory-whitespace'
|
||
import {
|
||
asciiAlpha,
|
||
asciiAlphanumeric,
|
||
markdownLineEnding,
|
||
markdownLineEndingOrSpace,
|
||
markdownSpace
|
||
} 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 (code === 58 || code === 95 || asciiAlpha(code)) {
|
||
effects.enter(attributeType)
|
||
effects.enter(attributeNameType)
|
||
effects.consume(code)
|
||
return name
|
||
}
|
||
if (disallowEol && markdownSpace(code)) {
|
||
return factorySpace(effects, between, 'whitespace')(code)
|
||
}
|
||
if (!disallowEol && markdownLineEndingOrSpace(code)) {
|
||
return factoryWhitespace(effects, between)(code)
|
||
}
|
||
return end(code)
|
||
}
|
||
|
||
/** @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 === 45 ||
|
||
code === 46 ||
|
||
code === 58 ||
|
||
code === 95 ||
|
||
asciiAlphanumeric(code)
|
||
) {
|
||
effects.consume(code)
|
||
return name
|
||
}
|
||
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)
|
||
}
|
||
|
||
/** @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)
|
||
}
|
||
}
|