Skip to content

Commit 38c2aa8

Browse files
Add types
Closes GH-20. Closes GH-21. Reviewed-by: Jonathan Haines <[email protected]> Reviewed-by: Christian Murphy <[email protected]> Reviewed-by: Titus Wormer <[email protected]>
1 parent ea21109 commit 38c2aa8

5 files changed

+305
-2
lines changed

package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
"Titus Wormer <[email protected]> (https://wooorm.com)",
2727
"Jason Switzer <[email protected]>"
2828
],
29+
"types": "types/index.d.ts",
2930
"files": [
31+
"types/index.d.ts",
3032
"lib",
3133
"index.js"
3234
],
@@ -36,8 +38,9 @@
3638
"devDependencies": {
3739
"browserify": "^16.0.0",
3840
"deepmerge": "^4.0.0",
41+
"dtslint": "^3.6.12",
3942
"hast-util-to-html": "^7.0.0",
40-
"hastscript": "^5.0.0",
43+
"hastscript": "^6.0.0",
4144
"nyc": "^15.0.0",
4245
"prettier": "^2.0.0",
4346
"remark-cli": "^8.0.0",
@@ -54,7 +57,8 @@
5457
"build": "npm run build-bundle && npm run build-mangle",
5558
"test-api": "node test",
5659
"test-coverage": "nyc --reporter lcov tape test.js",
57-
"test": "npm run format && npm run build && npm run test-coverage"
60+
"test-types": "dtslint types",
61+
"test": "npm run format && npm run build && npm run test-coverage && npm run test-types"
5862
},
5963
"nyc": {
6064
"check-coverage": true,

types/hast-util-sanitize-tests.ts

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
import h = require('hastscript')
2+
import u = require('unist-builder')
3+
import merge = require('deepmerge')
4+
import sanitize = require('hast-util-sanitize')
5+
6+
// Taken from Readme
7+
const tree = h('div', {onmouseover: 'alert("alpha")'}, [
8+
h(
9+
'a',
10+
{href: 'jAva script:alert("bravo")', onclick: 'alert("charlie")'},
11+
'delta'
12+
),
13+
u('text', '\n'),
14+
h('script', 'alert("charlie")'),
15+
u('text', '\n'),
16+
h('img', {src: 'x', onerror: 'alert("delta")'}),
17+
u('text', '\n'),
18+
// eslint-disable-next-line no-script-url
19+
h('iframe', {src: 'javascript:alert("echo")'}),
20+
u('text', '\n'),
21+
h('math', h('mi', {'xlink:href': 'data:x,<script>alert("foxtrot")</script>'}))
22+
])
23+
24+
const gh: sanitize.Schema = {
25+
strip: ['script'],
26+
clobberPrefix: 'user-content-',
27+
clobber: ['name', 'id'],
28+
ancestors: {
29+
tbody: ['table'],
30+
tfoot: ['table'],
31+
thead: ['table'],
32+
td: ['table'],
33+
th: ['table'],
34+
tr: ['table']
35+
},
36+
protocols: {
37+
href: ['http', 'https', 'mailto', 'xmpp', 'irc', 'ircs'],
38+
cite: ['http', 'https'],
39+
src: ['http', 'https'],
40+
longDesc: ['http', 'https']
41+
},
42+
tagNames: [
43+
'h1',
44+
'h2',
45+
'h3',
46+
'h4',
47+
'h5',
48+
'h6',
49+
'br',
50+
'b',
51+
'i',
52+
'strong',
53+
'em',
54+
'a',
55+
'pre',
56+
'code',
57+
'img',
58+
'tt',
59+
'div',
60+
'ins',
61+
'del',
62+
'sup',
63+
'sub',
64+
'p',
65+
'ol',
66+
'ul',
67+
'table',
68+
'thead',
69+
'tbody',
70+
'tfoot',
71+
'blockquote',
72+
'dl',
73+
'dt',
74+
'dd',
75+
'kbd',
76+
'q',
77+
'samp',
78+
'var',
79+
'hr',
80+
'ruby',
81+
'rt',
82+
'rp',
83+
'li',
84+
'tr',
85+
'td',
86+
'th',
87+
's',
88+
'strike',
89+
'summary',
90+
'details',
91+
'caption',
92+
'figure',
93+
'figcaption',
94+
'abbr',
95+
'bdo',
96+
'cite',
97+
'dfn',
98+
'mark',
99+
'small',
100+
'span',
101+
'time',
102+
'wbr',
103+
'input'
104+
],
105+
attributes: {
106+
a: ['href'],
107+
img: ['src', 'longDesc'],
108+
input: [
109+
['type', 'checkbox'],
110+
['disabled', true]
111+
],
112+
li: [['className', 'task-list-item']],
113+
div: ['itemScope', 'itemType'],
114+
blockquote: ['cite'],
115+
del: ['cite'],
116+
ins: ['cite'],
117+
q: ['cite'],
118+
'*': [
119+
'abbr',
120+
'accept',
121+
'acceptCharset',
122+
'accessKey',
123+
'action',
124+
'align',
125+
'alt',
126+
'ariaDescribedBy',
127+
'ariaHidden',
128+
'ariaLabel',
129+
'ariaLabelledBy',
130+
'axis',
131+
'border',
132+
'cellPadding',
133+
'cellSpacing',
134+
'char',
135+
'charOff',
136+
'charSet',
137+
'checked',
138+
'clear',
139+
'cols',
140+
'colSpan',
141+
'color',
142+
'compact',
143+
'coords',
144+
'dateTime',
145+
'dir',
146+
'disabled',
147+
'encType',
148+
'htmlFor',
149+
'frame',
150+
'headers',
151+
'height',
152+
'hrefLang',
153+
'hSpace',
154+
'isMap',
155+
'id',
156+
'label',
157+
'lang',
158+
'maxLength',
159+
'media',
160+
'method',
161+
'multiple',
162+
'name',
163+
'noHref',
164+
'noShade',
165+
'noWrap',
166+
'open',
167+
'prompt',
168+
'readOnly',
169+
'rel',
170+
'rev',
171+
'rows',
172+
'rowSpan',
173+
'rules',
174+
'scope',
175+
'selected',
176+
'shape',
177+
'size',
178+
'span',
179+
'start',
180+
'summary',
181+
'tabIndex',
182+
'target',
183+
'title',
184+
'type',
185+
'useMap',
186+
'vAlign',
187+
'value',
188+
'vSpace',
189+
'width',
190+
'itemProp'
191+
]
192+
},
193+
required: {
194+
input: {
195+
type: 'checkbox',
196+
disabled: true
197+
}
198+
}
199+
}
200+
201+
const schema = merge(gh, {attributes: {'*': ['className']}})
202+
203+
sanitize(tree)
204+
sanitize(tree, schema)

types/index.d.ts

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import {Node} from 'unist'
2+
3+
declare namespace sanitize {
4+
/**
5+
* Possible HTML attribute values
6+
*/
7+
type HTMLValue = string | number | boolean
8+
9+
/**
10+
* Sanitization configuration
11+
*/
12+
interface Schema {
13+
/**
14+
* Map of tag names to allowed property names
15+
*
16+
* The special '*' key defines property names allowed on all elements
17+
*/
18+
attributes?: {
19+
[key: string]: Array<string | [string, ...HTMLValue[]]>
20+
}
21+
22+
/**
23+
* Map of tag names to required property names and their default property value
24+
*/
25+
required?: {[key: string]: {[key: string]: HTMLValue}}
26+
27+
/**
28+
* List of allowed tag names
29+
*/
30+
tagNames?: string[]
31+
32+
/**
33+
* Map of protocols to allow in property values
34+
*/
35+
protocols?: {[key: string]: string[]}
36+
37+
/**
38+
* Map of tag names to their required ancestor elements
39+
*/
40+
ancestors?: {[key: string]: string[]}
41+
42+
/**
43+
* List of allowed property names which can clobber
44+
*/
45+
clobber?: string[]
46+
47+
/**
48+
* Prefix to use before potentially clobbering property names
49+
*/
50+
clobberPrefix?: string
51+
52+
/**
53+
* Names of elements to strip from the tree
54+
*/
55+
strip?: string[]
56+
57+
/**
58+
* Whether to allow comments
59+
*/
60+
allowComments?: boolean
61+
62+
/**
63+
* Whether to allow doctypes
64+
*/
65+
allowDoctypes?: boolean
66+
}
67+
}
68+
69+
/**
70+
* Hast utility to sanitize a tree
71+
*
72+
* @param tree Hast tree to sanitize
73+
* @param schema Schema defining how to sanitize - defaults to Github style sanitation
74+
*/
75+
declare function sanitize(tree: Node, schema?: sanitize.Schema): Node
76+
77+
export = sanitize

types/tsconfig.json

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"compilerOptions": {
3+
"lib": ["es2015"],
4+
"strict": true,
5+
"baseUrl": ".",
6+
"resolveJsonModule": true,
7+
"paths": {
8+
"hast-util-sanitize": ["index.d.ts"]
9+
}
10+
}
11+
}

types/tslint.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"extends": "dtslint/dtslint.json",
3+
"rules": {
4+
"semicolon": false,
5+
"whitespace": false
6+
}
7+
}

0 commit comments

Comments
 (0)