Skip to content

Commit f1a9042

Browse files
committed
Refactor to move implementation to lib/
1 parent ff79ea3 commit f1a9042

File tree

3 files changed

+176
-168
lines changed

3 files changed

+176
-168
lines changed

index.js

+4-168
Original file line numberDiff line numberDiff line change
@@ -1,171 +1,7 @@
11
/**
2-
* @typedef {import('mdast').Literal} Literal
3-
* @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension
4-
* @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext
5-
* @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle
6-
* @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension
7-
*
8-
* @typedef {import('micromark-extension-frontmatter/matters.js').Options} Options
9-
* @typedef {import('micromark-extension-frontmatter/matters.js').Matter} Matter
10-
* @typedef {import('micromark-extension-frontmatter/matters.js').Info} Info
2+
* @typedef {import('./lib/index.js').Info} Info
3+
* @typedef {import('./lib/index.js').Matter} Matter
4+
* @typedef {import('./lib/index.js').Options} Options
115
*/
126

13-
import {matters} from 'micromark-extension-frontmatter/matters.js'
14-
15-
/**
16-
* Create an extension for `mdast-util-from-markdown`.
17-
*
18-
* @param {Options | null | undefined} [options]
19-
* Configuration.
20-
* @returns {FromMarkdownExtension}
21-
* Extension for `mdast-util-from-markdown`.
22-
*/
23-
export function frontmatterFromMarkdown(options) {
24-
// @ts-expect-error: `micromark-extension-frontmatter` should fix types to
25-
// accept `null` as options.
26-
const settings = matters(options)
27-
/** @type {FromMarkdownExtension['enter']} */
28-
const enter = {}
29-
/** @type {FromMarkdownExtension['exit']} */
30-
const exit = {}
31-
let index = -1
32-
33-
while (++index < settings.length) {
34-
const matter = settings[index]
35-
enter[matter.type] = opener(matter)
36-
exit[matter.type] = close
37-
exit[matter.type + 'Value'] = value
38-
}
39-
40-
return {enter, exit}
41-
}
42-
43-
/**
44-
* @param {Matter} matter
45-
* @returns {FromMarkdownHandle} enter
46-
*/
47-
function opener(matter) {
48-
return open
49-
50-
/**
51-
* @this {CompileContext}
52-
* @type {FromMarkdownHandle}
53-
*/
54-
function open(token) {
55-
// @ts-expect-error: custom.
56-
this.enter({type: matter.type, value: ''}, token)
57-
this.buffer()
58-
}
59-
}
60-
61-
/**
62-
* @this {CompileContext}
63-
* @type {FromMarkdownHandle}
64-
*/
65-
function close(token) {
66-
const data = this.resume()
67-
const node = /** @type {Literal} */ (this.exit(token))
68-
// Remove the initial and final eol.
69-
node.value = data.replace(/^(\r?\n|\r)|(\r?\n|\r)$/g, '')
70-
}
71-
72-
/**
73-
* @this {CompileContext}
74-
* @type {FromMarkdownHandle}
75-
*/
76-
function value(token) {
77-
this.config.enter.data.call(this, token)
78-
this.config.exit.data.call(this, token)
79-
}
80-
81-
/**
82-
* Create an extension for `mdast-util-to-markdown`.
83-
*
84-
* @param {Options | null | undefined} [options]
85-
* Configuration.
86-
* @returns {ToMarkdownExtension}
87-
* Extension for `mdast-util-to-markdown`.
88-
*/
89-
export function frontmatterToMarkdown(options) {
90-
// To do: use an extension object with `satisfies` later.
91-
/** @type {ToMarkdownExtension['unsafe']} */
92-
const unsafe = []
93-
/** @type {ToMarkdownExtension['handlers']} */
94-
const handlers = {}
95-
// @ts-expect-error: `micromark-extension-frontmatter` should fix types to
96-
// accept `null` as options.
97-
const settings = matters(options)
98-
let index = -1
99-
100-
while (++index < settings.length) {
101-
const matter = settings[index]
102-
103-
// @ts-expect-error: this can add custom frontmatter nodes.
104-
// Typing those is the responsibility of the end user.
105-
handlers[matter.type] = handler(matter)
106-
107-
// To do: idea: perhaps make this smarter, with an `after` of the second char?
108-
unsafe.push({atBreak: true, character: fence(matter, 'open').charAt(0)})
109-
}
110-
111-
return {unsafe, handlers}
112-
}
113-
114-
/**
115-
* Create a handle that can serialize a frontmatter node as markdown.
116-
*
117-
* @param {Matter} matter
118-
* Structure.
119-
* @returns {(node: Literal) => string} enter
120-
* Handler.
121-
*/
122-
function handler(matter) {
123-
const open = fence(matter, 'open')
124-
const close = fence(matter, 'close')
125-
126-
return handle
127-
128-
/**
129-
* Serialize a frontmatter node as markdown.
130-
*
131-
* @param {Literal} node
132-
* Node to serialize.
133-
* @returns {string}
134-
* Serialized node.
135-
*/
136-
function handle(node) {
137-
return open + (node.value ? '\n' + node.value : '') + '\n' + close
138-
}
139-
}
140-
141-
/**
142-
* Get an `open` or `close` fence.
143-
*
144-
* @param {Matter} matter
145-
* Structure.
146-
* @param {'open' | 'close'} prop
147-
* Field to get.
148-
* @returns {string}
149-
* Fence.
150-
*/
151-
function fence(matter, prop) {
152-
return matter.marker
153-
? pick(matter.marker, prop).repeat(3)
154-
: // @ts-expect-error: They’re mutually exclusive.
155-
pick(matter.fence, prop)
156-
}
157-
158-
/**
159-
* Take `open` or `close` fields when schema is an info object, or use the
160-
* given value when it is a string.
161-
*
162-
* @param {Info | string} schema
163-
* Info object or value.
164-
* @param {'open' | 'close'} prop
165-
* Field to get.
166-
* @returns {string}
167-
* Thing to use for the opening or closing.
168-
*/
169-
function pick(schema, prop) {
170-
return typeof schema === 'string' ? schema : schema[prop]
171-
}
7+
export {frontmatterFromMarkdown, frontmatterToMarkdown} from './lib/index.js'

lib/index.js

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/**
2+
* @typedef {import('mdast').Literal} Literal
3+
* @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension
4+
* @typedef {import('mdast-util-from-markdown').CompileContext} CompileContext
5+
* @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle
6+
* @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension
7+
*
8+
* @typedef {import('micromark-extension-frontmatter/matters.js').Options} Options
9+
* @typedef {import('micromark-extension-frontmatter/matters.js').Matter} Matter
10+
* @typedef {import('micromark-extension-frontmatter/matters.js').Info} Info
11+
*/
12+
13+
import {matters} from 'micromark-extension-frontmatter/matters.js'
14+
15+
/**
16+
* Create an extension for `mdast-util-from-markdown`.
17+
*
18+
* @param {Options | null | undefined} [options]
19+
* Configuration.
20+
* @returns {FromMarkdownExtension}
21+
* Extension for `mdast-util-from-markdown`.
22+
*/
23+
export function frontmatterFromMarkdown(options) {
24+
// @ts-expect-error: `micromark-extension-frontmatter` should fix types to
25+
// accept `null` as options.
26+
const settings = matters(options)
27+
/** @type {FromMarkdownExtension['enter']} */
28+
const enter = {}
29+
/** @type {FromMarkdownExtension['exit']} */
30+
const exit = {}
31+
let index = -1
32+
33+
while (++index < settings.length) {
34+
const matter = settings[index]
35+
enter[matter.type] = opener(matter)
36+
exit[matter.type] = close
37+
exit[matter.type + 'Value'] = value
38+
}
39+
40+
return {enter, exit}
41+
}
42+
43+
/**
44+
* @param {Matter} matter
45+
* @returns {FromMarkdownHandle} enter
46+
*/
47+
function opener(matter) {
48+
return open
49+
50+
/**
51+
* @this {CompileContext}
52+
* @type {FromMarkdownHandle}
53+
*/
54+
function open(token) {
55+
// @ts-expect-error: custom.
56+
this.enter({type: matter.type, value: ''}, token)
57+
this.buffer()
58+
}
59+
}
60+
61+
/**
62+
* @this {CompileContext}
63+
* @type {FromMarkdownHandle}
64+
*/
65+
function close(token) {
66+
const data = this.resume()
67+
const node = /** @type {Literal} */ (this.exit(token))
68+
// Remove the initial and final eol.
69+
node.value = data.replace(/^(\r?\n|\r)|(\r?\n|\r)$/g, '')
70+
}
71+
72+
/**
73+
* @this {CompileContext}
74+
* @type {FromMarkdownHandle}
75+
*/
76+
function value(token) {
77+
this.config.enter.data.call(this, token)
78+
this.config.exit.data.call(this, token)
79+
}
80+
81+
/**
82+
* Create an extension for `mdast-util-to-markdown`.
83+
*
84+
* @param {Options | null | undefined} [options]
85+
* Configuration.
86+
* @returns {ToMarkdownExtension}
87+
* Extension for `mdast-util-to-markdown`.
88+
*/
89+
export function frontmatterToMarkdown(options) {
90+
// To do: use an extension object with `satisfies` later.
91+
/** @type {ToMarkdownExtension['unsafe']} */
92+
const unsafe = []
93+
/** @type {ToMarkdownExtension['handlers']} */
94+
const handlers = {}
95+
// @ts-expect-error: `micromark-extension-frontmatter` should fix types to
96+
// accept `null` as options.
97+
const settings = matters(options)
98+
let index = -1
99+
100+
while (++index < settings.length) {
101+
const matter = settings[index]
102+
103+
// @ts-expect-error: this can add custom frontmatter nodes.
104+
// Typing those is the responsibility of the end user.
105+
handlers[matter.type] = handler(matter)
106+
107+
// To do: idea: perhaps make this smarter, with an `after` of the second char?
108+
unsafe.push({atBreak: true, character: fence(matter, 'open').charAt(0)})
109+
}
110+
111+
return {unsafe, handlers}
112+
}
113+
114+
/**
115+
* Create a handle that can serialize a frontmatter node as markdown.
116+
*
117+
* @param {Matter} matter
118+
* Structure.
119+
* @returns {(node: Literal) => string} enter
120+
* Handler.
121+
*/
122+
function handler(matter) {
123+
const open = fence(matter, 'open')
124+
const close = fence(matter, 'close')
125+
126+
return handle
127+
128+
/**
129+
* Serialize a frontmatter node as markdown.
130+
*
131+
* @param {Literal} node
132+
* Node to serialize.
133+
* @returns {string}
134+
* Serialized node.
135+
*/
136+
function handle(node) {
137+
return open + (node.value ? '\n' + node.value : '') + '\n' + close
138+
}
139+
}
140+
141+
/**
142+
* Get an `open` or `close` fence.
143+
*
144+
* @param {Matter} matter
145+
* Structure.
146+
* @param {'open' | 'close'} prop
147+
* Field to get.
148+
* @returns {string}
149+
* Fence.
150+
*/
151+
function fence(matter, prop) {
152+
return matter.marker
153+
? pick(matter.marker, prop).repeat(3)
154+
: // @ts-expect-error: They’re mutually exclusive.
155+
pick(matter.fence, prop)
156+
}
157+
158+
/**
159+
* Take `open` or `close` fields when schema is an info object, or use the
160+
* given value when it is a string.
161+
*
162+
* @param {Info | string} schema
163+
* Info object or value.
164+
* @param {'open' | 'close'} prop
165+
* Field to get.
166+
* @returns {string}
167+
* Thing to use for the opening or closing.
168+
*/
169+
function pick(schema, prop) {
170+
return typeof schema === 'string' ? schema : schema[prop]
171+
}

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"main": "index.js",
3232
"types": "index.d.ts",
3333
"files": [
34+
"lib/",
3435
"index.d.ts",
3536
"index.js"
3637
],

0 commit comments

Comments
 (0)