Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

html-flow.js 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. 'use strict'
  2. var assert = require('assert')
  3. var asciiAlpha = require('../character/ascii-alpha.js')
  4. var asciiAlphanumeric = require('../character/ascii-alphanumeric.js')
  5. var codes = require('../character/codes.js')
  6. var markdownLineEnding = require('../character/markdown-line-ending.js')
  7. var markdownLineEndingOrSpace = require('../character/markdown-line-ending-or-space.js')
  8. var markdownSpace = require('../character/markdown-space.js')
  9. var constants = require('../constant/constants.js')
  10. var fromCharCode = require('../constant/from-char-code.js')
  11. var htmlBlockNames = require('../constant/html-block-names.js')
  12. var htmlRawNames = require('../constant/html-raw-names.js')
  13. var types = require('../constant/types.js')
  14. var partialBlankLine = require('./partial-blank-line.js')
  15. function _interopDefaultLegacy(e) {
  16. return e && typeof e === 'object' && 'default' in e ? e : {default: e}
  17. }
  18. var assert__default = /*#__PURE__*/ _interopDefaultLegacy(assert)
  19. var htmlFlow = {
  20. name: 'htmlFlow',
  21. tokenize: tokenizeHtmlFlow,
  22. resolveTo: resolveToHtmlFlow,
  23. concrete: true
  24. }
  25. var nextBlankConstruct = {tokenize: tokenizeNextBlank, partial: true}
  26. function resolveToHtmlFlow(events) {
  27. var index = events.length
  28. while (index--) {
  29. if (
  30. events[index][0] === 'enter' &&
  31. events[index][1].type === types.htmlFlow
  32. ) {
  33. break
  34. }
  35. }
  36. if (index > 1 && events[index - 2][1].type === types.linePrefix) {
  37. // Add the prefix start to the HTML token.
  38. events[index][1].start = events[index - 2][1].start
  39. // Add the prefix start to the HTML line token.
  40. events[index + 1][1].start = events[index - 2][1].start
  41. // Remove the line prefix.
  42. events.splice(index - 2, 2)
  43. }
  44. return events
  45. }
  46. function tokenizeHtmlFlow(effects, ok, nok) {
  47. var self = this
  48. var kind
  49. var startTag
  50. var buffer
  51. var index
  52. var marker
  53. return start
  54. function start(code) {
  55. assert__default['default'](code === codes.lessThan, 'expected `<`')
  56. effects.enter(types.htmlFlow)
  57. effects.enter(types.htmlFlowData)
  58. effects.consume(code)
  59. return open
  60. }
  61. function open(code) {
  62. if (code === codes.exclamationMark) {
  63. effects.consume(code)
  64. return declarationStart
  65. }
  66. if (code === codes.slash) {
  67. effects.consume(code)
  68. return tagCloseStart
  69. }
  70. if (code === codes.questionMark) {
  71. effects.consume(code)
  72. kind = constants.htmlInstruction
  73. // While we’re in an instruction instead of a declaration, we’re on a `?`
  74. // right now, so we do need to search for `>`, similar to declarations.
  75. return self.interrupt ? ok : continuationDeclarationInside
  76. }
  77. if (asciiAlpha(code)) {
  78. effects.consume(code)
  79. buffer = fromCharCode(code)
  80. startTag = true
  81. return tagName
  82. }
  83. return nok(code)
  84. }
  85. function declarationStart(code) {
  86. if (code === codes.dash) {
  87. effects.consume(code)
  88. kind = constants.htmlComment
  89. return commentOpenInside
  90. }
  91. if (code === codes.leftSquareBracket) {
  92. effects.consume(code)
  93. kind = constants.htmlCdata
  94. buffer = constants.cdataOpeningString
  95. index = 0
  96. return cdataOpenInside
  97. }
  98. if (asciiAlpha(code)) {
  99. effects.consume(code)
  100. kind = constants.htmlDeclaration
  101. return self.interrupt ? ok : continuationDeclarationInside
  102. }
  103. return nok(code)
  104. }
  105. function commentOpenInside(code) {
  106. if (code === codes.dash) {
  107. effects.consume(code)
  108. return self.interrupt ? ok : continuationDeclarationInside
  109. }
  110. return nok(code)
  111. }
  112. function cdataOpenInside(code) {
  113. if (code === buffer.charCodeAt(index++)) {
  114. effects.consume(code)
  115. return index === buffer.length
  116. ? self.interrupt
  117. ? ok
  118. : continuation
  119. : cdataOpenInside
  120. }
  121. return nok(code)
  122. }
  123. function tagCloseStart(code) {
  124. if (asciiAlpha(code)) {
  125. effects.consume(code)
  126. buffer = fromCharCode(code)
  127. return tagName
  128. }
  129. return nok(code)
  130. }
  131. function tagName(code) {
  132. if (
  133. code === codes.eof ||
  134. code === codes.slash ||
  135. code === codes.greaterThan ||
  136. markdownLineEndingOrSpace(code)
  137. ) {
  138. if (
  139. code !== codes.slash &&
  140. startTag &&
  141. htmlRawNames.indexOf(buffer.toLowerCase()) > -1
  142. ) {
  143. kind = constants.htmlRaw
  144. return self.interrupt ? ok(code) : continuation(code)
  145. }
  146. if (htmlBlockNames.indexOf(buffer.toLowerCase()) > -1) {
  147. kind = constants.htmlBasic
  148. if (code === codes.slash) {
  149. effects.consume(code)
  150. return basicSelfClosing
  151. }
  152. return self.interrupt ? ok(code) : continuation(code)
  153. }
  154. kind = constants.htmlComplete
  155. // Do not support complete HTML when interrupting.
  156. return self.interrupt
  157. ? nok(code)
  158. : startTag
  159. ? completeAttributeNameBefore(code)
  160. : completeClosingTagAfter(code)
  161. }
  162. if (code === codes.dash || asciiAlphanumeric(code)) {
  163. effects.consume(code)
  164. buffer += fromCharCode(code)
  165. return tagName
  166. }
  167. return nok(code)
  168. }
  169. function basicSelfClosing(code) {
  170. if (code === codes.greaterThan) {
  171. effects.consume(code)
  172. return self.interrupt ? ok : continuation
  173. }
  174. return nok(code)
  175. }
  176. function completeClosingTagAfter(code) {
  177. if (markdownSpace(code)) {
  178. effects.consume(code)
  179. return completeClosingTagAfter
  180. }
  181. return completeEnd(code)
  182. }
  183. function completeAttributeNameBefore(code) {
  184. if (code === codes.slash) {
  185. effects.consume(code)
  186. return completeEnd
  187. }
  188. if (code === codes.colon || code === codes.underscore || asciiAlpha(code)) {
  189. effects.consume(code)
  190. return completeAttributeName
  191. }
  192. if (markdownSpace(code)) {
  193. effects.consume(code)
  194. return completeAttributeNameBefore
  195. }
  196. return completeEnd(code)
  197. }
  198. function completeAttributeName(code) {
  199. if (
  200. code === codes.dash ||
  201. code === codes.dot ||
  202. code === codes.colon ||
  203. code === codes.underscore ||
  204. asciiAlphanumeric(code)
  205. ) {
  206. effects.consume(code)
  207. return completeAttributeName
  208. }
  209. return completeAttributeNameAfter(code)
  210. }
  211. function completeAttributeNameAfter(code) {
  212. if (code === codes.equalsTo) {
  213. effects.consume(code)
  214. return completeAttributeValueBefore
  215. }
  216. if (markdownSpace(code)) {
  217. effects.consume(code)
  218. return completeAttributeNameAfter
  219. }
  220. return completeAttributeNameBefore(code)
  221. }
  222. function completeAttributeValueBefore(code) {
  223. if (
  224. code === codes.eof ||
  225. code === codes.lessThan ||
  226. code === codes.equalsTo ||
  227. code === codes.greaterThan ||
  228. code === codes.graveAccent
  229. ) {
  230. return nok(code)
  231. }
  232. if (code === codes.quotationMark || code === codes.apostrophe) {
  233. effects.consume(code)
  234. marker = code
  235. return completeAttributeValueQuoted
  236. }
  237. if (markdownSpace(code)) {
  238. effects.consume(code)
  239. return completeAttributeValueBefore
  240. }
  241. marker = undefined
  242. return completeAttributeValueUnquoted(code)
  243. }
  244. function completeAttributeValueQuoted(code) {
  245. if (code === marker) {
  246. effects.consume(code)
  247. return completeAttributeValueQuotedAfter
  248. }
  249. if (code === codes.eof || markdownLineEnding(code)) {
  250. return nok(code)
  251. }
  252. effects.consume(code)
  253. return completeAttributeValueQuoted
  254. }
  255. function completeAttributeValueUnquoted(code) {
  256. if (
  257. code === codes.eof ||
  258. code === codes.quotationMark ||
  259. code === codes.apostrophe ||
  260. code === codes.lessThan ||
  261. code === codes.equalsTo ||
  262. code === codes.greaterThan ||
  263. code === codes.graveAccent ||
  264. markdownLineEndingOrSpace(code)
  265. ) {
  266. return completeAttributeNameAfter(code)
  267. }
  268. effects.consume(code)
  269. return completeAttributeValueUnquoted
  270. }
  271. function completeAttributeValueQuotedAfter(code) {
  272. if (
  273. code === codes.slash ||
  274. code === codes.greaterThan ||
  275. markdownSpace(code)
  276. ) {
  277. return completeAttributeNameBefore(code)
  278. }
  279. return nok(code)
  280. }
  281. function completeEnd(code) {
  282. if (code === codes.greaterThan) {
  283. effects.consume(code)
  284. return completeAfter
  285. }
  286. return nok(code)
  287. }
  288. function completeAfter(code) {
  289. if (markdownSpace(code)) {
  290. effects.consume(code)
  291. return completeAfter
  292. }
  293. return code === codes.eof || markdownLineEnding(code)
  294. ? continuation(code)
  295. : nok(code)
  296. }
  297. function continuation(code) {
  298. if (code === codes.dash && kind === constants.htmlComment) {
  299. effects.consume(code)
  300. return continuationCommentInside
  301. }
  302. if (code === codes.lessThan && kind === constants.htmlRaw) {
  303. effects.consume(code)
  304. return continuationRawTagOpen
  305. }
  306. if (code === codes.greaterThan && kind === constants.htmlDeclaration) {
  307. effects.consume(code)
  308. return continuationClose
  309. }
  310. if (code === codes.questionMark && kind === constants.htmlInstruction) {
  311. effects.consume(code)
  312. return continuationDeclarationInside
  313. }
  314. if (code === codes.rightSquareBracket && kind === constants.htmlCdata) {
  315. effects.consume(code)
  316. return continuationCharacterDataInside
  317. }
  318. if (
  319. markdownLineEnding(code) &&
  320. (kind === constants.htmlBasic || kind === constants.htmlComplete)
  321. ) {
  322. return effects.check(
  323. nextBlankConstruct,
  324. continuationClose,
  325. continuationAtLineEnding
  326. )(code)
  327. }
  328. if (code === codes.eof || markdownLineEnding(code)) {
  329. return continuationAtLineEnding(code)
  330. }
  331. effects.consume(code)
  332. return continuation
  333. }
  334. function continuationAtLineEnding(code) {
  335. effects.exit(types.htmlFlowData)
  336. return htmlContinueStart(code)
  337. }
  338. function htmlContinueStart(code) {
  339. if (code === codes.eof) {
  340. return done(code)
  341. }
  342. if (markdownLineEnding(code)) {
  343. effects.enter(types.lineEnding)
  344. effects.consume(code)
  345. effects.exit(types.lineEnding)
  346. return htmlContinueStart
  347. }
  348. effects.enter(types.htmlFlowData)
  349. return continuation(code)
  350. }
  351. function continuationCommentInside(code) {
  352. if (code === codes.dash) {
  353. effects.consume(code)
  354. return continuationDeclarationInside
  355. }
  356. return continuation(code)
  357. }
  358. function continuationRawTagOpen(code) {
  359. if (code === codes.slash) {
  360. effects.consume(code)
  361. buffer = ''
  362. return continuationRawEndTag
  363. }
  364. return continuation(code)
  365. }
  366. function continuationRawEndTag(code) {
  367. if (
  368. code === codes.greaterThan &&
  369. htmlRawNames.indexOf(buffer.toLowerCase()) > -1
  370. ) {
  371. effects.consume(code)
  372. return continuationClose
  373. }
  374. if (asciiAlpha(code) && buffer.length < constants.htmlRawSizeMax) {
  375. effects.consume(code)
  376. buffer += fromCharCode(code)
  377. return continuationRawEndTag
  378. }
  379. return continuation(code)
  380. }
  381. function continuationCharacterDataInside(code) {
  382. if (code === codes.rightSquareBracket) {
  383. effects.consume(code)
  384. return continuationDeclarationInside
  385. }
  386. return continuation(code)
  387. }
  388. function continuationDeclarationInside(code) {
  389. if (code === codes.greaterThan) {
  390. effects.consume(code)
  391. return continuationClose
  392. }
  393. return continuation(code)
  394. }
  395. function continuationClose(code) {
  396. if (code === codes.eof || markdownLineEnding(code)) {
  397. effects.exit(types.htmlFlowData)
  398. return done(code)
  399. }
  400. effects.consume(code)
  401. return continuationClose
  402. }
  403. function done(code) {
  404. effects.exit(types.htmlFlow)
  405. return ok(code)
  406. }
  407. }
  408. function tokenizeNextBlank(effects, ok, nok) {
  409. return start
  410. function start(code) {
  411. assert__default['default'](
  412. markdownLineEnding(code),
  413. 'expected a line ending'
  414. )
  415. effects.exit(types.htmlFlowData)
  416. effects.enter(types.lineEndingBlank)
  417. effects.consume(code)
  418. effects.exit(types.lineEndingBlank)
  419. return effects.attempt(partialBlankLine, ok, nok)
  420. }
  421. }
  422. module.exports = htmlFlow