|
|
@@ -578,9 +578,6 @@ class MDState {
|
|
578
|
578
|
/** @type {MDState|null} */
|
|
579
|
579
|
#parent = null;
|
|
580
|
580
|
|
|
581
|
|
- /** @type {MDConfig} */
|
|
582
|
|
- config;
|
|
583
|
|
-
|
|
584
|
581
|
/**
|
|
585
|
582
|
* Array of `MDReader`s sorted by block reading priority.
|
|
586
|
583
|
* @type {MDReader[]}
|
|
|
@@ -600,6 +597,15 @@ class MDState {
|
|
600
|
597
|
readersBySubstitutePriority = [];
|
|
601
|
598
|
|
|
602
|
599
|
/**
|
|
|
600
|
+ * Prefix to include in any generated `id` attributes on HTML elements.
|
|
|
601
|
+ * Useful for keeping elements unique in multiple parsed documents in the
|
|
|
602
|
+ * same HTML page.
|
|
|
603
|
+ *
|
|
|
604
|
+ * @type {string}
|
|
|
605
|
+ */
|
|
|
606
|
+ elementIdPrefix = '';
|
|
|
607
|
+
|
|
|
608
|
+ /**
|
|
603
|
609
|
* Mapping of reference symbols to URLs.
|
|
604
|
610
|
* @type {object}
|
|
605
|
611
|
*/
|
|
|
@@ -618,23 +624,9 @@ class MDState {
|
|
618
|
624
|
|
|
619
|
625
|
/**
|
|
620
|
626
|
* @param {string[]} lines - lines of markdown text
|
|
621
|
|
- * @param {MDConfig} config
|
|
622
|
|
- * @param {MDReader[]} readersByBlockPriority
|
|
623
|
|
- * @param {MDReader[]} readersByTokenPriority
|
|
624
|
|
- * @param {Array} readersBySubstitutePriority - tuple arrays of priority and MDReader
|
|
625
|
|
- */
|
|
626
|
|
- constructor(lines,
|
|
627
|
|
- config=null,
|
|
628
|
|
- readersByBlockPriority=null,
|
|
629
|
|
- readersByTokenPriority=null,
|
|
630
|
|
- readersBySubstitutePriority=null,
|
|
631
|
|
- tagFilter=null) {
|
|
|
627
|
+ */
|
|
|
628
|
+ constructor(lines) {
|
|
632
|
629
|
this.#lines = lines;
|
|
633
|
|
- this.config = config;
|
|
634
|
|
- this.readersByBlockPriority = readersByBlockPriority
|
|
635
|
|
- this.readersByTokenPriority = readersByTokenPriority
|
|
636
|
|
- this.readersBySubstitutePriority = readersBySubstitutePriority
|
|
637
|
|
- this.tagFilter = tagFilter;
|
|
638
|
630
|
}
|
|
639
|
631
|
|
|
640
|
632
|
/**
|
|
|
@@ -647,7 +639,6 @@ class MDState {
|
|
647
|
639
|
copy(lines) {
|
|
648
|
640
|
let cp = new MDState(lines);
|
|
649
|
641
|
cp.#parent = this;
|
|
650
|
|
- cp.config = this.config;
|
|
651
|
642
|
return cp;
|
|
652
|
643
|
}
|
|
653
|
644
|
|
|
|
@@ -2034,14 +2025,21 @@ class MDStrongReader extends MDSimplePairInlineReader {
|
|
2034
|
2025
|
}
|
|
2035
|
2026
|
|
|
2036
|
2027
|
class MDStrikethroughReader extends MDSimplePairInlineReader {
|
|
|
2028
|
+ /** @type {boolean} */
|
|
|
2029
|
+ singleTildeEnabled = true;
|
|
|
2030
|
+ /** @type {boolean} */
|
|
|
2031
|
+ doubleTildeEnabled = true;
|
|
|
2032
|
+
|
|
2037
|
2033
|
readToken(state, line) {
|
|
2038
|
2034
|
if (line.startsWith('~')) return new MDToken('~', MDTokenType.Tilde);
|
|
2039
|
2035
|
return null;
|
|
2040
|
2036
|
}
|
|
2041
|
2037
|
|
|
2042
|
2038
|
substituteTokens(state, pass, tokens) {
|
|
2043
|
|
- if (this.attemptPair(state, pass, tokens, MDStrikethroughNode, MDTokenType.Tilde, 2)) return true;
|
|
2044
|
|
- if (state.config.strikethroughSingleTildeEnabled) {
|
|
|
2039
|
+ if (this.singleTildeEnabled) {
|
|
|
2040
|
+ if (this.attemptPair(state, pass, tokens, MDStrikethroughNode, MDTokenType.Tilde, 2)) return true;
|
|
|
2041
|
+ }
|
|
|
2042
|
+ if (this.doubleTildeEnabled) {
|
|
2045
|
2043
|
if (this.attemptPair(state, pass, tokens, MDStrikethroughNode, MDTokenType.Tilde)) return true;
|
|
2046
|
2044
|
}
|
|
2047
|
2045
|
return false;
|
|
|
@@ -2266,11 +2264,6 @@ class MDSubscriptReader extends MDSimplePairInlineReader {
|
|
2266
|
2264
|
return null;
|
|
2267
|
2265
|
}
|
|
2268
|
2266
|
|
|
2269
|
|
- preProcess(state) {
|
|
2270
|
|
- // Causes a conflict
|
|
2271
|
|
- state.config.strikethroughSingleTildeEnabled = false;
|
|
2272
|
|
- }
|
|
2273
|
|
-
|
|
2274
|
2267
|
substituteTokens(state, pass, tokens) {
|
|
2275
|
2268
|
return this.attemptPair(state, pass, tokens, MDSubscriptNode, MDTokenType.Tilde);
|
|
2276
|
2269
|
}
|
|
|
@@ -2747,6 +2740,17 @@ class MDDefinitionListDefinitionNode extends MDBlockNode {
|
|
2747
|
2740
|
}
|
|
2748
|
2741
|
|
|
2749
|
2742
|
class MDFootnoteListNode extends MDBlockNode {
|
|
|
2743
|
+ /**
|
|
|
2744
|
+ * @param {MDState} state
|
|
|
2745
|
+ * @param {string} symbol
|
|
|
2746
|
+ * @return {number}
|
|
|
2747
|
+ */
|
|
|
2748
|
+ #footnoteId(state, symbol) {
|
|
|
2749
|
+ const lookup = state.root['footnoteIds'];
|
|
|
2750
|
+ if (!lookup) return null;
|
|
|
2751
|
+ return lookup[symbol] ?? null;
|
|
|
2752
|
+ }
|
|
|
2753
|
+
|
|
2750
|
2754
|
toHTML(state) {
|
|
2751
|
2755
|
const footnotes = state.footnotes;
|
|
2752
|
2756
|
var symbolOrder = Object.keys(footnotes);
|
|
|
@@ -2759,12 +2763,13 @@ class MDFootnoteListNode extends MDBlockNode {
|
|
2759
|
2763
|
/** @type {MDNode[]} */
|
|
2760
|
2764
|
let content = footnotes[symbol];
|
|
2761
|
2765
|
if (!content) continue;
|
|
|
2766
|
+ let footnoteId = this.#footnoteId(state, symbol);
|
|
2762
|
2767
|
const contentHTML = MDNode.toHTML(content, state);
|
|
2763
|
|
- html += `<li value="${symbol}" id="footnote_${symbol}">${contentHTML}`;
|
|
|
2768
|
+ html += `<li value="${symbol}" id="${state.root.elementIdPrefix}footnote_${footnoteId}">${contentHTML}`;
|
|
2764
|
2769
|
const uniques = footnoteUniques[symbol];
|
|
2765
|
2770
|
if (uniques) {
|
|
2766
|
2771
|
for (const unique of uniques) {
|
|
2767
|
|
- html += ` <a href="#footnoteref_${unique}" class="footnote-backref">↩︎</a>`;
|
|
|
2772
|
+ html += ` <a href="#${state.root.elementIdPrefix}footnoteref_${unique}" class="footnote-backref">↩︎</a>`;
|
|
2768
|
2773
|
}
|
|
2769
|
2774
|
}
|
|
2770
|
2775
|
html += `</li>\n`;
|
|
|
@@ -2908,7 +2913,8 @@ class MDFootnoteNode extends MDInlineNode {
|
|
2908
|
2913
|
|
|
2909
|
2914
|
toHTML(state) {
|
|
2910
|
2915
|
if (this.differentiator !== null) {
|
|
2911
|
|
- return `<sup id="footnoteref_${this.occurrenceId}"${this._htmlAttributes()}><a href="#footnote_${this.footnoteId}">${MDUtils.escapeHTML(this.displaySymbol ?? this.symbol)}</a></sup>`;
|
|
|
2916
|
+ return `<sup id="${state.root.elementIdPrefix}footnoteref_${this.occurrenceId}"${this._htmlAttributes()}>` +
|
|
|
2917
|
+ `<a href="#${state.root.elementIdPrefix}footnote_${this.footnoteId}">${MDUtils.escapeHTML(this.displaySymbol ?? this.symbol)}</a></sup>`;
|
|
2912
|
2918
|
}
|
|
2913
|
2919
|
return `<!--FNREF:{${this.symbol}}-->`;
|
|
2914
|
2920
|
}
|
|
|
@@ -3747,10 +3753,6 @@ class MDTagModifier {
|
|
3747
|
3753
|
}
|
|
3748
|
3754
|
}
|
|
3749
|
3755
|
|
|
3750
|
|
-class MDConfig {
|
|
3751
|
|
- strikethroughSingleTildeEnabled = true;
|
|
3752
|
|
-}
|
|
3753
|
|
-
|
|
3754
|
3756
|
class Markdown {
|
|
3755
|
3757
|
/**
|
|
3756
|
3758
|
* Set of standard readers.
|
|
|
@@ -3808,11 +3810,6 @@ class Markdown {
|
|
3808
|
3810
|
static completeParser = new Markdown(this.allReaders);
|
|
3809
|
3811
|
|
|
3810
|
3812
|
/**
|
|
3811
|
|
- * @type {MDConfig}
|
|
3812
|
|
- */
|
|
3813
|
|
- config;
|
|
3814
|
|
-
|
|
3815
|
|
- /**
|
|
3816
|
3813
|
* Filter for what non-markdown HTML is permitted. HTML generated as a
|
|
3817
|
3814
|
* result of markdown is unaffected.
|
|
3818
|
3815
|
*/
|
|
|
@@ -3831,11 +3828,9 @@ class Markdown {
|
|
3831
|
3828
|
* Creates a Markdown parser with the given syntax readers.
|
|
3832
|
3829
|
*
|
|
3833
|
3830
|
* @param {MDReader[]} readers
|
|
3834
|
|
- * @param {MDConfig} config
|
|
3835
|
3831
|
*/
|
|
3836
|
|
- constructor(readers=Markdown.allReaders, config=new MDConfig()) {
|
|
|
3832
|
+ constructor(readers=Markdown.allReaders) {
|
|
3837
|
3833
|
this.#readers = readers;
|
|
3838
|
|
- this.config = config;
|
|
3839
|
3834
|
this.#readersByBlockPriority = MDReader.sortReaderForBlocks(readers);
|
|
3840
|
3835
|
this.#readersByTokenPriority = MDReader.sortReadersForTokenizing(readers);
|
|
3841
|
3836
|
this.#readersBySubstitutePriority = MDReader.sortReadersForSubstitution(readers);
|
|
|
@@ -3844,17 +3839,20 @@ class Markdown {
|
|
3844
|
3839
|
/**
|
|
3845
|
3840
|
* Converts a markdown string to an HTML string.
|
|
3846
|
3841
|
*
|
|
3847
|
|
- * @param {string} markdown
|
|
|
3842
|
+ * @param {string} markdown
|
|
|
3843
|
+ * @param {string} elementIdPrefix - Optional prefix for generated element
|
|
|
3844
|
+ * `id`s and links to them. For differentiating multiple markdown docs in
|
|
|
3845
|
+ * the same HTML page.
|
|
3848
|
3846
|
* @returns {string} HTML
|
|
3849
|
3847
|
*/
|
|
3850
|
|
- toHTML(markdown) {
|
|
|
3848
|
+ toHTML(markdown, elementIdPrefix='') {
|
|
3851
|
3849
|
const lines = markdown.split(/(?:\n|\r|\r\n)/);
|
|
3852
|
|
- const state = new MDState(lines,
|
|
3853
|
|
- this.config,
|
|
3854
|
|
- this.#readersByBlockPriority,
|
|
3855
|
|
- this.#readersByTokenPriority,
|
|
3856
|
|
- this.#readersBySubstitutePriority,
|
|
3857
|
|
- this.tagFilter);
|
|
|
3850
|
+ const state = new MDState(lines);
|
|
|
3851
|
+ state.readersByBlockPriority = this.#readersByBlockPriority;
|
|
|
3852
|
+ state.readersByTokenPriority = this.#readersByTokenPriority
|
|
|
3853
|
+ state.readersBySubstitutePriority = this.#readersBySubstitutePriority
|
|
|
3854
|
+ state.tagFilter = this.tagFilter;
|
|
|
3855
|
+ state.elementIdPrefix = elementIdPrefix;
|
|
3858
|
3856
|
for (const reader of this.#readers) {
|
|
3859
|
3857
|
reader.preProcess(state);
|
|
3860
|
3858
|
}
|