4.2: the ADF property #75
@@ -0,0 +1,107 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "underline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": ":a{"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "x",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "underline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "y",
|
||||||
|
"title": ":a{"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "x",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "underline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": ":a[]{"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "x",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "underline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "https://example.com/?q=:emoji{"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "x",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "underline"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "ab:c{"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "ab:c{",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
:underline[[x](\:a{)]
|
||||||
|
|
||||||
|
:underline[[x](y "\:a{")]
|
||||||
|
|
||||||
|
:underline[[x](\:a[]{)]
|
||||||
|
|
||||||
|
:underline[[x](https://example.com/?q=\:emoji{)]
|
||||||
|
|
||||||
|
:underline[[ab\:c{](ab\:c{)]
|
||||||
+6
-6
@@ -48,8 +48,8 @@ normalizes to it through the round-trip.
|
|||||||
title; title in double quotes. A backslash escapes a parenthesis the destination leaves
|
title; title in double quotes. A backslash escapes a parenthesis the destination leaves
|
||||||
unbalanced, and a quote inside the title; a balanced pair stays bare. `<url>` autolink form only
|
unbalanced, and a quote inside the title; a balanced pair stays bare. `<url>` autolink form only
|
||||||
when the text equals the destination and the destination is a valid CommonMark autolink
|
when the text equals the destination and the destination is a valid CommonMark autolink
|
||||||
(absolute URI) — inside an inline directive's `[content]`, one holding no backtick and no
|
(absolute URI) — inside an inline directive's `[content]`, one holding no backtick, no
|
||||||
unbalanced bracket.
|
unbalanced bracket and no inline directive opener.
|
||||||
- Paragraphs on one line — no soft wrapping; a soft line break in input becomes a single space.
|
- Paragraphs on one line — no soft wrapping; a soft line break in input becomes a single space.
|
||||||
- Entity references in input decode to their characters; output backslash-escapes only where text
|
- Entity references in input decode to their characters; output backslash-escapes only where text
|
||||||
would otherwise parse as syntax, scanning the assembled line rather than each text node: escape
|
would otherwise parse as syntax, scanning the assembled line rather than each text node: escape
|
||||||
@@ -132,10 +132,10 @@ each a named error naming the spelling to write instead.
|
|||||||
|
|
||||||
**Escaping**: the emitter backslash-escapes whatever literal text would otherwise parse as
|
**Escaping**: the emitter backslash-escapes whatever literal text would otherwise parse as
|
||||||
directive syntax — the leading `:` of a would-be directive, `]` inside content, a bracket a link's
|
directive syntax — the leading `:` of a would-be directive, `]` inside content, a bracket a link's
|
||||||
destination and title inside content leave unbalanced and a backtick there that would open a code
|
destination and title inside content leave unbalanced, a backtick there that would open a code span
|
||||||
span, a `{` right after a directive's closing `]`, which would otherwise be read as the attributes
|
and a `:` there that would open an inline directive, a `{` right after a directive's closing `]`,
|
||||||
it has none of; outside code spans and code blocks, a backslash before `:` in input yields a
|
which would otherwise be read as the attributes it has none of; outside code spans and code blocks,
|
||||||
literal colon.
|
a backslash before `:` in input yields a literal colon.
|
||||||
|
|
||||||
**Malformed directives are error results**, named: an unclosed container at end of input, a body
|
**Malformed directives are error results**, named: an unclosed container at end of input, a body
|
||||||
fence line of the container's length or longer, a bare colon-run line outside any container or
|
fence line of the container's length or longer, a bare colon-run line outside any container or
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ export function attributeValue(text: string, kind: AttributeKind): AttributeRead
|
|||||||
return overNested(parsed) ? { refusal: 'nesting' } : { value: { kind, value: parsed } }
|
return overNested(parsed) ? { refusal: 'nesting' } : { value: { kind, value: parsed } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function holdsInlineDirectiveOpener(text: string): boolean {
|
||||||
|
for (let index = text.indexOf(':'); index !== -1; index = text.indexOf(':', index + 1)) if (opensInlineDirective(text, index)) return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
export function isBareToken(text: string): boolean {
|
export function isBareToken(text: string): boolean {
|
||||||
return bareToken.test(text)
|
return bareToken.test(text)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import { claimsLine, holdsNullCharacter, isAutolink } from '../commonmark-gramma
|
|||||||
import { escapeUnbalanced, spellDestination, spellLinkTarget } from '../link-syntax.ts'
|
import { escapeUnbalanced, spellDestination, spellLinkTarget } from '../link-syntax.ts'
|
||||||
import { failure, faulted, success, type ConvertErrorPath, type Result } from '../../result.ts'
|
import { failure, faulted, success, type ConvertErrorPath, type Result } from '../../result.ts'
|
||||||
import { holdsEntityReference } from '../entity-references.ts'
|
import { holdsEntityReference } from '../entity-references.ts'
|
||||||
|
import { holdsInlineDirectiveOpener, slotLineEndingFault, spellLeafDirective } from '../directive-syntax.ts'
|
||||||
import { inlineDirective } from '../../adf/inline-directives.ts'
|
import { inlineDirective } from '../../adf/inline-directives.ts'
|
||||||
import { largestNesting } from '../../nesting.ts'
|
import { largestNesting } from '../../nesting.ts'
|
||||||
import { longestBacktickRun } from '../backtick-runs.ts'
|
import { longestBacktickRun } from '../backtick-runs.ts'
|
||||||
import { markSpelling, spellMarkAttributes } from '../mark-spellings.ts'
|
import { markSpelling, spellMarkAttributes } from '../mark-spellings.ts'
|
||||||
import { nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
import { nodeAttrs, nodeContent, nodeMarks } from '../../adf/document.ts'
|
||||||
import { sameMark } from '../../adf/editor-normal.ts'
|
import { sameMark } from '../../adf/editor-normal.ts'
|
||||||
import { slotLineEndingFault, spellLeafDirective } from '../directive-syntax.ts'
|
|
||||||
import { spellInlineNodeAttributes } from './inline-directive-spelling.ts'
|
import { spellInlineNodeAttributes } from './inline-directive-spelling.ts'
|
||||||
import { spellTextDirective } from '../text-directive.ts'
|
import { spellTextDirective } from '../text-directive.ts'
|
||||||
|
|
||||||
@@ -284,7 +284,7 @@ function emitLink(nodes: readonly AdfNode[], mark: AdfMark, depth: number, range
|
|||||||
if (typeof href !== 'string') return success({ carry: range })
|
if (typeof href !== 'string') return success({ carry: range })
|
||||||
const node = nodes[0]
|
const node = nodes[0]
|
||||||
const bare = nodes.length === 1 && node !== undefined && node.type === 'text' && node.text === href && nodeMarks(node).length === depth + 1
|
const bare = nodes.length === 1 && node !== undefined && node.type === 'text' && node.text === href && nodeMarks(node).length === depth + 1
|
||||||
const autolinkHolds = !context.bracketed || (!href.includes('`') && escapeUnbalanced(href, '[', ']') === href)
|
const autolinkHolds = !context.bracketed || (!href.includes('`') && !holdsInlineDirectiveOpener(href) && escapeUnbalanced(href, '[', ']') === href)
|
||||||
if (bare && autolinkHolds && title === undefined && isAutolink(href) && !holdsEntityReference(href)) return success({ segments: [syntax(`<${href}>`)] })
|
if (bare && autolinkHolds && title === undefined && isAutolink(href) && !holdsEntityReference(href)) return success({ segments: [syntax(`<${href}>`)] })
|
||||||
const target = spellLinkTarget(href, typeof title === 'string' ? title : undefined, path)
|
const target = spellLinkTarget(href, typeof title === 'string' ? title : undefined, path)
|
||||||
if (!target.ok) return target
|
if (!target.ok) return target
|
||||||
|
|||||||
@@ -81,7 +81,8 @@ function escape(segments: readonly InlineSegment[], container: LineContainer): A
|
|||||||
(claimsLineStart(line, index, container) ||
|
(claimsLineStart(line, index, container) ||
|
||||||
mergesWithSyntax(scan, escapings, index) ||
|
mergesWithSyntax(scan, escapings, index) ||
|
||||||
opensConstruct(scan, linkClose, index, escaping === 'bracketed', container, escaped))) ||
|
opensConstruct(scan, linkClose, index, escaping === 'bracketed', container, escaped))) ||
|
||||||
(escaping === 'bracketed-link-target' && scan.charAt(index) === '`' && opensCodeSpan(scan, index, escaped))
|
(escaping === 'bracketed-link-target' &&
|
||||||
|
((scan.charAt(index) === '`' && opensCodeSpan(scan, index, escaped)) || (scan.charAt(index) === ':' && opensInlineDirective(scan, index))))
|
||||||
) {
|
) {
|
||||||
output += '\\'
|
output += '\\'
|
||||||
escaped.add(index)
|
escaped.add(index)
|
||||||
|
|||||||
Reference in New Issue
Block a user