@markdoc/markdoc
Advanced tools
Comparing version 0.1.6 to 0.1.7
import type { Node, Value } from './types'; | ||
declare type Options = { | ||
allowIndentation?: boolean; | ||
maxTagOpeningWidth?: number; | ||
parent?: Node; | ||
@@ -5,0 +6,0 @@ indent?: number; |
{ | ||
"name": "@markdoc/markdoc", | ||
"author": "Ryan Paul", | ||
"version": "0.1.6", | ||
"version": "0.1.7", | ||
"description": "A text markup language for documentation", | ||
@@ -6,0 +6,0 @@ "main": "dist/index.js", |
@@ -82,4 +82,4 @@ import { diff } from 'jest-diff'; | ||
function stable(source) { | ||
return check(source, source); | ||
function stable(source, options?) { | ||
return check(source, source, options); | ||
} | ||
@@ -109,2 +109,5 @@ | ||
const source = ` | ||
{% if $primary %} | ||
X | ||
{% /if %} | ||
{% $user.name %} | ||
@@ -114,2 +117,6 @@ {% key x=$user.name new=$flag /%} | ||
const expected = ` | ||
{% if $primary %} | ||
X | ||
{% /if %} | ||
{% $user.name %} | ||
@@ -134,2 +141,3 @@ | ||
check(source, expected); | ||
stable(expected, expected); | ||
}); | ||
@@ -140,2 +148,11 @@ | ||
{% key /%} | ||
{% a %}{% /a %} | ||
{% a %} | ||
{% /a %} | ||
{% a %} | ||
{% /a %} | ||
@@ -151,2 +168,8 @@ {% checkout %} | ||
{% a /%} | ||
{% a /%} | ||
{% a /%} | ||
{% checkout %} | ||
@@ -177,2 +200,9 @@ {% if true %} | ||
it('long tags with maxTagOpeningWidth=Infinity', () => { | ||
const source = ` | ||
{% tag a=true b="My very long text well over 80 characters in total" c=123456789 d=false /%} | ||
`; | ||
check(source, source, { maxTagOpeningWidth: Infinity }); | ||
}); | ||
it('nested tags — allowIndentation: true', () => { | ||
@@ -196,2 +226,3 @@ const source = ` | ||
check(source, expected, { allowIndentation: true }); | ||
stable(expected, { allowIndentation: true }); | ||
}); | ||
@@ -262,2 +293,30 @@ | ||
it('tables with tags', () => { | ||
const source = ` | ||
{% table %} | ||
* H1 | ||
* H2 | ||
{% if $var %} | ||
--- | ||
* H3 | ||
* H4 | ||
{% /if %} | ||
{% /table %} | ||
`; | ||
const expected = ` | ||
{% table %} | ||
- H1 | ||
- H2 | ||
{% if $var %} | ||
--- | ||
- H3 | ||
- H4 | ||
{% /if %} | ||
{% /table %} | ||
`; | ||
check(source, expected); | ||
stable(expected); | ||
}); | ||
it('lists', () => { | ||
@@ -375,3 +434,9 @@ const source = ` | ||
* Set the proxy status to \`off\` to avoid issues during setup. | ||
{% /table %}`; | ||
{% /table %} | ||
1. foo\\ | ||
baz | ||
Soft | ||
break | ||
Markdoc uses…`; | ||
@@ -409,2 +474,8 @@ const expected = ` | ||
{% /table %} | ||
1. foo\\ | ||
baz | ||
Soft | ||
break | ||
Markdoc uses… | ||
`; | ||
@@ -411,0 +482,0 @@ |
@@ -7,2 +7,3 @@ import Ast from './ast'; | ||
allowIndentation?: boolean; | ||
maxTagOpeningWidth?: number; | ||
parent?: Node; | ||
@@ -18,3 +19,3 @@ indent?: number; | ||
const MAX_TAG_HEAD_LENGTH = 80; | ||
const MAX_TAG_OPENING_WIDTH = 80; | ||
@@ -60,3 +61,3 @@ const max = (a: number, b: number) => Math.max(a, b); | ||
function formatAnnotationValue(a: AttributeValue): string { | ||
if (a.name === 'primary') return a.value; | ||
if (a.name === 'primary') return formatScalar(a.value); | ||
if (a.name === 'id' && typeof a.value === 'string') return '#' + a.value; | ||
@@ -202,8 +203,15 @@ if (a.type === 'class') return '.' + a.name; | ||
const inlineTag = tag.join(SPACE); | ||
if (inlineTag.length + open.length * 2 > MAX_TAG_HEAD_LENGTH) { | ||
yield tag.join(NL + SPACE.repeat(open.length) + indent); | ||
} else { | ||
yield inlineTag; | ||
} | ||
yield SPACE + (n.children.length ? '' : '/') + CLOSE; | ||
const isLongTagOpening = | ||
inlineTag.length + open.length * 2 > | ||
(o.maxTagOpeningWidth || MAX_TAG_OPENING_WIDTH); | ||
// {% tag attributes={...} %} | ||
yield (isLongTagOpening | ||
? tag.join(NL + SPACE.repeat(open.length) + indent) | ||
: inlineTag) + | ||
SPACE + | ||
(n.children.length ? '' : '/') + | ||
CLOSE; | ||
if (n.children.length) { | ||
@@ -214,5 +222,4 @@ yield* formatChildren(n, no.allowIndentation ? increment(no) : no); | ||
} | ||
yield OPEN + SPACE + '/'; | ||
yield n.tag; | ||
yield SPACE + CLOSE; | ||
// {% /tag %} | ||
yield OPEN + SPACE + '/' + n.tag + SPACE + CLOSE; | ||
} | ||
@@ -274,21 +281,32 @@ if (!n.inline) { | ||
case 'table': { | ||
const table = [...formatChildren(n, increment(no))] as any as string[][]; | ||
const table = [...formatChildren(n, increment(no))] as any as any[]; | ||
if (o.parent && o.parent.type === 'tag' && o.parent.tag === 'table') { | ||
for (const row of table) { | ||
yield NL; | ||
for (const d of row) { | ||
// TODO see if we should move trim() to `td` | ||
yield indent + UL + d.trim(); | ||
yield NL; | ||
for (let i = 0; i < table.length; i++) { | ||
const row = table[i]; | ||
// format tags like "if" in the middle of a table list | ||
if (typeof row === 'string') { | ||
if (row.trim().length) { | ||
yield NL; | ||
yield row; | ||
} | ||
} else { | ||
if (i !== 0) { | ||
yield NL; | ||
yield indent + '---'; | ||
} | ||
for (let j = 0; j < row.length; j++) { | ||
const d = row[j]; | ||
yield NL; | ||
// TODO see if we should move trim() to `td` | ||
yield indent + UL + d.trim(); | ||
} | ||
} | ||
if (row !== table[table.length - 1]) { | ||
yield indent + '---'; | ||
} | ||
} | ||
yield NL; | ||
} else { | ||
yield NL; | ||
const [head, ...rows] = table; | ||
const [head, ...rows] = table as string[][]; | ||
const ml = table | ||
.map((arr) => arr.map((s) => s.length).reduce(max)) | ||
.map((arr) => arr.map((s: string) => s.length).reduce(max)) | ||
.reduce(max); | ||
@@ -378,3 +396,3 @@ | ||
for (const s of formatValue(v, options)) doc += s; | ||
return doc; | ||
return doc.trimStart(); | ||
} |
@@ -229,3 +229,3 @@ import type { Schema } from './types'; | ||
export const softbreak: Schema = { | ||
transform(_node, _config) { | ||
transform() { | ||
return ' '; | ||
@@ -232,0 +232,0 @@ }, |
@@ -235,2 +235,48 @@ import Markdoc from '../index'; | ||
describe('attribute validation', () => { | ||
it('should return error on failure to match array', () => { | ||
const example = '{% foo jawn="cat" /%}'; | ||
const schema = { | ||
tags: { | ||
foo: { | ||
attributes: { | ||
jawn: { | ||
type: String, | ||
matches: ['bar', 'baz', 'bat'], | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
expect(validate(example, schema)).toDeepEqualSubset([ | ||
{ | ||
type: 'tag', | ||
error: { | ||
id: 'attribute-value-invalid', | ||
message: `Attribute 'jawn' must match one of ["bar","baz","bat"]. Got 'cat' instead.`, | ||
}, | ||
}, | ||
]); | ||
}); | ||
// https://github.com/markdoc/markdoc/issues/122 | ||
it('should validate partial file attributes', () => { | ||
const example = `{% partial file="non-existent.md" /%}`; | ||
const output = validate(example, {}); | ||
expect(output).toDeepEqualSubset([ | ||
{ | ||
type: 'tag', | ||
error: { | ||
id: 'attribute-value-invalid', | ||
level: 'error', | ||
message: | ||
"Partial `non-existent.md` not found. The 'file' attribute must be set in `config.partials`", | ||
}, | ||
}, | ||
]); | ||
}); | ||
}); | ||
describe('custom type registration example', () => { | ||
@@ -341,20 +387,2 @@ class Link { | ||
}); | ||
// https://github.com/markdoc/markdoc/issues/122 | ||
it('should validate partial file attributes', () => { | ||
const example = `{% partial file="non-existent.md" /%}`; | ||
const output = validate(example, {}); | ||
expect(output).toDeepEqualSubset([ | ||
{ | ||
type: 'tag', | ||
error: { | ||
id: 'attribute-value-invalid', | ||
level: 'error', | ||
message: | ||
"Partial `non-existent.md` not found. The 'file' attribute must be set in `config.partials`", | ||
}, | ||
}, | ||
]); | ||
}); | ||
}); |
@@ -223,3 +223,3 @@ import { globalAttributes } from './transformer'; | ||
matches | ||
)}`, | ||
)}. Got '${value}' instead.`, | ||
}); | ||
@@ -231,3 +231,3 @@ | ||
level: errorLevel || 'error', | ||
message: `Attribute '${key}' must match ${matches}`, | ||
message: `Attribute '${key}' must match ${matches}. Got '${value}' instead.`, | ||
}); | ||
@@ -234,0 +234,0 @@ } |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1800271
23969