123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513 |
- 'use strict'
-
- var assert = require('assert')
- var asciiAlpha = require('../character/ascii-alpha.js')
- var asciiAlphanumeric = require('../character/ascii-alphanumeric.js')
- var codes = require('../character/codes.js')
- var markdownLineEnding = require('../character/markdown-line-ending.js')
- var markdownLineEndingOrSpace = require('../character/markdown-line-ending-or-space.js')
- var markdownSpace = require('../character/markdown-space.js')
- var constants = require('../constant/constants.js')
- var fromCharCode = require('../constant/from-char-code.js')
- var htmlBlockNames = require('../constant/html-block-names.js')
- var htmlRawNames = require('../constant/html-raw-names.js')
- var types = require('../constant/types.js')
- var partialBlankLine = require('./partial-blank-line.js')
-
- function _interopDefaultLegacy(e) {
- return e && typeof e === 'object' && 'default' in e ? e : {default: e}
- }
-
- var assert__default = /*#__PURE__*/ _interopDefaultLegacy(assert)
-
- var htmlFlow = {
- name: 'htmlFlow',
- tokenize: tokenizeHtmlFlow,
- resolveTo: resolveToHtmlFlow,
- concrete: true
- }
-
- var nextBlankConstruct = {tokenize: tokenizeNextBlank, partial: true}
-
- function resolveToHtmlFlow(events) {
- var index = events.length
-
- while (index--) {
- if (
- events[index][0] === 'enter' &&
- events[index][1].type === types.htmlFlow
- ) {
- break
- }
- }
-
- if (index > 1 && events[index - 2][1].type === types.linePrefix) {
- // Add the prefix start to the HTML token.
- events[index][1].start = events[index - 2][1].start
- // Add the prefix start to the HTML line token.
- events[index + 1][1].start = events[index - 2][1].start
- // Remove the line prefix.
- events.splice(index - 2, 2)
- }
-
- return events
- }
-
- function tokenizeHtmlFlow(effects, ok, nok) {
- var self = this
- var kind
- var startTag
- var buffer
- var index
- var marker
-
- return start
-
- function start(code) {
- assert__default['default'](code === codes.lessThan, 'expected `<`')
- effects.enter(types.htmlFlow)
- effects.enter(types.htmlFlowData)
- effects.consume(code)
- return open
- }
-
- function open(code) {
- if (code === codes.exclamationMark) {
- effects.consume(code)
- return declarationStart
- }
-
- if (code === codes.slash) {
- effects.consume(code)
- return tagCloseStart
- }
-
- if (code === codes.questionMark) {
- effects.consume(code)
- kind = constants.htmlInstruction
- // While we’re in an instruction instead of a declaration, we’re on a `?`
- // right now, so we do need to search for `>`, similar to declarations.
- return self.interrupt ? ok : continuationDeclarationInside
- }
-
- if (asciiAlpha(code)) {
- effects.consume(code)
- buffer = fromCharCode(code)
- startTag = true
- return tagName
- }
-
- return nok(code)
- }
-
- function declarationStart(code) {
- if (code === codes.dash) {
- effects.consume(code)
- kind = constants.htmlComment
- return commentOpenInside
- }
-
- if (code === codes.leftSquareBracket) {
- effects.consume(code)
- kind = constants.htmlCdata
- buffer = constants.cdataOpeningString
- index = 0
- return cdataOpenInside
- }
-
- if (asciiAlpha(code)) {
- effects.consume(code)
- kind = constants.htmlDeclaration
- return self.interrupt ? ok : continuationDeclarationInside
- }
-
- return nok(code)
- }
-
- function commentOpenInside(code) {
- if (code === codes.dash) {
- effects.consume(code)
- return self.interrupt ? ok : continuationDeclarationInside
- }
-
- return nok(code)
- }
-
- function cdataOpenInside(code) {
- if (code === buffer.charCodeAt(index++)) {
- effects.consume(code)
- return index === buffer.length
- ? self.interrupt
- ? ok
- : continuation
- : cdataOpenInside
- }
-
- return nok(code)
- }
-
- function tagCloseStart(code) {
- if (asciiAlpha(code)) {
- effects.consume(code)
- buffer = fromCharCode(code)
- return tagName
- }
-
- return nok(code)
- }
-
- function tagName(code) {
- if (
- code === codes.eof ||
- code === codes.slash ||
- code === codes.greaterThan ||
- markdownLineEndingOrSpace(code)
- ) {
- if (
- code !== codes.slash &&
- startTag &&
- htmlRawNames.indexOf(buffer.toLowerCase()) > -1
- ) {
- kind = constants.htmlRaw
- return self.interrupt ? ok(code) : continuation(code)
- }
-
- if (htmlBlockNames.indexOf(buffer.toLowerCase()) > -1) {
- kind = constants.htmlBasic
-
- if (code === codes.slash) {
- effects.consume(code)
- return basicSelfClosing
- }
-
- return self.interrupt ? ok(code) : continuation(code)
- }
-
- kind = constants.htmlComplete
- // Do not support complete HTML when interrupting.
- return self.interrupt
- ? nok(code)
- : startTag
- ? completeAttributeNameBefore(code)
- : completeClosingTagAfter(code)
- }
-
- if (code === codes.dash || asciiAlphanumeric(code)) {
- effects.consume(code)
- buffer += fromCharCode(code)
- return tagName
- }
-
- return nok(code)
- }
-
- function basicSelfClosing(code) {
- if (code === codes.greaterThan) {
- effects.consume(code)
- return self.interrupt ? ok : continuation
- }
-
- return nok(code)
- }
-
- function completeClosingTagAfter(code) {
- if (markdownSpace(code)) {
- effects.consume(code)
- return completeClosingTagAfter
- }
-
- return completeEnd(code)
- }
-
- function completeAttributeNameBefore(code) {
- if (code === codes.slash) {
- effects.consume(code)
- return completeEnd
- }
-
- if (code === codes.colon || code === codes.underscore || asciiAlpha(code)) {
- effects.consume(code)
- return completeAttributeName
- }
-
- if (markdownSpace(code)) {
- effects.consume(code)
- return completeAttributeNameBefore
- }
-
- return completeEnd(code)
- }
-
- function completeAttributeName(code) {
- if (
- code === codes.dash ||
- code === codes.dot ||
- code === codes.colon ||
- code === codes.underscore ||
- asciiAlphanumeric(code)
- ) {
- effects.consume(code)
- return completeAttributeName
- }
-
- return completeAttributeNameAfter(code)
- }
-
- function completeAttributeNameAfter(code) {
- if (code === codes.equalsTo) {
- effects.consume(code)
- return completeAttributeValueBefore
- }
-
- if (markdownSpace(code)) {
- effects.consume(code)
- return completeAttributeNameAfter
- }
-
- return completeAttributeNameBefore(code)
- }
-
- function completeAttributeValueBefore(code) {
- if (
- code === codes.eof ||
- code === codes.lessThan ||
- code === codes.equalsTo ||
- code === codes.greaterThan ||
- code === codes.graveAccent
- ) {
- return nok(code)
- }
-
- if (code === codes.quotationMark || code === codes.apostrophe) {
- effects.consume(code)
- marker = code
- return completeAttributeValueQuoted
- }
-
- if (markdownSpace(code)) {
- effects.consume(code)
- return completeAttributeValueBefore
- }
-
- marker = undefined
- return completeAttributeValueUnquoted(code)
- }
-
- function completeAttributeValueQuoted(code) {
- if (code === marker) {
- effects.consume(code)
- return completeAttributeValueQuotedAfter
- }
-
- if (code === codes.eof || markdownLineEnding(code)) {
- return nok(code)
- }
-
- effects.consume(code)
- return completeAttributeValueQuoted
- }
-
- function completeAttributeValueUnquoted(code) {
- if (
- code === codes.eof ||
- code === codes.quotationMark ||
- code === codes.apostrophe ||
- code === codes.lessThan ||
- code === codes.equalsTo ||
- code === codes.greaterThan ||
- code === codes.graveAccent ||
- markdownLineEndingOrSpace(code)
- ) {
- return completeAttributeNameAfter(code)
- }
-
- effects.consume(code)
- return completeAttributeValueUnquoted
- }
-
- function completeAttributeValueQuotedAfter(code) {
- if (
- code === codes.slash ||
- code === codes.greaterThan ||
- markdownSpace(code)
- ) {
- return completeAttributeNameBefore(code)
- }
-
- return nok(code)
- }
-
- function completeEnd(code) {
- if (code === codes.greaterThan) {
- effects.consume(code)
- return completeAfter
- }
-
- return nok(code)
- }
-
- function completeAfter(code) {
- if (markdownSpace(code)) {
- effects.consume(code)
- return completeAfter
- }
-
- return code === codes.eof || markdownLineEnding(code)
- ? continuation(code)
- : nok(code)
- }
-
- function continuation(code) {
- if (code === codes.dash && kind === constants.htmlComment) {
- effects.consume(code)
- return continuationCommentInside
- }
-
- if (code === codes.lessThan && kind === constants.htmlRaw) {
- effects.consume(code)
- return continuationRawTagOpen
- }
-
- if (code === codes.greaterThan && kind === constants.htmlDeclaration) {
- effects.consume(code)
- return continuationClose
- }
-
- if (code === codes.questionMark && kind === constants.htmlInstruction) {
- effects.consume(code)
- return continuationDeclarationInside
- }
-
- if (code === codes.rightSquareBracket && kind === constants.htmlCdata) {
- effects.consume(code)
- return continuationCharacterDataInside
- }
-
- if (
- markdownLineEnding(code) &&
- (kind === constants.htmlBasic || kind === constants.htmlComplete)
- ) {
- return effects.check(
- nextBlankConstruct,
- continuationClose,
- continuationAtLineEnding
- )(code)
- }
-
- if (code === codes.eof || markdownLineEnding(code)) {
- return continuationAtLineEnding(code)
- }
-
- effects.consume(code)
- return continuation
- }
-
- function continuationAtLineEnding(code) {
- effects.exit(types.htmlFlowData)
- return htmlContinueStart(code)
- }
-
- function htmlContinueStart(code) {
- if (code === codes.eof) {
- return done(code)
- }
-
- if (markdownLineEnding(code)) {
- effects.enter(types.lineEnding)
- effects.consume(code)
- effects.exit(types.lineEnding)
- return htmlContinueStart
- }
-
- effects.enter(types.htmlFlowData)
- return continuation(code)
- }
-
- function continuationCommentInside(code) {
- if (code === codes.dash) {
- effects.consume(code)
- return continuationDeclarationInside
- }
-
- return continuation(code)
- }
-
- function continuationRawTagOpen(code) {
- if (code === codes.slash) {
- effects.consume(code)
- buffer = ''
- return continuationRawEndTag
- }
-
- return continuation(code)
- }
-
- function continuationRawEndTag(code) {
- if (
- code === codes.greaterThan &&
- htmlRawNames.indexOf(buffer.toLowerCase()) > -1
- ) {
- effects.consume(code)
- return continuationClose
- }
-
- if (asciiAlpha(code) && buffer.length < constants.htmlRawSizeMax) {
- effects.consume(code)
- buffer += fromCharCode(code)
- return continuationRawEndTag
- }
-
- return continuation(code)
- }
-
- function continuationCharacterDataInside(code) {
- if (code === codes.rightSquareBracket) {
- effects.consume(code)
- return continuationDeclarationInside
- }
-
- return continuation(code)
- }
-
- function continuationDeclarationInside(code) {
- if (code === codes.greaterThan) {
- effects.consume(code)
- return continuationClose
- }
-
- return continuation(code)
- }
-
- function continuationClose(code) {
- if (code === codes.eof || markdownLineEnding(code)) {
- effects.exit(types.htmlFlowData)
- return done(code)
- }
-
- effects.consume(code)
- return continuationClose
- }
-
- function done(code) {
- effects.exit(types.htmlFlow)
- return ok(code)
- }
- }
-
- function tokenizeNextBlank(effects, ok, nok) {
- return start
-
- function start(code) {
- assert__default['default'](
- markdownLineEnding(code),
- 'expected a line ending'
- )
- effects.exit(types.htmlFlowData)
- effects.enter(types.lineEndingBlank)
- effects.consume(code)
- effects.exit(types.lineEndingBlank)
- return effects.attempt(partialBlankLine, ok, nok)
- }
- }
-
- module.exports = htmlFlow
|