UNPKG

micromark-extension-taggable

Version:
152 lines (146 loc) 4.63 kB
'use strict'; var micromarkUtilSymbol = require('micromark-util-symbol'); var micromarkUtilCharacter = require('micromark-util-character'); const defaultOptions = { classes: ["micromark-taggable"], rules: [ { marker: "#", type: "tag", toUrl: (val) => `/tags/${val}`, classes: ["tag"], }, { marker: "@", type: "mention", toUrl: (val) => `/users/${val}`, classes: ["mention"], }, ], allowEmail: false, }; function syntax(opts = defaultOptions) { if (opts.allowEmail == undefined) opts.allowEmail = false; const rules = opts.rules; let valueCursor = 0; const markers = []; const typeMap = new Map(); const allowEmail = opts.allowEmail; for (const i of rules) { markers.push(i.marker); typeMap.set(i.marker, i.type); } function tokenize(effects, ok, nok) { return start; function start(code) { if (!code || micromarkUtilCharacter.markdownLineEnding(code) || code === micromarkUtilSymbol.codes.eof) { return nok(code); } effects.enter("taggable"); effects.enter("taggableMarker"); return consumeMarker(code); } function consumeMarker(code) { if (!code || !typeMap.has(String.fromCodePoint(code))) { return nok(code); } effects.consume(code); effects.exit("taggableMarker"); effects.enter("taggableValue"); return consumeValue; } function consumeValue(code) { if (!code || micromarkUtilCharacter.markdownLineEnding(code) || code === micromarkUtilSymbol.codes.eof || !(allowEmail ? /[\p{L}\p{N}\p{Pd}\p{Pc}\p{M}@.]/u.test(String.fromCodePoint(code)) : /[\p{L}\p{N}\p{Pd}\p{Pc}\p{M}]/u.test(String.fromCodePoint(code)))) { if (valueCursor < 1) { return nok(code); } else { effects.exit("taggableValue"); effects.exit("taggable"); return ok(code); } } valueCursor++; effects.consume(code); return consumeValue; } } // Marker-hooks const text = {}; for (const i of markers) { text[i.codePointAt(0)] = { tokenize: tokenize }; } return { text }; } function html(opts = defaultOptions) { opts = opts ? opts : defaultOptions; if (opts.allowEmail == undefined) opts.allowEmail = false; const markers = []; const typeMap = new Map(); const urlResolverMap = new Map(); const cls = opts.classes ? opts.classes : ["micromark-taggable"]; const clsMap = new Map(); for (const i of opts.rules) { markers.push(i.marker); typeMap.set(i.marker, i.type); urlResolverMap.set(i.marker, i.toUrl); if (i.classes) { clsMap.set(i.marker, i.classes); } } function enterTaggable() { this.setData("taggableStack", { type: "taggable", value: "", data: { marker: "", type: "", url: "", }, }); } function exitTaggableMarker(token) { const marker = this.sliceSerialize(token); const current = this.getData("taggableStack"); current.data.marker = marker; } function exitTaggableValue(token) { const value = this.sliceSerialize(token); const current = this.getData("taggableStack"); current.value = value; } function exitTaggable() { const taggable = this.getData("taggableStack"); const marker = taggable.data.marker; const value = taggable.value; this.tag('<a href="' + urlResolverMap.get(marker)(value) + '" class="' + cls.join(" ") + (clsMap.get(marker) ? " " + clsMap.get(marker).join(" ") : "") + '">'); this.raw(marker + value); this.tag("</a>"); } return { enter: { taggable: enterTaggable, }, exit: { taggableMarker: exitTaggableMarker, taggableValue: exitTaggableValue, taggable: exitTaggable, }, }; } exports.defaultOptions = defaultOptions; exports.html = html; exports.syntax = syntax; //# sourceMappingURL=index.cjs.js.map