Skip to content

Commit

Permalink
Add associationId helper to state
Browse files Browse the repository at this point in the history
  • Loading branch information
wooorm committed Jan 4, 2023
1 parent 35ceafc commit 070ad5f
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 18 deletions.
3 changes: 1 addition & 2 deletions lib/handle/definition.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* @typedef {import('../types.js').Info} Info
*/

import {association} from '../util/association.js'
import {checkQuote} from '../util/check-quote.js'

/**
Expand All @@ -23,7 +22,7 @@ export function definition(node, _, state, info) {
const tracker = state.createTracker(info)
let value = tracker.move('[')
value += tracker.move(
state.safe(association(node), {
state.safe(state.associationId(node), {
before: value,
after: ']',
...tracker.current()
Expand Down
4 changes: 1 addition & 3 deletions lib/handle/image-reference.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
* @typedef {import('../types.js').Info} Info
*/

import {association} from '../util/association.js'

imageReference.peek = imageReferencePeek

/**
Expand Down Expand Up @@ -38,7 +36,7 @@ export function imageReference(node, _, state, info) {
// up making a `shortcut` reference, because then there is no brace output.
// Practically, in that case, there is no content, so it doesn’t matter that
// we’ve tracked one too many characters.
const reference = state.safe(association(node), {
const reference = state.safe(state.associationId(node), {
before: value,
after: ']',
...tracker.current()
Expand Down
4 changes: 1 addition & 3 deletions lib/handle/link-reference.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
* @typedef {import('../types.js').Info} Info
*/

import {association} from '../util/association.js'

linkReference.peek = linkReferencePeek

/**
Expand Down Expand Up @@ -38,7 +36,7 @@ export function linkReference(node, _, state, info) {
// up making a `shortcut` reference, because then there is no brace output.
// Practically, in that case, there is no content, so it doesn’t matter that
// we’ve tracked one too many characters.
const reference = state.safe(association(node), {
const reference = state.safe(state.associationId(node), {
before: value,
after: ']',
...tracker.current()
Expand Down
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {configure} from './configure.js'
import {handle as handlers} from './handle/index.js'
import {join} from './join.js'
import {unsafe} from './unsafe.js'
import {association} from './util/association.js'
import {containerPhrasing} from './util/container-phrasing.js'
import {containerFlow} from './util/container-flow.js'
import {indentLines} from './util/indent-lines.js'
Expand All @@ -38,6 +39,7 @@ export function toMarkdown(tree, options = {}) {
const state = {
enter,
indentLines,
associationId: association,
containerPhrasing: containerPhrasingBound,
containerFlow: containerFlowBound,
createTracker: track,
Expand Down
29 changes: 27 additions & 2 deletions lib/types.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
/**
* @typedef {import('unist').Parent} UnistParent
* @typedef {import('unist').Point} Point
* @typedef {import('mdast').Root} Root
* @typedef {import('mdast').Association} Association
* @typedef {import('mdast').Content} Content
* @typedef {import('mdast').TopLevelContent} TopLevelContent
* @typedef {import('mdast').ListContent} ListContent
* @typedef {import('mdast').PhrasingContent} PhrasingContent
* @typedef {import('mdast').Root} Root
* @typedef {import('mdast').TopLevelContent} TopLevelContent
* @typedef {import('../index.js').ConstructName} ConstructName
*/

Expand Down Expand Up @@ -73,6 +74,28 @@
* @returns {Tracker}
* Tracker.
*
* @callback AssociationId
* Get an identifier from an association to match it to others.
*
* Associations are nodes that match to something else through an ID:
* <https://github.com/syntax-tree/mdast#association>.
*
* The `label` of an association is the string value: character escapes and
* references work, and casing is intact.
* The `identifier` is used to match one association to another:
* controversially, character escapes and references don’t work in this
* matching: `&copy;` does not match `©`, and `\+` does not match `+`.
*
* But casing is ignored (and whitespace) is trimmed and collapsed: ` A\nb`
* matches `a b`.
* So, we do prefer the label when figuring out how we’re going to serialize:
* it has whitespace, casing, and we can ignore most useless character
* escapes and all character references.
* @param {Association} node
* Node that includes an association.
* @returns {string}
* ID.
*
* @callback Map
* Map function to pad a single line.
* @param {string} value
Expand Down Expand Up @@ -169,6 +192,8 @@
* Positions of child nodes in their parents.
* @property {IndentLines} indentLines
* Pad serialized markdown.
* @property {AssociationId} associationId
* Get an identifier from an association to match it to others.
* @property {ContainerPhrasing} containerPhrasing
* Serialize the children of a parent that contains phrasing children.
* @property {ContainerFlow} containerFlow
Expand Down
21 changes: 13 additions & 8 deletions lib/util/association.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
/**
* @typedef {import('mdast').Association} Association
* @typedef {import('../types.js').AssociationId} AssociationId
*/

import {decodeString} from 'micromark-util-decode-string'

/**
* Get an identifier from an association to match it to others.
*
* Associations are nodes that match to something else through an ID:
* <https://github.com/syntax-tree/mdast#association>.
*
* The `label` of an association is the string value: character escapes and
* references work, and casing is intact.
* The `identifier` is used to match one association to another: controversially,
* character escapes and references don’t work in this matching: `&copy;` does
* not match `©`, and `\+` does not match `+`.
* The `identifier` is used to match one association to another:
* controversially, character escapes and references don’t work in this
* matching: `&copy;` does not match `©`, and `\+` does not match `+`.
*
* But casing is ignored (and whitespace) is trimmed and collapsed: ` A\nb`
* matches `a b`.
* So, we do prefer the label when figuring out how we’re going to serialize:
* it has whitespace, casing, and we can ignore most useless character escapes
* and all character references.
* it has whitespace, casing, and we can ignore most useless character
* escapes and all character references.
*
* @param {Association} node
* @returns {string}
* @type {AssociationId}
*/
export function association(node) {
if (node.label || !node.identifier) {
Expand Down
5 changes: 5 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,9 @@ Info passed around about the current state (TypeScript type).
— stack of constructs we’re in
* `indexStack` (`Array<number>`)
— positions of child nodes in their parents
* `associationId` (`(node: Association) => string`)
— get an identifier from an association to match it to others (see
[`Association`][association])
* `enter` (`(construct: ConstructName) => () => void`)
— enter a construct (returns a corresponding exit function)
(see [`ConstructName`][constructname])
Expand Down Expand Up @@ -685,6 +688,8 @@ abide by its terms.

[node]: https://github.com/syntax-tree/mdast#nodes

[association]: https://github.com/syntax-tree/mdast#association

[mdast-util-gfm]: https://github.com/syntax-tree/mdast-util-gfm

[mdast-util-mdx]: https://github.com/syntax-tree/mdast-util-mdx
Expand Down

0 comments on commit 070ad5f

Please sign in to comment.