123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- /**
- * @typedef {import('mdast').Link} Link
- * @typedef {import('mdast').Parents} Parents
- * @typedef {import('../types.js').Exit} Exit
- * @typedef {import('../types.js').Info} Info
- * @typedef {import('../types.js').State} State
- */
- import {checkQuote} from '../util/check-quote.js'
- import {formatLinkAsAutolink} from '../util/format-link-as-autolink.js'
- link.peek = linkPeek
- /**
- * @param {Link} node
- * @param {Parents | undefined} _
- * @param {State} state
- * @param {Info} info
- * @returns {string}
- */
- export function link(node, _, state, info) {
- const quote = checkQuote(state)
- const suffix = quote === '"' ? 'Quote' : 'Apostrophe'
- const tracker = state.createTracker(info)
- /** @type {Exit} */
- let exit
- /** @type {Exit} */
- let subexit
- if (formatLinkAsAutolink(node, state)) {
- // Hide the fact that we’re in phrasing, because escapes don’t work.
- const stack = state.stack
- state.stack = []
- exit = state.enter('autolink')
- let value = tracker.move('<')
- value += tracker.move(
- state.containerPhrasing(node, {
- before: value,
- after: '>',
- ...tracker.current()
- })
- )
- value += tracker.move('>')
- exit()
- state.stack = stack
- return value
- }
- exit = state.enter('link')
- subexit = state.enter('label')
- let value = tracker.move('[')
- value += tracker.move(
- state.containerPhrasing(node, {
- before: value,
- after: '](',
- ...tracker.current()
- })
- )
- value += tracker.move('](')
- subexit()
- if (
- // If there’s no url but there is a title…
- (!node.url && node.title) ||
- // If there are control characters or whitespace.
- /[\0- \u007F]/.test(node.url)
- ) {
- subexit = state.enter('destinationLiteral')
- value += tracker.move('<')
- value += tracker.move(
- state.safe(node.url, {before: value, after: '>', ...tracker.current()})
- )
- value += tracker.move('>')
- } else {
- // No whitespace, raw is prettier.
- subexit = state.enter('destinationRaw')
- value += tracker.move(
- state.safe(node.url, {
- before: value,
- after: node.title ? ' ' : ')',
- ...tracker.current()
- })
- )
- }
- subexit()
- if (node.title) {
- subexit = state.enter(`title${suffix}`)
- value += tracker.move(' ' + quote)
- value += tracker.move(
- state.safe(node.title, {
- before: value,
- after: quote,
- ...tracker.current()
- })
- )
- value += tracker.move(quote)
- subexit()
- }
- value += tracker.move(')')
- exit()
- return value
- }
- /**
- * @param {Link} node
- * @param {Parents | undefined} _
- * @param {State} state
- * @returns {string}
- */
- function linkPeek(node, _, state) {
- return formatLinkAsAutolink(node, state) ? '<' : '['
- }
|