diff --git a/packages/nuejs.org/@global/navigation.yaml b/packages/nuejs.org/@global/navigation.yaml
index 038aeec8..98fe6975 100644
--- a/packages/nuejs.org/@global/navigation.yaml
+++ b/packages/nuejs.org/@global/navigation.yaml
@@ -43,7 +43,7 @@ globalnav:
# header toolbar (complementary)
toolbar:
- - "@tipiirai": //x.com/tipiirai "social"
+ - tipiirai: //x.com/tipiirai "social"
- 6.1k: //github.com/nuejs/nue "github pill"
# burger menu
diff --git a/packages/nuekit/src/layout/page.js b/packages/nuekit/src/layout/page.js
index d41157dd..42031c1a 100644
--- a/packages/nuekit/src/layout/page.js
+++ b/packages/nuekit/src/layout/page.js
@@ -96,17 +96,16 @@ export function renderSlots(data, lib) {
}
-// Markdown extensions
-function createTags(lib, data) {
+// custom components as Markdown extensions (tags)
+function convertToTags(components, data) {
const tags = {}
- // components as Markdown tags
- lib.forEach(comp => {
+ components.forEach(comp => {
const { name } = comp
if (name && !SLOTS.includes(name)) {
tags[name] = function(data) {
const { attr, innerHTML } = this
- return comp.render({ attr, ...data, innerHTML }, lib)
+ return comp.render({ attr, ...data, innerHTML }, components)
}
}
})
@@ -120,12 +119,14 @@ export function renderPage({ doc, data, lib }) {
const slots = renderSlots(data, comps)
const tags = {
- ...createTags(lib, data),
+ ...convertToTags(lib, data),
'page-list': renderPageList,
toc: doc.renderTOC
}
- const content = doc.render({ data, tags })
+ // nuemark opts: { data, sections, heading_ids, links, tags }
+ const { heading_ids, sections, links } = data
+ const content = doc.render({ data, heading_ids, sections, links, tags })
// ...
if (!slots.main && data.main !== false) {
diff --git a/packages/nuekit/test/nuekit.test.js b/packages/nuekit/test/nuekit.test.js
index facc7344..262e98ce 100644
--- a/packages/nuekit/test/nuekit.test.js
+++ b/packages/nuekit/test/nuekit.test.js
@@ -181,7 +181,7 @@ test('content collection', async () => {
expect(coll[0]).toMatchObject({ title: "First", slug: "first-a.html", basedir: "blog" })
})
-test('basig page generation', async () => {
+test('basic page generation', async () => {
await write('index.md', '# Hello\nWorld')
const kit = await getKit()
diff --git a/packages/nuemark/index.js b/packages/nuemark/index.js
index fd1ba6be..af83161f 100644
--- a/packages/nuemark/index.js
+++ b/packages/nuemark/index.js
@@ -1,18 +1,18 @@
+import { parseDocument } from './src/parse-document.js'
import { renderLines } from './src/render-blocks.js'
-import { parseDocument } from './src/document.js'
const EOL = /\r\n|\r|\n/
-export function nuemark(str, opts) {
- return renderLines(str.split(EOL), opts)
+export function nuedoc(str, opts) {
+ return parseDocument(str.split(EOL), opts)
}
-export function nuedoc(str) {
- return parseDocument(str.split(EOL))
+export function nuemark(str, opts) {
+ return renderLines(str.split(EOL), opts)
}
/* utilities */
export { renderInline } from './src/render-inline.js'
export { parseSize } from './src/render-tag.js'
-export { elem } from './src/document.js'
+export { elem } from './src/render-blocks.js'
diff --git a/packages/nuemark/src/parse-blocks.js b/packages/nuemark/src/parse-blocks.js
index 41cf23e0..29956afd 100644
--- a/packages/nuemark/src/parse-blocks.js
+++ b/packages/nuemark/src/parse-blocks.js
@@ -1,14 +1,19 @@
import { load as parseYAML } from 'js-yaml'
-import { parseInline } from './parse-inline.js'
+
+import { parseInline, parseLinkTitle } from './parse-inline.js'
import { parseTag } from './parse-tag.js'
export function parseBlocks(lines, capture) {
const blocks = []
let spaces, block
- // capture stuff while recursing things
- if (!capture) capture = { reflinks: {}, footnotes: [] }
+ // capture things while recursing blocks
+ capture = capture || {
+ footnotes: [],
+ reflinks: {},
+ noterefs: []
+ }
lines.forEach(line => {
const c = line[0]
@@ -92,9 +97,18 @@ export function parseBlocks(lines, capture) {
}
}
- // reflink (can be nested on any level)
- const ref = parseReflink(trimmed)
- if (ref) return capture.reflinks[ref.key] = ref.link
+ // reflink or footnote (can be nested on any level)
+ const ref = parseRef(trimmed)
+ if (ref) {
+ const { key, value } = ref
+ if (key[0] == '^') {
+ capture.footnotes.push(ref)
+ capture.noterefs.push(key)
+ } else {
+ capture.reflinks[key] = parseLinkTitle(value)
+ }
+ return
+ }
// tag
@@ -142,26 +156,25 @@ export function parseBlocks(lines, capture) {
})
-
/* tokenize lists and quotes. parse component data */
blocks.forEach(block => processNestedBlocks(block, capture))
- blocks.footnotes = capture.footnotes
- blocks.reflinks = capture.reflinks
- return blocks
+ return { blocks, ...capture }
}
-
-
// recursive processing of nested blocks
function processNestedBlocks(block, capture) {
const { name } = block
if (block.is_list) {
- block.items = block.entries.map(blocks => parseBlocks(blocks, capture))
+ block.items = block.entries.map(lines => {
+ const { blocks } = parseBlocks(lines, capture)
+ return blocks
+ })
} else if (block.is_quote) {
- block.blocks = parseBlocks(block.content, capture)
+ const { blocks } = parseBlocks(block.content, capture)
+ block.blocks = blocks
} else if (block.is_tag) {
@@ -179,11 +192,12 @@ function processNestedBlocks(block, capture) {
}
if (name != 'table') {
- if (!block.has_data) block.blocks = parseBlocks(block.body, capture)
+ const { blocks } = parseBlocks(block.body, capture)
+ if (!block.has_data) block.blocks = blocks
delete block.body
if (name == 'define') {
- capture.footnotes.push(...getFootnoteIds(block.blocks))
+ capture.noterefs.push(...getFootnoteIds(blocks))
}
}
}
@@ -207,13 +221,12 @@ function getFootnoteIds(blocks) {
.map(el => `^${el.attr.id}`)
}
-function parseReflink(str) {
+function parseRef(str) {
if (str[0] == '[') {
const i = str.indexOf(']:')
if (i > 1) {
const key = str.slice(1, i)
- const is_footnote = key[0] == '^'
- return { key, is_footnote, link: str.slice(i + 2).trim() }
+ return { key, value: str.slice(i + 2).trim() }
}
}
}
diff --git a/packages/nuemark/src/document.js b/packages/nuemark/src/parse-document.js
similarity index 51%
rename from packages/nuemark/src/document.js
rename to packages/nuemark/src/parse-document.js
index 254a9acb..53079caf 100644
--- a/packages/nuemark/src/document.js
+++ b/packages/nuemark/src/parse-document.js
@@ -1,68 +1,61 @@
import { renderBlocks, createHeadingId } from './render-blocks.js'
import { parseLinkTitle } from './parse-inline.js'
+import { renderInline } from './render-inline.js'
import { parseBlocks } from './parse-blocks.js'
import { load as parseYAML } from 'js-yaml'
+import { elem } from './render-blocks.js'
-export function parseDocument(lines) {
- const user_meta = stripMeta(lines)
- const blocks = parseBlocks(lines)
- const { reflinks } = blocks
-
- const meta = {
-
- get title() {
- const tag = blocks.find(el => el.is_tag)
- return findTitle(blocks) || tag && findTitle(tag.blocks) || ''
- },
- get description() {
- const block = blocks.find(el => el.is_content)
- return block?.content[0]
- },
-
- ...user_meta
+// OPTS: { data, sections, heading_ids, links, tags }
+export function parseDocument(lines) {
+ const meta = stripMeta(lines)
+ const things = parseBlocks(lines)
+ const { blocks } = things
+
+ // title
+ if (!meta.title) {
+ const tag = blocks.find(el => el.is_tag)
+ meta.title = getTitle(blocks) || tag && getTitle(tag.blocks) || ''
}
- const api = {
+ // descrption
+ if (!meta.description) {
+ const block = blocks.find(el => el.is_content)
+ meta.description = block?.content[0]
+ }
- get sections() {
- return sectionize(blocks) || [ blocks ]
- },
+ const sections = sectionize(blocks) || [ blocks ]
- get codeblocks() {
- return blocks.filter(el => el.is_code)
- },
+ function renderSections(opts) {
+ const classList = Array.isArray(opts.sections) ? opts.sections : []
+ const html = []
- addReflink(label, href) {
- reflinks.push({ label, ...parseLinkTitle(href) })
- },
-
- renderSections(classes, opts) {
- const html = []
+ sections.forEach((section, i) => {
+ html.push(elem('section', { class: classList[i] }, renderBlocks(section, opts)))
+ })
+ return html.join('\n\n')
+ }
- api.sections.forEach((blocks, i) => {
- html.push(elem('section', { class: classes[i] }, renderBlocks(blocks, opts)))
- })
- return html.join('\n\n')
+ return {
+ render(opts={}) {
+ Object.assign(things.reflinks, parseReflinks(opts.links))
+ opts = { ...opts, ...things }
+ const html = opts.sections ? renderSections(opts) : renderBlocks(blocks, opts)
+ return html + renderFootnotes(things.footnotes)
},
renderTOC(attr={}) {
- const navs = api.sections.map(renderNav).join('\n').trim()
+ const navs = sections.map(renderNav).join('\n').trim()
return elem('div', { 'aria-label': 'Table of contents', ...attr }, navs)
},
- render(opts={ data: meta }) {
- let classes = opts.data.sections
- if (classes && !Array.isArray(classes)) classes = []
- return classes ? api.renderSections(classes, opts) : renderBlocks(blocks, opts)
- },
+ codeblocks: blocks.filter(el => el.is_code),
+ sections,
+ meta,
}
-
- return { meta, reflinks, ...api }
}
-
export function sectionize(blocks=[]) {
const arr = []
let section
@@ -88,6 +81,13 @@ export function sectionize(blocks=[]) {
}
+function renderFootnotes(arr) {
+ if (!arr.length) return ''
+ const html = arr.map(el => elem('li', elem('a', { name: el.key }) + renderInline(el.value) ))
+ return elem('ol', { role: 'doc-endnotes' }, html.join('\n'))
+}
+
+
function renderNav(blocks) {
const headings = blocks.filter(b => [2, 3].includes(b.level))
@@ -100,7 +100,7 @@ function renderNav(blocks) {
return links[0] ? elem('nav', links.join('\n')) : ''
}
-function findTitle(blocks) {
+function getTitle(blocks) {
const h1 = blocks?.find(el => el.level == 1)
return h1?.text || ''
}
@@ -126,28 +126,13 @@ export function stripMeta(lines) {
return parseYAML(front)
}
-
-/**** utilities ****/
-const SELF_CLOSING = ['img', 'source', 'meta', 'link']
-
-export function elem(name, attr, body) {
- if (typeof attr == 'string') { body = attr; attr = null }
-
- const html = [`<${name}${renderAttrs(attr)}>`]
-
- if (body) html.push(body)
- if (!SELF_CLOSING.includes(name)) html.push(`${name}>`)
- return html.join('')
-}
-
-
-function renderAttrs(attr) {
- const arr = []
- for (const key in attr) {
- const val = attr[key]
- if (val) arr.push(val === true ? key :`${key}="${val}"`)
+function parseReflinks(links={}) {
+ for (const key in links) {
+ const href = links[key]
+ if (typeof href == 'string') links[key] = parseLinkTitle(href)
}
- return arr[0] ? ' ' + arr.join(' ') : ''
+ return links
}
+
diff --git a/packages/nuemark/src/parse-inline.js b/packages/nuemark/src/parse-inline.js
index 74fbada0..5425ede7 100644
--- a/packages/nuemark/src/parse-inline.js
+++ b/packages/nuemark/src/parse-inline.js
@@ -83,7 +83,7 @@ const PARSERS = [
// footnote?
if (name[0] == '^') {
const rel = name.slice(1)
- return rel >= 0 || isValidName(rel) ? { is_footnote: true, href: name, end } : { text: c }
+ return rel >= 0 || isValidName(rel) ? { href: name, end } : { text: c }
}
// normal tag
@@ -197,13 +197,11 @@ export function parseLink(str, is_reflink) {
if (str[j + 1] == ')') j++
}
-
// href & title
let { href, title } = parseLinkTitle(str.slice(i + 2, j))
return {
href, title, label,
- is_footnote: href[0] == '^',
is_reflink,
end: j + 1
}
diff --git a/packages/nuemark/src/render-blocks.js b/packages/nuemark/src/render-blocks.js
index d1ef27e5..614da3ab 100644
--- a/packages/nuemark/src/render-blocks.js
+++ b/packages/nuemark/src/render-blocks.js
@@ -3,18 +3,16 @@ import { glow } from 'nue-glow'
import { renderInline, renderTokens } from './render-inline.js'
import { renderTable, renderTag, wrap } from './render-tag.js'
-import { parseLinkTitle } from './parse-inline.js'
import { parseBlocks } from './parse-blocks.js'
-import { elem } from './document.js'
+// for testing only
export function renderLines(lines, opts) {
- return renderBlocks(parseBlocks(lines), opts)
+ const things = parseBlocks(lines)
+ return renderBlocks(things.blocks, { ...opts, ...things })
}
export function renderBlocks(blocks, opts={}) {
- opts.reflinks = parseReflinks({ ...blocks.reflinks, ...opts?.data?.links })
- opts.footnotes = blocks.footnotes
return blocks.map(b => renderBlock(b, opts)).join('\n')
}
@@ -40,16 +38,9 @@ function renderList({ items, numbered }, opts) {
return elem(numbered ? 'ol' : 'ul', html.join('\n'))
}
-function parseReflinks(links) {
- for (const key in links) {
- links[key] = parseLinkTitle(links[key])
- }
- return links
-}
-
export function renderHeading(h, opts={}) {
const attr = { ...h.attr }
- const show_id = opts.data?.heading_ids
+ const show_id = opts.heading_ids
if (show_id && !attr.id) attr.id = createHeadingId(h.text)
// anchor
@@ -87,4 +78,30 @@ function renderCode({ name, code, attr, data }, opts) {
return wrap(klass, html)
}
+/**** utilities ****/
+const SELF_CLOSING = ['img', 'source', 'meta', 'link']
+
+export function elem(name, attr, body) {
+ if (typeof attr == 'string') { body = attr; attr = null }
+
+ const html = [`<${name}${renderAttrs(attr)}>`]
+
+ if (body) html.push(body)
+ if (!SELF_CLOSING.includes(name)) html.push(`${name}>`)
+ return html.join('')
+}
+
+
+function renderAttrs(attr) {
+ const arr = []
+ for (const key in attr) {
+ const val = attr[key]
+ if (val) arr.push(val === true ? key :`${key}="${val}"`)
+ }
+ return arr[0] ? ' ' + arr.join(' ') : ''
+}
+
+
+
+
diff --git a/packages/nuemark/src/render-inline.js b/packages/nuemark/src/render-inline.js
index c57a94f5..5b34915d 100644
--- a/packages/nuemark/src/render-inline.js
+++ b/packages/nuemark/src/render-inline.js
@@ -1,7 +1,7 @@
import { parseInline, ESCAPED } from './parse-inline.js'
import { renderTag } from './render-tag.js'
-import { elem } from './document.js'
+import { elem } from './render-blocks.js'
export function renderToken(token, opts={}) {
const { data={} } = opts
@@ -31,15 +31,16 @@ function renderImage(img) {
}
function renderLink(link, opts) {
- const { href, title, is_footnote } = link
- const { reflinks={}, footnotes=[] } = opts
+ const { href, title } = link
+ const { reflinks={}, noterefs=[] } = opts
const url = reflinks[href] || { href }
+ const is_footnote = href[0] == '^'
let label = renderInline(link.label, opts)
- // footnotes
+ // noterefs
if (is_footnote) {
- const index = footnotes.findIndex(el => el == href)
+ const index = noterefs.findIndex(el => el == href)
if (index >= 0) label += elem('sup', { role: 'doc-noteref' }, index + 1)
}
diff --git a/packages/nuemark/src/render-tag.js b/packages/nuemark/src/render-tag.js
index 0a1b4e19..7c51207a 100644
--- a/packages/nuemark/src/render-tag.js
+++ b/packages/nuemark/src/render-tag.js
@@ -1,7 +1,8 @@
import { renderBlocks, renderContent } from './render-blocks.js'
+import { sectionize, } from './parse-document.js'
import { renderInline } from './render-inline.js'
-import { sectionize, elem } from './document.js'
+import { elem } from './render-blocks.js'
import { readFileSync } from 'node:fs'
import { join } from 'node:path'
@@ -98,7 +99,7 @@ const TAGS = {
let table = { rows: data.rows || data.items }
if (!table.rows && body) table = parseTable(body)
- const html = renderTable({ attr, ...data, ...table }, this.opts)
+ const html = renderTable({ attr, ...data, ...table }, opts)
return wrap(data.wrapper, html)
},
@@ -119,7 +120,7 @@ const TAGS = {
}
export function renderTag(tag, opts={}) {
- const tags = opts.tags = { ...TAGS, ...opts?.tags }
+ const tags = { ...TAGS, ...opts.tags }
const fn = tags[tag.name || 'block']
if (!fn) return renderIsland(tag, opts.data)
@@ -229,7 +230,7 @@ function getInnerHTML(blocks = [], opts) {
// table helpers
-export function renderTable(table, md_opts) {
+export function renderTable(table, opts) {
const { rows, attr, head=true } = table
if (!rows) return ''
@@ -246,14 +247,14 @@ export function renderTable(table, md_opts) {
const cells = row.map(td => {
const attr = colspan > 1 ? { colspan } : null
- return elem(is_head || is_foot ? 'th' : 'td', attr, renderInline(td, md_opts))
+ return elem(is_head || is_foot ? 'th' : 'td', attr, renderInline(td, opts))
})
const tr = elem('tr', cells.join(''))
return is_head ? elem('thead', tr) : is_foot ? elem('tfoot', tr) : tr
})
- const caption = table.caption ? elem('caption', renderInline(table.caption, md_opts)) : ''
+ const caption = table.caption ? elem('caption', renderInline(table.caption, opts)) : ''
return elem('table', attr, caption + html.join('\n'))
}
diff --git a/packages/nuemark/test/block.test.js b/packages/nuemark/test/block.test.js
index b57642fb..b5ffe1cb 100644
--- a/packages/nuemark/test/block.test.js
+++ b/packages/nuemark/test/block.test.js
@@ -5,7 +5,7 @@ import { nuemark } from '..'
test('paragraphs', () => {
- const blocks = parseBlocks([ 'a', 'b', '', '', 'c' ])
+ const { blocks } = parseBlocks([ 'a', 'b', '', '', 'c' ])
expect(blocks.length).toBe(2)
const html = renderBlocks(blocks)
@@ -14,28 +14,29 @@ test('paragraphs', () => {
})
test('list items', () => {
- const blocks = parseBlocks(['- a', '', ' a1', '- b', '', '', '- c'])
+ const { blocks } = parseBlocks(['- a', '', ' a1', '- b', '', '', '- c'])
expect(blocks.length).toBe(1)
expect(blocks[0].entries).toEqual([[ "a", "", "a1" ], [ "b", "", "" ], [ "c" ]])
})
test('nested lists', () => {
- const blocks = parseBlocks(['- item', '', ' - nested 1', '', '', ' - nested 2'])
+ const { blocks } = parseBlocks(['- item', '', ' - nested 1', '', '', ' - nested 2'])
expect(blocks.length).toBe(1)
expect(blocks[0].entries[0]).toEqual([ "item", "", "- nested 1", "", "", "- nested 2" ])
+
const html = renderBlocks(blocks)
expect(html).toEndWith('
nested 2
')
})
test('nested tag data', () => {
- const [ comp ] = parseBlocks(['[hello]', '', '', ' foo: bar', '', ' bro: 10'])
- expect(comp.data).toEqual({ foo: "bar", bro: 10 })
+ const { blocks } = parseBlocks(['[hello]', '', '', ' foo: bar', '', ' bro: 10'])
+ expect(blocks[0].data).toEqual({ foo: "bar", bro: 10 })
})
test('nested tag content', () => {
- const blocks = parseBlocks(['[.stack]', '', '', ' line1', '', ' line2'])
+ const { blocks } = parseBlocks(['[.stack]', '', '', ' line1', '', ' line2'])
expect(blocks.length).toBe(1)
expect(blocks[0].blocks.length).toBe(2)
@@ -44,7 +45,7 @@ test('nested tag content', () => {
})
test('subsequent blockquotes', () => {
- const blocks = parseBlocks(['> hey', '> boy', '', '> another'])
+ const { blocks } = parseBlocks(['> hey', '> boy', '', '> another'])
expect(blocks.length).toBe(3)
const html = renderBlocks(blocks)
expect(html).toStartWith('hey boy
')
@@ -52,14 +53,14 @@ test('subsequent blockquotes', () => {
test('numbered items', () => {
- const [ list ] = parseBlocks(['1. Yo', '10. Bruh', '* Bro'])
- expect(list.numbered).toBeTrue()
- expect(list.entries).toEqual([[ "Yo" ], [ "Bruh" ], [ "Bro" ]])
+ const { blocks } = parseBlocks(['1. Yo', '10. Bruh', '* Bro'])
+ expect(blocks[0].numbered).toBeTrue()
+ expect(blocks[0].entries).toEqual([[ "Yo" ], [ "Bruh" ], [ "Bro" ]])
})
test('multiple thematic breaks', () => {
- const blocks = parseBlocks(['A', '---', 'B', '---', 'C' ])
+ const { blocks } = parseBlocks(['A', '---', 'B', '---', 'C' ])
expect(blocks.length).toBe(5)
})
@@ -106,17 +107,17 @@ test('heading attr', () => {
expect(renderHeading(h)).toBe('Hey
')
- const html = renderHeading(h, { data: { heading_ids: true } })
+ const html = renderHeading(h, { heading_ids: true })
expect(html).toInclude('')
})
test('generated heading id', () => {
- const html = nuemark('# Hello', { data: { heading_ids: true } })
+ const html = nuemark('# Hello', { heading_ids: true })
expect(html).toBe('Hello
')
})
test('heading block count', () => {
- const blocks = parseBlocks(['# Yo', 'rap', '## Bruh', 'bat', '## Bro'])
+ const { blocks } = parseBlocks(['# Yo', 'rap', '## Bruh', 'bat', '## Bro'])
expect(blocks.length).toBe(5)
})
@@ -139,12 +140,12 @@ test('fenced code with caption', () => {
test('multi-line list entries', () => {
- const [ list ] = parseBlocks(['* foo', ' boy', '* bar'])
+ const list = parseBlocks(['* foo', ' boy', '* bar']).blocks[0]
expect(list.entries).toEqual([ [ "foo", "boy" ], [ "bar" ] ])
})
test('nested list', () => {
- const [ { items } ] = parseBlocks(['* > foo', ' 1. boy', ' 2. bar'])
+ const { items } = parseBlocks(['* > foo', ' 1. boy', ' 2. bar']).blocks[0]
const [ [ quote, nested ] ] = items
expect(quote.is_quote).toBeTrue()
@@ -152,13 +153,13 @@ test('nested list', () => {
})
test('blockquote', () => {
- const [ quote ] = parseBlocks(['> foo', '> boy'])
+ const [ quote ] = parseBlocks(['> foo', '> boy']).blocks
expect(quote.is_quote).toBeTrue()
expect(quote.content).toEqual([ "foo", "boy" ])
})
test('fenced code blocks', () => {
- const [ code ] = parseBlocks(['``` css.foo numbered', 'func()', '```'])
+ const [ code ] = parseBlocks(['``` css.foo numbered', 'func()', '```']).blocks
expect(code.name).toBe('css')
expect(code.attr).toEqual({ class: 'foo' })
@@ -175,7 +176,7 @@ test('parse table', () => {
]
// parse
- const [ table ] = parseBlocks(lines)
+ const [ table ] = parseBlocks(lines).blocks
expect(table.rows[1]).toEqual([ "January", "$250" ])
expect(table.rows.length).toBe(3)
expect(table.head).toBeTrue()
@@ -195,35 +196,16 @@ test('parse reflinks', () => {
])
expect(reflinks).toEqual({
- 1: '//another.net "something"',
- foo: '//website.com',
+ "1": {
+ href: "//another.net",
+ title: "something",
+ },
+ foo: {
+ href: "//website.com",
+ },
})
})
-
-test('render reflinks', () => {
- const links = { external: 'https://bar.com/zappa "External link"' }
- const html = renderLines([
- '[Hey *dude*][local]',
- 'Inlined [Second][external]',
- '[local]: /blog/yo.html "Local link"'
- ], { data: { links }})
-
- expect(html).toInclude('Hey dude')
- expect(html).toInclude('Inlined Second')
-})
-
-test.skip('footnotes', () => {
- const html = renderLines([
- 'This,[^1] [here][^a] goes.[^b]',
- '[^1]: foo',
- '[^a]: bar',
- '[^b]: baz',
- ])
-
-
-})
-
test('footnotes with [define]', () => {
const html = renderLines([
'[hey][^ki] [^ko]',
@@ -239,7 +221,7 @@ test('footnotes with [define]', () => {
test('complex tag data', () => {
- const [ comp ] = parseBlocks(['[hello#foo.bar world size="10"]', ' foo: bar'])
+ const comp = parseBlocks(['[hello#foo.bar world size="10"]', ' foo: bar']).blocks[0]
expect(comp.attr).toEqual({ class: "bar", id: "foo", })
expect(comp.data).toEqual({ world: true, size: 10, foo: "bar", })
})
diff --git a/packages/nuemark/test/document.test.js b/packages/nuemark/test/document.test.js
index f7e5f7c3..8b2847fc 100644
--- a/packages/nuemark/test/document.test.js
+++ b/packages/nuemark/test/document.test.js
@@ -1,5 +1,5 @@
-import { parseDocument, stripMeta, sectionize } from '../src/document.js'
+import { parseDocument, stripMeta, sectionize } from '../src/parse-document.js'
import { parseBlocks } from '../src/parse-blocks.js'
test('front matter', () => {
@@ -49,15 +49,15 @@ test('sectionize', () => {
['lol', '---', 'bol'],
]
- for (const blocks of tests) {
- const headings = parseBlocks(blocks)
- expect(sectionize(headings).length).toBe(2)
+ for (const test of tests) {
+ const { blocks } = parseBlocks(test)
+ expect(sectionize(blocks).length).toBe(2)
}
})
test('non section', () => {
- const paragraphs = parseBlocks(['hello', 'world'])
- expect(sectionize(paragraphs)).toBeUndefined()
+ const { blocks } = parseBlocks(['hello', 'world'])
+ expect(sectionize(blocks)).toBeUndefined()
})
test('single section', () => {
@@ -66,19 +66,51 @@ test('single section', () => {
})
test('multiple sections', () => {
- const doc = parseDocument([
+ const lines = [
'# Hello', 'World',
'## Foo', 'Bar',
'---', 'Bruh', '***',
- ])
+ ]
+ const doc = parseDocument(lines)
expect(doc.sections.length).toBe(2)
- const html = doc.render({ data: { sections: ['hero'] }})
+
+ const html = doc.render({ sections: ['hero'] })
expect(html).toStartWith('Hello
')
expect(html).toEndWith('
')
})
+test('render reflinks', () => {
+ const links = { external: 'https://bar.com/zappa "External link"' }
+
+ const doc = parseDocument([
+ '[Hey *dude*][local]',
+ 'Inlined [Second][external]',
+ '[local]: /blog/yo.html "Local link"'
+ ])
+
+ const html = doc.render({ links })
+ expect(html).toInclude('Hey dude')
+ expect(html).toInclude('Inlined Second')
+})
+
+
+test('footnotes', () => {
+ const doc = parseDocument([
+ 'This,[^1] [here][^a] goes.[^b]',
+ '[^1]: foo',
+ '[^a]: bar',
+ '[^b]: baz',
+ ])
+
+ const html = doc.render()
+ expect(html).toInclude('')
+ expect(html).toInclude('- foo
')
+})
+
+
+
test('table of contents', () => {
const doc = parseDocument([
'# Hello', 'World',
diff --git a/packages/nuemark/test/inline.test.js b/packages/nuemark/test/inline.test.js
index 23ea191b..80214615 100644
--- a/packages/nuemark/test/inline.test.js
+++ b/packages/nuemark/test/inline.test.js
@@ -182,27 +182,25 @@ test('parse complex Wikipedia-style link', () => {
test('parse footnote link', () => {
const link = parseLink('[Hello][^1]', true)
- expect(link.is_footnote).toBe(true)
expect(link.href).toBe('^1')
})
test('parse footnote ref', () => {
const [text, tag] = parseInline('Hello [^1]', true)
- expect(tag.is_footnote).toBe(true)
expect(tag.href).toBe('^1')
})
test('render footnote link', () => {
- const footnotes = ['^1', '^go']
- const rel = { is_footnote: true, href: '^go' }
- const html = renderToken(rel, { footnotes })
+ const noterefs = ['^1', '^go']
+ const rel = { href: '^go' }
+ const html = renderToken(rel, { noterefs })
expect(html).toStartWith('')
expect(html).toInclude('2')
})
test('footnote mix', () => {
- const html = renderInline('[a][^1] b [^1]', { footnotes: ['^1'] })
+ const html = renderInline('[a][^1] b [^1]', { noterefs: ['^1'] })
expect(html).toInclude('a')
})