Skip to content

Commit 043e021

Browse files
committed
.
0 parents  commit 043e021

12 files changed

+840
-0
lines changed

.editorconfig

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true

.github/workflows/bb.yml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: bb
2+
on:
3+
issues:
4+
types: [opened, reopened, edited, closed, labeled, unlabeled]
5+
pull_request_target:
6+
types: [opened, reopened, edited, closed, labeled, unlabeled]
7+
jobs:
8+
main:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: unifiedjs/beep-boop-beta@main
12+
with:
13+
repo-token: ${{secrets.GITHUB_TOKEN}}

.github/workflows/main.yml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: main
2+
on:
3+
- pull_request
4+
- push
5+
jobs:
6+
main:
7+
name: ${{matrix.node}}
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- uses: dcodeIO/setup-node-nvm@master
12+
with:
13+
node-version: ${{matrix.node}}
14+
- run: npm install
15+
- run: npm test
16+
- uses: codecov/codecov-action@v1
17+
strategy:
18+
matrix:
19+
node:
20+
- lts/erbium
21+
- node

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
coverage/
2+
node_modules/
3+
.DS_Store
4+
*.d.ts
5+
*.log
6+
yarn.lock

.npmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

.prettierignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
coverage/
2+
*.md

index.js

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/**
2+
* @typedef {import('mdast').FootnoteReference} FootnoteReference
3+
* @typedef {import('mdast').FootnoteDefinition} FootnoteDefinition
4+
* @typedef {import('mdast-util-from-markdown').Extension} FromMarkdownExtension
5+
* @typedef {import('mdast-util-from-markdown').Handle} FromMarkdownHandle
6+
* @typedef {import('mdast-util-to-markdown').Options} ToMarkdownExtension
7+
* @typedef {import('mdast-util-to-markdown').Handle} ToMarkdownHandle
8+
* @typedef {import('mdast-util-to-markdown').Map} Map
9+
*/
10+
11+
import {normalizeIdentifier} from 'micromark-util-normalize-identifier'
12+
import {association} from 'mdast-util-to-markdown/lib/util/association.js'
13+
import {containerFlow} from 'mdast-util-to-markdown/lib/util/container-flow.js'
14+
import {indentLines} from 'mdast-util-to-markdown/lib/util/indent-lines.js'
15+
import {safe} from 'mdast-util-to-markdown/lib/util/safe.js'
16+
import {visit, EXIT} from 'unist-util-visit'
17+
18+
let warningColonInFootnote = false
19+
let warningListInFootnote = false
20+
21+
/**
22+
* @returns {FromMarkdownExtension}
23+
*/
24+
export function gfmFootnoteFromMarkdown() {
25+
return {
26+
enter: {
27+
gfmFootnoteDefinition: enterFootnoteDefinition,
28+
gfmFootnoteDefinitionLabelString: enterFootnoteDefinitionLabelString,
29+
gfmFootnoteCall: enterFootnoteCall,
30+
gfmFootnoteCallString: enterFootnoteCallString
31+
},
32+
exit: {
33+
gfmFootnoteDefinition: exitFootnoteDefinition,
34+
gfmFootnoteDefinitionLabelString: exitFootnoteDefinitionLabelString,
35+
gfmFootnoteCall: exitFootnoteCall,
36+
gfmFootnoteCallString: exitFootnoteCallString
37+
}
38+
}
39+
40+
/** @type {FromMarkdownHandle} */
41+
function enterFootnoteDefinition(token) {
42+
this.enter(
43+
{type: 'footnoteDefinition', identifier: '', label: '', children: []},
44+
token
45+
)
46+
}
47+
48+
/** @type {FromMarkdownHandle} */
49+
function enterFootnoteDefinitionLabelString() {
50+
this.buffer()
51+
}
52+
53+
/** @type {FromMarkdownHandle} */
54+
function exitFootnoteDefinitionLabelString(token) {
55+
const label = this.resume()
56+
const node = /** @type {FootnoteDefinition} */ (
57+
this.stack[this.stack.length - 1]
58+
)
59+
node.label = label
60+
node.identifier = normalizeIdentifier(
61+
this.sliceSerialize(token)
62+
).toLowerCase()
63+
}
64+
65+
/** @type {FromMarkdownHandle} */
66+
function exitFootnoteDefinition(token) {
67+
this.exit(token)
68+
}
69+
70+
/** @type {FromMarkdownHandle} */
71+
function enterFootnoteCall(token) {
72+
this.enter({type: 'footnoteReference', identifier: '', label: ''}, token)
73+
}
74+
75+
/** @type {FromMarkdownHandle} */
76+
function enterFootnoteCallString() {
77+
this.buffer()
78+
}
79+
80+
/** @type {FromMarkdownHandle} */
81+
function exitFootnoteCallString(token) {
82+
const label = this.resume()
83+
const node = /** @type {FootnoteDefinition} */ (
84+
this.stack[this.stack.length - 1]
85+
)
86+
node.label = label
87+
node.identifier = normalizeIdentifier(
88+
this.sliceSerialize(token)
89+
).toLowerCase()
90+
}
91+
92+
/** @type {FromMarkdownHandle} */
93+
function exitFootnoteCall(token) {
94+
this.exit(token)
95+
}
96+
}
97+
98+
/**
99+
* @returns {ToMarkdownExtension}
100+
*/
101+
export function gfmFootnoteToMarkdown() {
102+
footnoteReference.peek = footnoteReferencePeek
103+
104+
return {
105+
// This is on by default already.
106+
unsafe: [{character: '[', inConstruct: ['phrasing', 'label', 'reference']}],
107+
handlers: {footnoteDefinition, footnoteReference}
108+
}
109+
110+
/**
111+
* @type {ToMarkdownHandle}
112+
* @param {FootnoteReference} node
113+
*/
114+
function footnoteReference(node, _, context) {
115+
const exit = context.enter('footnoteReference')
116+
const subexit = context.enter('reference')
117+
const reference = safe(context, association(node), {
118+
before: '^',
119+
after: ']'
120+
})
121+
subexit()
122+
exit()
123+
return '[^' + reference + ']'
124+
}
125+
126+
/** @type {ToMarkdownHandle} */
127+
function footnoteReferencePeek() {
128+
return '['
129+
}
130+
131+
/**
132+
* @type {ToMarkdownHandle}
133+
* @param {FootnoteDefinition} node
134+
*/
135+
function footnoteDefinition(node, _, context) {
136+
const exit = context.enter('footnoteDefinition')
137+
const subexit = context.enter('label')
138+
const id = safe(context, association(node), {before: '^', after: ']'})
139+
const label = '[^' + id + ']:'
140+
subexit()
141+
const value = indentLines(containerFlow(node, context), map)
142+
exit()
143+
144+
if (!warningColonInFootnote && id.includes(':')) {
145+
console.warn(
146+
'[mdast-util-gfm-footnote] Warning: Found a colon in footnote identifier `' +
147+
id +
148+
'`. GitHub currently crahes on colons in footnotes (see <https://github.com/github/cmark-gfm/issues/241> for more info)'
149+
)
150+
warningColonInFootnote = true
151+
}
152+
153+
if (!warningListInFootnote) {
154+
visit(node, 'list', () => {
155+
console.warn(
156+
'[mdast-util-gfm-footnote] Warning: Found a list in a footnote definition. GitHub currently crahes on lists in footnotes (see <https://github.com/github/cmark-gfm/issues/241> for more info)'
157+
)
158+
warningListInFootnote = true
159+
return EXIT
160+
})
161+
}
162+
163+
return value
164+
165+
/** @type {Map} */
166+
function map(line, index, blank) {
167+
if (index) {
168+
return (blank ? '' : ' ') + line
169+
}
170+
171+
return (blank ? label : label + ' ') + line
172+
}
173+
}
174+
}

license

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
(The MIT License)
2+
3+
Copyright (c) 2021 Titus Wormer <tituswormer@gmail.com>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining
6+
a copy of this software and associated documentation files (the
7+
'Software'), to deal in the Software without restriction, including
8+
without limitation the rights to use, copy, modify, merge, publish,
9+
distribute, sublicense, and/or sell copies of the Software, and to
10+
permit persons to whom the Software is furnished to do so, subject to
11+
the following conditions:
12+
13+
The above copyright notice and this permission notice shall be
14+
included in all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package.json

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
{
2+
"name": "mdast-util-gfm-footnote",
3+
"version": "0.0.0",
4+
"description": "mdast extension to parse and serialize GFM footnotes",
5+
"license": "MIT",
6+
"keywords": [
7+
"unist",
8+
"mdast",
9+
"mdast-util",
10+
"util",
11+
"utility",
12+
"markdown",
13+
"markup",
14+
"gfm",
15+
"footnote",
16+
"note"
17+
],
18+
"repository": "syntax-tree/mdast-util-gfm-footnote",
19+
"bugs": "https://github.com/syntax-tree/mdast-util-gfm-footnote/issues",
20+
"funding": {
21+
"type": "opencollective",
22+
"url": "https://opencollective.com/unified"
23+
},
24+
"author": "Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)",
25+
"contributors": [
26+
"Titus Wormer <tituswormer@gmail.com> (https://wooorm.com)"
27+
],
28+
"sideEffects": false,
29+
"type": "module",
30+
"main": "index.js",
31+
"types": "index.d.ts",
32+
"files": [
33+
"index.d.ts",
34+
"index.js"
35+
],
36+
"dependencies": {
37+
"@types/mdast": "^3.0.0",
38+
"mdast-util-to-markdown": "^1.0.0",
39+
"micromark-util-normalize-identifier": "^1.0.0",
40+
"unist-util-visit": "^4.0.0"
41+
},
42+
"devDependencies": {
43+
"@types/tape": "^4.0.0",
44+
"c8": "^7.0.0",
45+
"mdast-util-from-markdown": "^1.0.0",
46+
"micromark-extension-gfm-footnote": "^1.0.0",
47+
"prettier": "^2.0.0",
48+
"remark-cli": "^10.0.0",
49+
"remark-preset-wooorm": "^9.0.0",
50+
"rimraf": "^3.0.0",
51+
"tape": "^5.0.0",
52+
"type-coverage": "^2.0.0",
53+
"typescript": "^4.0.0",
54+
"xo": "^0.45.0"
55+
},
56+
"scripts": {
57+
"build": "rimraf \"*.d.ts\" && tsc && type-coverage",
58+
"format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
59+
"test-api": "node --conditions development test.js",
60+
"test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov node --conditions development test.js",
61+
"test": "npm run build && npm run format && npm run test-coverage"
62+
},
63+
"prettier": {
64+
"tabWidth": 2,
65+
"useTabs": false,
66+
"singleQuote": true,
67+
"bracketSpacing": false,
68+
"semi": false,
69+
"trailingComma": "none"
70+
},
71+
"xo": {
72+
"prettier": true
73+
},
74+
"remarkConfig": {
75+
"plugins": [
76+
"preset-wooorm"
77+
]
78+
},
79+
"typeCoverage": {
80+
"atLeast": 100,
81+
"detail": true,
82+
"strict": true,
83+
"ignoreCatch": true
84+
}
85+
}

0 commit comments

Comments
 (0)