Skip to content

Commit

Permalink
Refactor to use @imports
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Jul 5, 2024
1 parent f798cee commit 764bd0c
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 143 deletions.
164 changes: 147 additions & 17 deletions dev/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,153 @@
export {gfmFootnoteHtml, defaultBackLabel} from './lib/html.js'
export {gfmFootnote} from './lib/syntax.js'
export {
gfmFootnoteHtml,
defaultBackLabel,
type BackLabelTemplate,
type Options as HtmlOptions
} from './lib/html.js'

/**
* Generate a back label dynamically.
*
* For the following markdown:
*
* ```markdown
* Alpha[^micromark], bravo[^micromark], and charlie[^remark].
*
* [^remark]: things about remark
* [^micromark]: things about micromark
* ```
*
* This function will be called with:
*
* * `0` and `0` for the backreference from `things about micromark` to
* `alpha`, as it is the first used definition, and the first call to it
* * `0` and `1` for the backreference from `things about micromark` to
* `bravo`, as it is the first used definition, and the second call to it
* * `1` and `0` for the backreference from `things about remark` to
* `charlie`, as it is the second used definition
*
* @param referenceIndex
* Index of the definition in the order that they are first referenced,
* 0-indexed.
* @param rereferenceIndex
* Index of calls to the same definition, 0-indexed.
* @returns
* Back label to use when linking back from definitions to their reference.
*/
export type BackLabelTemplate = (
referenceIndex: number,
rereferenceIndex: number
) => string

/**
* Configuration.
*/
export interface HtmlOptions {
/**
* Prefix to use before the `id` attribute on footnotes to prevent them from
* *clobbering* (default: `'user-content-'`).
*
* Pass `''` for trusted markdown and when you are careful with
* polyfilling.
* You could pass a different prefix.
*
* DOM clobbering is this:
*
* ```html
* <p id="x"></p>
* <script>alert(x) // `x` now refers to the `p#x` DOM element</script>
* ```
*
* The above example shows that elements are made available by browsers, by
* their ID, on the `window` object.
* This is a security risk because you might be expecting some other variable
* at that place.
* It can also break polyfills.
* Using a prefix solves these problems.
*/
clobberPrefix?: string | null | undefined
/**
* Textual label to use for the footnotes section (default: `'Footnotes'`).
*
* Change it when the markdown is not in English.
*
* This label is typically hidden visually (assuming a `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass different attributes with the `labelAttributes` option.
*/
label?: string | null | undefined
/**
* Attributes to use on the footnote label (default: `'class="sr-only"'`).
*
* Change it to show the label and add other attributes.
*
* This label is typically hidden visually (assuming an `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass an empty string.
* You can also add different attributes.
*
* > 👉 **Note**: `id="footnote-label"` is always added, because footnote
* > calls use it with `aria-describedby` to provide an accessible label.
*/
labelAttributes?: string | null | undefined
/**
* HTML tag name to use for the footnote label element (default: `'h2'`).
*
* Change it to match your document structure.
*
* This label is typically hidden visually (assuming a `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass different attributes with the `labelAttributes` option.
*/
labelTagName?: string | null | undefined
/**
* Textual label to describe the backreference back to references (default:
* `defaultBackLabel`).
*
* The default value is:
*
* ```js
* function defaultBackLabel(referenceIndex, rereferenceIndex) {
* return (
* 'Back to reference ' +
* (referenceIndex + 1) +
* (rereferenceIndex > 1 ? '-' + rereferenceIndex : '')
* )
* }
* ```
*
* Change it when the markdown is not in English.
*
* This label is used in the `aria-label` attribute on each backreference
* (the `↩` links).
* It affects users of assistive technology.
*/
backLabel?: BackLabelTemplate | string | null | undefined
}

/**
* Augment types.
*/
declare module 'micromark-util-types' {
/**
* Compile data.
*/
interface CompileData {
gfmFootnoteDefinitions?: Record<string, string>
gfmFootnoteDefinitionStack?: Array<string>
gfmFootnoteCallCounts?: Record<string, number>
gfmFootnoteCallOrder?: Array<string>
}

/**
* Parse context.
*/
interface ParseContext {
gfmFootnotes?: Array<string>
}

/**
* Token types.
*/
interface TokenTypeMap {
gfmFootnoteCall: 'gfmFootnoteCall'
gfmFootnoteCallLabelMarker: 'gfmFootnoteCallLabelMarker'
Expand All @@ -20,15 +161,4 @@ declare module 'micromark-util-types' {
gfmFootnoteDefinitionMarker: 'gfmFootnoteDefinitionMarker'
gfmFootnoteDefinitionWhitespace: 'gfmFootnoteDefinitionWhitespace'
}

interface ParseContext {
gfmFootnotes?: string[]
}

interface CompileData {
gfmFootnoteDefinitions?: Record<string, string>
gfmFootnoteDefinitionStack?: string[]
gfmFootnoteCallCounts?: Record<string, number>
gfmFootnoteCallOrder?: string[]
}
}
111 changes: 2 additions & 109 deletions dev/lib/html.js
Original file line number Diff line number Diff line change
@@ -1,113 +1,6 @@
/**
* @typedef {import('micromark-util-types').HtmlExtension} HtmlExtension
*/

/**
* @callback BackLabelTemplate
* Generate a back label dynamically.
*
* For the following markdown:
*
* ```markdown
* Alpha[^micromark], bravo[^micromark], and charlie[^remark].
*
* [^remark]: things about remark
* [^micromark]: things about micromark
* ```
*
* This function will be called with:
*
* * `0` and `0` for the backreference from `things about micromark` to
* `alpha`, as it is the first used definition, and the first call to it
* * `0` and `1` for the backreference from `things about micromark` to
* `bravo`, as it is the first used definition, and the second call to it
* * `1` and `0` for the backreference from `things about remark` to
* `charlie`, as it is the second used definition
* @param {number} referenceIndex
* Index of the definition in the order that they are first referenced,
* 0-indexed.
* @param {number} rereferenceIndex
* Index of calls to the same definition, 0-indexed.
* @returns {string}
* Back label to use when linking back from definitions to their reference.
*/

/**
* @typedef Options
* Configuration.
* @property {string | null | undefined} [clobberPrefix='user-content-']
* Prefix to use before the `id` attribute on footnotes to prevent them from
* *clobbering* (default: `'user-content-'`).
*
* Pass `''` for trusted markdown and when you are careful with
* polyfilling.
* You could pass a different prefix.
*
* DOM clobbering is this:
*
* ```html
* <p id="x"></p>
* <script>alert(x) // `x` now refers to the `p#x` DOM element</script>
* ```
*
* The above example shows that elements are made available by browsers, by
* their ID, on the `window` object.
* This is a security risk because you might be expecting some other variable
* at that place.
* It can also break polyfills.
* Using a prefix solves these problems.
* @property {string | null | undefined} [label='Footnotes']
* Textual label to use for the footnotes section (default: `'Footnotes'`).
*
* Change it when the markdown is not in English.
*
* This label is typically hidden visually (assuming a `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass different attributes with the `labelAttributes` option.
* @property {string | null | undefined} [labelAttributes='class="sr-only"']
* Attributes to use on the footnote label (default: `'class="sr-only"'`).
*
* Change it to show the label and add other attributes.
*
* This label is typically hidden visually (assuming an `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass an empty string.
* You can also add different attributes.
*
* > 👉 **Note**: `id="footnote-label"` is always added, because footnote
* > calls use it with `aria-describedby` to provide an accessible label.
* @property {string | null | undefined} [labelTagName='h2']
* HTML tag name to use for the footnote label element (default: `'h2'`).
*
* Change it to match your document structure.
*
* This label is typically hidden visually (assuming a `sr-only` CSS class
* is defined that does that) and so affects screen readers only.
* If you do have such a class, but want to show this section to everyone,
* pass different attributes with the `labelAttributes` option.
* @property {BackLabelTemplate | string | null | undefined} [backLabel]
* Textual label to describe the backreference back to references (default:
* `defaultBackLabel`).
*
* The default value is:
*
* ```js
* function defaultBackLabel(referenceIndex, rereferenceIndex) {
* return (
* 'Back to reference ' +
* (referenceIndex + 1) +
* (rereferenceIndex > 1 ? '-' + rereferenceIndex : '')
* )
* }
* ```
*
* Change it when the markdown is not in English.
*
* This label is used in the `aria-label` attribute on each backreference
* (the `↩` links).
* It affects users of assistive technology.
* @import {HtmlOptions as Options} from 'micromark-extension-gfm-footnote'
* @import {HtmlExtension} from 'micromark-util-types'
*/

import {ok as assert} from 'devlop'
Expand Down
15 changes: 4 additions & 11 deletions dev/lib/syntax.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
/**
* @typedef {import('micromark-util-types').Event} Event
* @typedef {import('micromark-util-types').Exiter} Exiter
* @typedef {import('micromark-util-types').Extension} Extension
* @typedef {import('micromark-util-types').Resolver} Resolver
* @typedef {import('micromark-util-types').State} State
* @typedef {import('micromark-util-types').Token} Token
* @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext
* @typedef {import('micromark-util-types').Tokenizer} Tokenizer
* @import {Event, Exiter, Extension, Resolver, State, Token, TokenizeContext, Tokenizer} from 'micromark-util-types'
*/

import {ok as assert} from 'devlop'
Expand Down Expand Up @@ -36,19 +29,19 @@ export function gfmFootnote() {
return {
document: {
[codes.leftSquareBracket]: {
name: 'footnoteDefinition',
name: 'gfmFootnoteDefinition',
tokenize: tokenizeDefinitionStart,
continuation: {tokenize: tokenizeDefinitionContinuation},
exit: gfmFootnoteDefinitionEnd
}
},
text: {
[codes.leftSquareBracket]: {
name: 'footnoteCall',
name: 'gfmFootnoteCall',
tokenize: tokenizeGfmFootnoteCall
},
[codes.rightSquareBracket]: {
name: 'potentialFootnoteCall',
name: 'gfmPotentialFootnoteCall',
add: 'after',
tokenize: tokenizePotentialGfmFootnoteCall,
resolveTo: resolveToPotentialGfmFootnoteCall
Expand Down
19 changes: 17 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,25 @@
"overrides": [
{
"files": [
"**/*.ts"
"**/*.d.ts"
],
"rules": {
"@typescript-eslint/consistent-type-definitions": 0
"@typescript-eslint/array-type": [
"error",
{
"default": "generic"
}
],
"@typescript-eslint/ban-types": [
"error",
{
"extendDefaults": true
}
],
"@typescript-eslint/consistent-type-definitions": [
"error",
"interface"
]
}
},
{
Expand Down
8 changes: 4 additions & 4 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ test('micromark-extension-gfm-footnote', async function (t) {
})

await t.test(
'should skip calls and definitions construct if `disable.null` includes `footnoteDefinition` and `footnoteCall`',
'should skip calls and definitions construct if `disable.null` includes `footnoteDefinition` and `footnoteCall`',
async function () {
assert.deepEqual(
micromark('A call.[^a]\n\n[^a]: whatevs', {
Expand All @@ -56,9 +56,9 @@ test('micromark-extension-gfm-footnote', async function (t) {
{
disable: {
null: [
'footnoteDefinition',
'footnoteCall',
'potentialFootnoteCall'
'gfmFootnoteDefinition',
'gfmFootnoteCall',
'gfmPotentialFootnoteCall'
]
}
}
Expand Down

0 comments on commit 764bd0c

Please sign in to comment.