Brunobkr/llama.cpp_AlgMor24_github
ΩFFFΣLLIa • llama.cpp • AlgMor24 ██████╗ ███████╗███████╗███████╗██╗ ██╗ ██╗ █████╗ ██╔═══██╗██╔════╝██╔════╝██╔════╝██║ ██║ ██║██╔══██╗ ██║ ██║█████╗ █████╗ █████╗ ██║ ██║ ██║███████║ ██║ ██║██╔══╝ ██╔══╝ ██╔══╝ ██║ ██║ ██║██╔══██║ ╚██████╔╝██║ ██║ ███████╗███████╗███████╗██║██║ ██║ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝╚══════╝╚═╝╚═╝ ╚═╝ High-Performance LLM / VLM Inference & Autonomous Agentic Ecosystem… See the full description on the dataset page: https://huggingface.co/datasets/Brunobkr/llama.cpp_AlgMor24_github.
03.1k
1/**2 * While micromark is a lexer/tokenizer, the common case of going from markdown3 * to html is currently built in as this module, even though the parts can be4 * used separately to build ASTs, CSTs, or many other output formats.5 *6 * Having an HTML compiler built in is useful because it allows us to check for7 * compliancy to CommonMark, the de facto norm of markdown, specified in roughly8 * 600 input/output cases.9 *10 * This module has an interface that accepts lists of events instead of the11 * whole at once, however, because markdown can’t be truly streaming, we buffer12 * events before processing and outputting the final result.13 */14 15/**16 * @import {17 * CompileContext,18 * CompileData,19 * CompileOptions,20 * Compile,21 * Definition,22 * Event,23 * Handle,24 * HtmlExtension,25 * LineEnding,26 * NormalizedHtmlExtension,27 * Token28 * } from 'micromark-util-types'29 */30 31/**32 * @typedef Media33 * @property {boolean | undefined} [image]34 * @property {string | undefined} [labelId]35 * @property {string | undefined} [label]36 * @property {string | undefined} [referenceId]37 * @property {string | undefined} [destination]38 * @property {string | undefined} [title]39 */40 41import {decodeNamedCharacterReference} from 'decode-named-character-reference'42import {ok as assert} from 'devlop'43import {push} from 'micromark-util-chunked'44import {combineHtmlExtensions} from 'micromark-util-combine-extensions'45import {decodeNumericCharacterReference} from 'micromark-util-decode-numeric-character-reference'46import {encode as _encode} from 'micromark-util-encode'47import {normalizeIdentifier} from 'micromark-util-normalize-identifier'48import {sanitizeUri} from 'micromark-util-sanitize-uri'49import {codes, constants, types} from 'micromark-util-symbol'50 51const hasOwnProperty = {}.hasOwnProperty52 53/**54 * These two are allowlists of safe protocols for full URLs in respectively the55 * `href` (on `<a>`) and `src` (on `<img>`) attributes.56 * They are based on what is allowed on GitHub,57 * <https://github.com/syntax-tree/hast-util-sanitize/blob/9275b21/lib/github.json#L31>58 */59const protocolHref = /^(https?|ircs?|mailto|xmpp)$/i60const protocolSource = /^https?$/i61 62/**63 * @param {CompileOptions | null | undefined} [options]64 * @returns {Compile}65 */66export function compile(options) {67 const settings = options || {}68 69 /**70 * Tags is needed because according to markdown, links and emphasis and71 * whatnot can exist in images, however, as HTML doesn’t allow content in72 * images, the tags are ignored in the `alt` attribute, but the content73 * remains.74 *75 * @type {boolean | undefined}76 */77 let tags = true78 79 /**80 * An object to track identifiers to media (URLs and titles) defined with81 * definitions.82 *83 * @type {Record<string, Definition>}84 */85 const definitions = {}86 87 /**88 * A lot of the handlers need to capture some of the output data, modify it89 * somehow, and then deal with it.90 * We do that by tracking a stack of buffers, that can be opened (with91 * `buffer`) and closed (with `resume`) to access them.92 *93 * @type {Array<Array<string>>}94 */95 const buffers = [[]]96 97 /**98 * As we can have links in images and the other way around, where the deepest99 * ones are closed first, we need to track which one we’re in.100 *101 * @type {Array<Media>}102 */103 const mediaStack = []104 105 /**106 * Same as `mediaStack` for tightness, which is specific to lists.107 * We need to track if we’re currently in a tight or loose container.108 *109 * @type {Array<boolean>}110 */111 const tightStack = []112 113 /** @type {HtmlExtension} */114 const defaultHandlers = {115 enter: {116 blockQuote: onenterblockquote,117 codeFenced: onentercodefenced,118 codeFencedFenceInfo: buffer,119 codeFencedFenceMeta: buffer,120 codeIndented: onentercodeindented,121 codeText: onentercodetext,122 content: onentercontent,123 definition: onenterdefinition,124 definitionDestinationString: onenterdefinitiondestinationstring,125 definitionLabelString: buffer,126 definitionTitleString: buffer,127 emphasis: onenteremphasis,128 htmlFlow: onenterhtmlflow,129 htmlText: onenterhtml,130 image: onenterimage,131 label: buffer,132 link: onenterlink,133 listItemMarker: onenterlistitemmarker,134 listItemValue: onenterlistitemvalue,135 listOrdered: onenterlistordered,136 listUnordered: onenterlistunordered,137 paragraph: onenterparagraph,138 reference: buffer,139 resource: onenterresource,140 resourceDestinationString: onenterresourcedestinationstring,141 resourceTitleString: buffer,142 setextHeading: onentersetextheading,143 strong: onenterstrong144 },145 exit: {146 atxHeading: onexitatxheading,147 atxHeadingSequence: onexitatxheadingsequence,148 autolinkEmail: onexitautolinkemail,149 autolinkProtocol: onexitautolinkprotocol,150 blockQuote: onexitblockquote,151 characterEscapeValue: onexitdata,152 characterReferenceMarkerHexadecimal: onexitcharacterreferencemarker,153 characterReferenceMarkerNumeric: onexitcharacterreferencemarker,154 characterReferenceValue: onexitcharacterreferencevalue,155 codeFenced: onexitflowcode,156 codeFencedFence: onexitcodefencedfence,157 codeFencedFenceInfo: onexitcodefencedfenceinfo,158 codeFencedFenceMeta: onresumedrop,159 codeFlowValue: onexitcodeflowvalue,160 codeIndented: onexitflowcode,161 codeText: onexitcodetext,162 codeTextData: onexitdata,163 data: onexitdata,164 definition: onexitdefinition,165 definitionDestinationString: onexitdefinitiondestinationstring,166 definitionLabelString: onexitdefinitionlabelstring,167 definitionTitleString: onexitdefinitiontitlestring,168 emphasis: onexitemphasis,169 hardBreakEscape: onexithardbreak,170 hardBreakTrailing: onexithardbreak,171 htmlFlow: onexithtml,172 htmlFlowData: onexitdata,173 htmlText: onexithtml,174 htmlTextData: onexitdata,175 image: onexitmedia,176 label: onexitlabel,177 labelText: onexitlabeltext,178 lineEnding: onexitlineending,179 link: onexitmedia,180 listOrdered: onexitlistordered,181 listUnordered: onexitlistunordered,182 paragraph: onexitparagraph,183 reference: onresumedrop,184 referenceString: onexitreferencestring,185 resource: onresumedrop,186 resourceDestinationString: onexitresourcedestinationstring,187 resourceTitleString: onexitresourcetitlestring,188 setextHeading: onexitsetextheading,189 setextHeadingLineSequence: onexitsetextheadinglinesequence,190 setextHeadingText: onexitsetextheadingtext,191 strong: onexitstrong,192 thematicBreak: onexitthematicbreak193 }194 }195 196 /**197 * Combine the HTML extensions with the default handlers.198 * An HTML extension is an object whose fields are either `enter` or `exit`199 * (reflecting whether a token is entered or exited).200 * The values at such objects are names of tokens mapping to handlers.201 * Handlers are called, respectively when a token is opener or closed, with202 * that token, and a context as `this`.203 */204 const handlers = /** @type {NormalizedHtmlExtension} */ (205 combineHtmlExtensions([defaultHandlers, ...(settings.htmlExtensions || [])])206 )207 208 /**209 * Handlers do often need to keep track of some state.210 * That state is provided here as a key-value store (an object).211 *212 * @type {CompileData}213 */214 const data = {215 definitions,216 tightStack217 }218 219 /**220 * The context for handlers references a couple of useful functions.221 * In handlers from extensions, those can be accessed at `this`.222 * For the handlers here, they can be accessed directly.223 *224 * @type {Omit<CompileContext, 'sliceSerialize'>}225 */226 const context = {227 buffer,228 encode,229 getData,230 lineEndingIfNeeded,231 options: settings,232 raw,233 resume,234 setData,235 tag236 }237 238 /**239 * Generally, micromark copies line endings (`'\r'`, `'\n'`, `'\r\n'`) in the240 * markdown document over to the compiled HTML.241 * In some cases, such as `> a`, CommonMark requires that extra line endings242 * are added: `<blockquote>\n<p>a</p>\n</blockquote>`.243 * This variable hold the default line ending when given (or `undefined`),244 * and in the latter case will be updated to the first found line ending if245 * there is one.246 */247 let lineEndingStyle = settings.defaultLineEnding248 249 // Return the function that handles a slice of events.250 return compile251 252 /**253 * Deal w/ a slice of events.254 * Return either the empty string if there’s nothing of note to return, or the255 * result when done.256 *257 * @param {ReadonlyArray<Event>} events258 * @returns {string}259 */260 function compile(events) {261 let index = -1262 let start = 0263 /** @type {Array<number>} */264 const listStack = []265 // As definitions can come after references, we need to figure out the media266 // (urls and titles) defined by them before handling the references.267 // So, we do sort of what HTML does: put metadata at the start (in head), and268 // then put content after (`body`).269 /** @type {Array<Event>} */270 let head = []271 /** @type {Array<Event>} */272 let body = []273 274 while (++index < events.length) {275 // Figure out the line ending style used in the document.276 if (277 !lineEndingStyle &&278 (events[index][1].type === types.lineEnding ||279 events[index][1].type === types.lineEndingBlank)280 ) {281 lineEndingStyle = /** @type {LineEnding} */ (282 events[index][2].sliceSerialize(events[index][1])283 )284 }285 286 // Preprocess lists to infer whether the list is loose or not.287 if (288 events[index][1].type === types.listOrdered ||289 events[index][1].type === types.listUnordered290 ) {291 if (events[index][0] === 'enter') {292 listStack.push(index)293 } else {294 prepareList(events.slice(listStack.pop(), index))295 }296 }297 298 // Move definitions to the front.299 if (events[index][1].type === types.definition) {300 if (events[index][0] === 'enter') {301 body = push(body, events.slice(start, index))302 start = index303 } else {304 head = push(head, events.slice(start, index + 1))305 start = index + 1306 }307 }308 }309 310 head = push(head, body)311 head = push(head, events.slice(start))312 index = -1313 const result = head314 315 // Handle the start of the document, if defined.316 if (handlers.enter.null) {317 handlers.enter.null.call(context)318 }319 320 // Handle all events.321 while (++index < events.length) {322 const handles = handlers[result[index][0]]323 const kind = result[index][1].type324 const handle = handles[kind]325 326 if (hasOwnProperty.call(handles, kind) && handle) {327 handle.call(328 {sliceSerialize: result[index][2].sliceSerialize, ...context},329 result[index][1]330 )331 }332 }333 334 // Handle the end of the document, if defined.335 if (handlers.exit.null) {336 handlers.exit.null.call(context)337 }338 339 return buffers[0].join('')340 }341 342 /**343 * Figure out whether lists are loose or not.344 *345 * @param {ReadonlyArray<Event>} slice346 * @returns {undefined}347 */348 function prepareList(slice) {349 const length = slice.length350 let index = 0 // Skip open.351 let containerBalance = 0352 let loose = false353 /** @type {boolean | undefined} */354 let atMarker355 356 while (++index < length) {357 const event = slice[index]358 359 if (event[1]._container) {360 atMarker = undefined361 362 if (event[0] === 'enter') {363 containerBalance++364 } else {365 containerBalance--366 }367 } else368 switch (event[1].type) {369 case types.listItemPrefix: {370 if (event[0] === 'exit') {371 atMarker = true372 }373 374 break375 }376 377 case types.linePrefix: {378 // Ignore379 380 break381 }382 383 case types.lineEndingBlank: {384 if (event[0] === 'enter' && !containerBalance) {385 if (atMarker) {386 atMarker = undefined387 } else {388 loose = true389 }390 }391 392 break393 }394 395 default: {396 atMarker = undefined397 }398 }399 }400 401 slice[0][1]._loose = loose402 }403 404 /**405 * @type {CompileContext['setData']}406 */407 function setData(key, value) {408 // @ts-expect-error: assume `value` is omitted (`undefined` is passed) only409 // if allowed.410 data[key] = value411 }412 413 /**414 * @type {CompileContext['getData']}415 */416 function getData(key) {417 return data[key]418 }419 420 /** @type {CompileContext['buffer']} */421 function buffer() {422 buffers.push([])423 }424 425 /** @type {CompileContext['resume']} */426 function resume() {427 const buf = buffers.pop()428 assert(buf !== undefined, 'Cannot resume w/o buffer')429 return buf.join('')430 }431 432 /** @type {CompileContext['tag']} */433 function tag(value) {434 if (!tags) return435 setData('lastWasTag', true)436 buffers[buffers.length - 1].push(value)437 }438 439 /** @type {CompileContext['raw']} */440 function raw(value) {441 setData('lastWasTag')442 buffers[buffers.length - 1].push(value)443 }444 445 /**446 * Output an extra line ending.447 *448 * @returns {undefined}449 */450 function lineEnding() {451 raw(lineEndingStyle || '\n')452 }453 454 /** @type {CompileContext['lineEndingIfNeeded']} */455 function lineEndingIfNeeded() {456 const buffer = buffers[buffers.length - 1]457 const slice = buffer[buffer.length - 1]458 const previous = slice ? slice.charCodeAt(slice.length - 1) : codes.eof459 460 if (461 previous === codes.lf ||462 previous === codes.cr ||463 previous === codes.eof464 ) {465 return466 }467 468 lineEnding()469 }470 471 /** @type {CompileContext['encode']} */472 function encode(value) {473 return getData('ignoreEncode') ? value : _encode(value)474 }475 476 //477 // Handlers.478 //479 480 /**481 * @returns {undefined}482 */483 function onresumedrop() {484 resume()485 }486 487 /**488 * @this {CompileContext}489 * @type {Handle}490 */491 function onenterlistordered(token) {492 tightStack.push(!token._loose)493 lineEndingIfNeeded()494 tag('<ol')495 setData('expectFirstItem', true)496 }497 498 /**499 * @this {CompileContext}500 * @type {Handle}501 */502 function onenterlistunordered(token) {503 tightStack.push(!token._loose)504 lineEndingIfNeeded()505 tag('<ul')506 setData('expectFirstItem', true)507 }508 509 /**510 * @this {CompileContext}511 * @type {Handle}512 */513 function onenterlistitemvalue(token) {514 if (getData('expectFirstItem')) {515 const value = Number.parseInt(516 this.sliceSerialize(token),517 constants.numericBaseDecimal518 )519 520 if (value !== 1) {521 tag(' start="' + encode(String(value)) + '"')522 }523 }524 }525 526 /**527 * @returns {undefined}528 */529 function onenterlistitemmarker() {530 if (getData('expectFirstItem')) {531 tag('>')532 } else {533 onexitlistitem()534 }535 536 lineEndingIfNeeded()537 tag('<li>')538 setData('expectFirstItem')539 // “Hack” to prevent a line ending from showing up if the item is empty.540 setData('lastWasTag')541 }542 543 /**544 * @returns {undefined}545 */546 function onexitlistordered() {547 onexitlistitem()548 tightStack.pop()549 lineEnding()550 tag('</ol>')551 }552 553 /**554 * @returns {undefined}555 */556 function onexitlistunordered() {557 onexitlistitem()558 tightStack.pop()559 lineEnding()560 tag('</ul>')561 }562 563 /**564 * @returns {undefined}565 */566 function onexitlistitem() {567 if (getData('lastWasTag') && !getData('slurpAllLineEndings')) {568 lineEndingIfNeeded()569 }570 571 tag('</li>')572 setData('slurpAllLineEndings')573 }574 575 /**576 * @this {CompileContext}577 * @type {Handle}578 */579 function onenterblockquote() {580 tightStack.push(false)581 lineEndingIfNeeded()582 tag('<blockquote>')583 }584 585 /**586 * @this {CompileContext}587 * @type {Handle}588 */589 function onexitblockquote() {590 tightStack.pop()591 lineEndingIfNeeded()592 tag('</blockquote>')593 setData('slurpAllLineEndings')594 }595 596 /**597 * @this {CompileContext}598 * @type {Handle}599 */600 function onenterparagraph() {601 if (!tightStack[tightStack.length - 1]) {602 lineEndingIfNeeded()603 tag('<p>')604 }605 606 setData('slurpAllLineEndings')607 }608 609 /**610 * @this {CompileContext}611 * @type {Handle}612 */613 function onexitparagraph() {614 if (tightStack[tightStack.length - 1]) {615 setData('slurpAllLineEndings', true)616 } else {617 tag('</p>')618 }619 }620 621 /**622 * @this {CompileContext}623 * @type {Handle}624 */625 function onentercodefenced() {626 lineEndingIfNeeded()627 tag('<pre><code')628 setData('fencesCount', 0)629 }630 631 /**632 * @this {CompileContext}633 * @type {Handle}634 */635 function onexitcodefencedfenceinfo() {636 const value = resume()637 tag(' class="language-' + value + '"')638 }639 640 /**641 * @this {CompileContext}642 * @type {Handle}643 */644 function onexitcodefencedfence() {645 const count = getData('fencesCount') || 0646 647 if (!count) {648 tag('>')649 setData('slurpOneLineEnding', true)650 }651 652 setData('fencesCount', count + 1)653 }654 655 /**656 * @this {CompileContext}657 * @type {Handle}658 */659 function onentercodeindented() {660 lineEndingIfNeeded()661 tag('<pre><code>')662 }663 664 /**665 * @this {CompileContext}666 * @type {Handle}667 */668 function onexitflowcode() {669 const count = getData('fencesCount')670 671 // One special case is if we are inside a container, and the fenced code was672 // not closed (meaning it runs to the end).673 // In that case, the following line ending, is considered *outside* the674 // fenced code and block quote by micromark, but CM wants to treat that675 // ending as part of the code.676 if (677 count !== undefined &&678 count < 2 &&679 data.tightStack.length > 0 &&680 !getData('lastWasTag')681 ) {682 lineEnding()683 }684 685 // But in most cases, it’s simpler: when we’ve seen some data, emit an extra686 // line ending when needed.687 if (getData('flowCodeSeenData')) {688 lineEndingIfNeeded()689 }690 691 tag('</code></pre>')692 if (count !== undefined && count < 2) lineEndingIfNeeded()693 setData('flowCodeSeenData')694 setData('fencesCount')695 setData('slurpOneLineEnding')696 }697 698 /**699 * @this {CompileContext}700 * @type {Handle}701 */702 function onenterimage() {703 mediaStack.push({image: true})704 tags = undefined // Disallow tags.705 }706 707 /**708 * @this {CompileContext}709 * @type {Handle}710 */711 function onenterlink() {712 mediaStack.push({})713 }714 715 /**716 * @this {CompileContext}717 * @type {Handle}718 */719 function onexitlabeltext(token) {720 mediaStack[mediaStack.length - 1].labelId = this.sliceSerialize(token)721 }722 723 /**724 * @this {CompileContext}725 * @type {Handle}726 */727 function onexitlabel() {728 mediaStack[mediaStack.length - 1].label = resume()729 }730 731 /**732 * @this {CompileContext}733 * @type {Handle}734 */735 function onexitreferencestring(token) {736 mediaStack[mediaStack.length - 1].referenceId = this.sliceSerialize(token)737 }738 739 /**740 * @this {CompileContext}741 * @type {Handle}742 */743 function onenterresource() {744 buffer() // We can have line endings in the resource, ignore them.745 mediaStack[mediaStack.length - 1].destination = ''746 }747 748 /**749 * @this {CompileContext}750 * @type {Handle}751 */752 function onenterresourcedestinationstring() {753 buffer()754 // Ignore encoding the result, as we’ll first percent encode the url and755 // encode manually after.756 setData('ignoreEncode', true)757 }758 759 /**760 * @this {CompileContext}761 * @type {Handle}762 */763 function onexitresourcedestinationstring() {764 mediaStack[mediaStack.length - 1].destination = resume()765 setData('ignoreEncode')766 }767 768 /**769 * @this {CompileContext}770 * @type {Handle}771 */772 function onexitresourcetitlestring() {773 mediaStack[mediaStack.length - 1].title = resume()774 }775 776 /**777 * @this {CompileContext}778 * @type {Handle}779 */780 function onexitmedia() {781 let index = mediaStack.length - 1 // Skip current.782 const media = mediaStack[index]783 const id = media.referenceId || media.labelId784 assert(id !== undefined, 'media should have `referenceId` or `labelId`')785 assert(media.label !== undefined, 'media should have `label`')786 const context =787 media.destination === undefined788 ? definitions[normalizeIdentifier(id)]789 : media790 791 tags = true792 793 while (index--) {794 if (mediaStack[index].image) {795 tags = undefined796 break797 }798 }799 800 if (media.image) {801 tag(802 '<img src="' +803 sanitizeUri(804 context.destination,805 settings.allowDangerousProtocol ? undefined : protocolSource806 ) +807 '" alt="'808 )809 raw(media.label)810 tag('"')811 } else {812 tag(813 '<a href="' +814 sanitizeUri(815 context.destination,816 settings.allowDangerousProtocol ? undefined : protocolHref817 ) +818 '"'819 )820 }821 822 tag(context.title ? ' title="' + context.title + '"' : '')823 824 if (media.image) {825 tag(' />')826 } else {827 tag('>')828 raw(media.label)829 tag('</a>')830 }831 832 mediaStack.pop()833 }834 835 /**836 * @this {CompileContext}837 * @type {Handle}838 */839 function onenterdefinition() {840 buffer()841 mediaStack.push({})842 }843 844 /**845 * @this {CompileContext}846 * @type {Handle}847 */848 function onexitdefinitionlabelstring(token) {849 // Discard label, use the source content instead.850 resume()851 mediaStack[mediaStack.length - 1].labelId = this.sliceSerialize(token)852 }853 854 /**855 * @this {CompileContext}856 * @type {Handle}857 */858 function onenterdefinitiondestinationstring() {859 buffer()860 setData('ignoreEncode', true)861 }862 863 /**864 * @this {CompileContext}865 * @type {Handle}866 */867 function onexitdefinitiondestinationstring() {868 mediaStack[mediaStack.length - 1].destination = resume()869 setData('ignoreEncode')870 }871 872 /**873 * @this {CompileContext}874 * @type {Handle}875 */876 function onexitdefinitiontitlestring() {877 mediaStack[mediaStack.length - 1].title = resume()878 }879 880 /**881 * @this {CompileContext}882 * @type {Handle}883 */884 function onexitdefinition() {885 const media = mediaStack[mediaStack.length - 1]886 assert(media.labelId !== undefined, 'media should have `labelId`')887 const id = normalizeIdentifier(media.labelId)888 889 resume()890 891 if (!hasOwnProperty.call(definitions, id)) {892 definitions[id] = mediaStack[mediaStack.length - 1]893 }894 895 mediaStack.pop()896 }897 898 /**899 * @this {CompileContext}900 * @type {Handle}901 */902 function onentercontent() {903 setData('slurpAllLineEndings', true)904 }905 906 /**907 * @this {CompileContext}908 * @type {Handle}909 */910 function onexitatxheadingsequence(token) {911 // Exit for further sequences.912 if (getData('headingRank')) return913 setData('headingRank', this.sliceSerialize(token).length)914 lineEndingIfNeeded()915 tag('<h' + getData('headingRank') + '>')916 }917 918 /**919 * @this {CompileContext}920 * @type {Handle}921 */922 function onentersetextheading() {923 buffer()924 setData('slurpAllLineEndings')925 }926 927 /**928 * @this {CompileContext}929 * @type {Handle}930 */931 function onexitsetextheadingtext() {932 setData('slurpAllLineEndings', true)933 }934 935 /**936 * @this {CompileContext}937 * @type {Handle}938 */939 function onexitatxheading() {940 tag('</h' + getData('headingRank') + '>')941 setData('headingRank')942 }943 944 /**945 * @this {CompileContext}946 * @type {Handle}947 */948 function onexitsetextheadinglinesequence(token) {949 setData(950 'headingRank',951 this.sliceSerialize(token).charCodeAt(0) === codes.equalsTo ? 1 : 2952 )953 }954 955 /**956 * @this {CompileContext}957 * @type {Handle}958 */959 function onexitsetextheading() {960 const value = resume()961 lineEndingIfNeeded()962 tag('<h' + getData('headingRank') + '>')963 raw(value)964 tag('</h' + getData('headingRank') + '>')965 setData('slurpAllLineEndings')966 setData('headingRank')967 }968 969 /**970 * @this {CompileContext}971 * @type {Handle}972 */973 function onexitdata(token) {974 raw(encode(this.sliceSerialize(token)))975 }976 977 /**978 * @this {CompileContext}979 * @type {Handle}980 */981 function onexitlineending(token) {982 if (getData('slurpAllLineEndings')) {983 return984 }985 986 if (getData('slurpOneLineEnding')) {987 setData('slurpOneLineEnding')988 return989 }990 991 if (getData('inCodeText')) {992 raw(' ')993 return994 }995 996 raw(encode(this.sliceSerialize(token)))997 }998 999 /**1000 * @this {CompileContext}1001 * @type {Handle}1002 */1003 function onexitcodeflowvalue(token) {1004 raw(encode(this.sliceSerialize(token)))1005 setData('flowCodeSeenData', true)1006 }1007 1008 /**1009 * @this {CompileContext}1010 * @type {Handle}1011 */1012 function onexithardbreak() {1013 tag('<br />')1014 }1015 1016 /**1017 * @returns {undefined}1018 */1019 function onenterhtmlflow() {1020 lineEndingIfNeeded()1021 onenterhtml()1022 }1023 1024 /**1025 * @returns {undefined}1026 */1027 function onexithtml() {1028 setData('ignoreEncode')1029 }1030 1031 /**1032 * @returns {undefined}1033 */1034 function onenterhtml() {1035 if (settings.allowDangerousHtml) {1036 setData('ignoreEncode', true)1037 }1038 }1039 1040 /**1041 * @returns {undefined}1042 */1043 function onenteremphasis() {1044 tag('<em>')1045 }1046 1047 /**1048 * @returns {undefined}1049 */1050 function onenterstrong() {1051 tag('<strong>')1052 }1053 1054 /**1055 * @returns {undefined}1056 */1057 function onentercodetext() {1058 setData('inCodeText', true)1059 tag('<code>')1060 }1061 1062 /**1063 * @returns {undefined}1064 */1065 function onexitcodetext() {1066 setData('inCodeText')1067 tag('</code>')1068 }1069 1070 /**1071 * @returns {undefined}1072 */1073 function onexitemphasis() {1074 tag('</em>')1075 }1076 1077 /**1078 * @returns {undefined}1079 */1080 function onexitstrong() {1081 tag('</strong>')1082 }1083 1084 /**1085 * @returns {undefined}1086 */1087 function onexitthematicbreak() {1088 lineEndingIfNeeded()1089 tag('<hr />')1090 }1091 1092 /**1093 * @this {CompileContext}1094 * @param {Token} token1095 * @returns {undefined}1096 */1097 function onexitcharacterreferencemarker(token) {1098 setData('characterReferenceType', token.type)1099 }1100 1101 /**1102 * @this {CompileContext}1103 * @type {Handle}1104 */1105 function onexitcharacterreferencevalue(token) {1106 const value = this.sliceSerialize(token)1107 const decoded = getData('characterReferenceType')1108 ? decodeNumericCharacterReference(1109 value,1110 getData('characterReferenceType') ===1111 types.characterReferenceMarkerNumeric1112 ? constants.numericBaseDecimal1113 : constants.numericBaseHexadecimal1114 )1115 : decodeNamedCharacterReference(value)1116 1117 // `decodeNamedCharacterReference` can return `false` for invalid named1118 // character references,1119 // but everything we’ve tokenized is valid.1120 raw(encode(/** @type {string} */ (decoded)))1121 setData('characterReferenceType')1122 }1123 1124 /**1125 * @this {CompileContext}1126 * @type {Handle}1127 */1128 function onexitautolinkprotocol(token) {1129 const uri = this.sliceSerialize(token)1130 tag(1131 '<a href="' +1132 sanitizeUri(1133 uri,1134 settings.allowDangerousProtocol ? undefined : protocolHref1135 ) +1136 '">'1137 )1138 raw(encode(uri))1139 tag('</a>')1140 }1141 1142 /**1143 * @this {CompileContext}1144 * @type {Handle}1145 */1146 function onexitautolinkemail(token) {1147 const uri = this.sliceSerialize(token)1148 tag('<a href="' + sanitizeUri('mailto:' + uri) + '">')1149 raw(encode(uri))1150 tag('</a>')1151 }1152}1153 