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 10KB

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