forked from rehypejs/rehype-minify
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
145 lines (135 loc) · 4.04 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/**
* rehype plugin to remove `meta[http-equiv=content-language]` and
* `meta[http-equiv=content-type]`.
*
* ## What is this?
*
* This package is a plugin that removes `<meta>` elements with `http-equiv`
* attributes.
* These `<meta>` elements can set the character encoding and natural language
* of the document, but there are shorter ways to do that.
*
* ## When should I use this?
*
* You can use this plugin when you want to improve the transfer size of HTML
* documents.
*
* ## API
*
* ### `unified().use(rehypeRemoveMetaHttpEquiv)`
*
* Remove `meta[http-equiv=content-language]` and
* `meta[http-equiv=content-type]`.
* There are no options.
*
* @example
* {"processor": {"fragment": false}, "format": true}
* <!doctype html>
* <html lang="en-GB">
* <head>
* <meta charset="utf8">
* <meta http-equiv="content-type" content="text/html; charset=chinese">
* <meta http-equiv="content-language" content="en-US">
* </head>
* <body></body>
* </html>
*/
/**
* @typedef {import('hast').Root} Root
* @typedef {import('hast').Element} Element
* @typedef {import('hast').Parent} Parent
*/
import {visit} from 'unist-util-visit'
import {stringify} from 'space-separated-tokens'
import {hasProperty} from 'hast-util-has-property'
/**
* Remove `meta[http-equiv=content-language]` and
* `meta[http-equiv=content-type]` elements for shorter output.
*
* @type {import('unified').Plugin<Array<void>, Root>}
*/
export default function rehypeRemoveMetaHttpEquiv() {
return (tree) => {
/** @type {Element|undefined} */
let html
/** @type {Element|undefined} */
let head
/** @type {Element|undefined} */
let charSet
/** @type {Element|undefined} */
let contentType
/** @type {Element|undefined} */
let contentLanguage
/** @type {Parent|null|undefined} */
let contentTypeParent
/** @type {Parent|null|undefined} */
let contentLanguageParent
visit(tree, 'element', (node, _, parent) => {
// Stop walking as we only need the `head`.
if (node.tagName === 'body') {
return false
}
if (node.tagName === 'html') {
html = node
} else if (node.tagName === 'head') {
head = node
} else if (node.tagName === 'meta' && node.properties) {
if (hasProperty(node, 'charSet')) {
charSet = node
} else if (
hasProperty(node, 'httpEquiv') &&
Array.isArray(node.properties.httpEquiv)
) {
const value = stringify(node.properties.httpEquiv).toLowerCase()
if (value === 'content-language') {
contentLanguage = node
contentLanguageParent = parent
} else if (value === 'content-type') {
contentType = node
contentTypeParent = parent
}
}
}
})
// `meta` has precedence over `html[lang]`:
// <https://html.spec.whatwg.org/#the-lang-and-xml:lang-attributes:pragma-set-default-language>
if (
html &&
html.properties &&
contentLanguage &&
contentLanguage.properties &&
contentLanguageParent
) {
html.properties.lang = contentLanguage.properties.content
contentLanguageParent.children.splice(
contentLanguageParent.children.indexOf(contentLanguage),
1
)
}
// `meta` has precedence over `meta[charset]`.
if (contentTypeParent && contentType && contentType.properties) {
const value = String(contentType.properties.content).replace(
/^.+charset=/i,
''
)
if (charSet && charSet.properties) {
charSet.properties.charSet = value
contentTypeParent.children.splice(
contentTypeParent.children.indexOf(contentType),
1
)
} else if (head) {
head.children.unshift({
type: 'element',
tagName: 'meta',
properties: {charSet: value},
children: []
})
contentTypeParent.children.splice(
contentTypeParent.children.indexOf(contentType),
1
)
}
}
}
}