Skip to content

Commit baac1a8

Browse files
committed
Add support for minifying doctypes
Apparently, `<!doctypehtml>`, `<!doctypehtml public"something">`, `<!doctypehtml system"something">`, and `<!doctypehtml public"something""else">` are all valid, except for the parse errors that is, and don’t cause quirksmode!
1 parent 3eb520f commit baac1a8

File tree

4 files changed

+59
-18
lines changed

4 files changed

+59
-18
lines changed

lib/doctype.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,27 @@ module.exports = doctype
44

55
/* Stringify a doctype `node`. */
66
function doctype(ctx, node) {
7+
var sep = ctx.tightDoctype ? '' : ' '
8+
var name = node.name
79
var pub = node.public
810
var sys = node.system
9-
var val = '<!doctype'
11+
var val = ['<!doctype']
1012

11-
if (!node.name) {
12-
return val + '>'
13-
}
14-
15-
val += ' ' + node.name
13+
if (name) {
14+
val.push(sep, name)
1615

17-
if (pub != null) {
18-
val += ' public ' + smart(pub)
19-
} else if (sys != null) {
20-
val += ' system'
21-
}
16+
if (pub != null) {
17+
val.push(' public', sep, smart(pub))
18+
} else if (sys != null) {
19+
val.push(' system')
20+
}
2221

23-
if (sys != null) {
24-
val += ' ' + smart(sys)
22+
if (sys != null) {
23+
val.push(sep, smart(sys))
24+
}
2525
}
2626

27-
return val + '>'
27+
return val.join('') + '>'
2828
}
2929

3030
function smart(value) {

lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ function toHTML(node, options) {
7676
alternative: smart ? alternative : null,
7777
unquoted: Boolean(settings.preferUnquoted),
7878
tight: settings.tightAttributes,
79+
tightDoctype: Boolean(settings.tightDoctype),
7980
tightLists: settings.tightCommaSeparatedLists,
8081
tightClose: settings.tightSelfClosing,
8182
collapseEmpty: settings.collapseEmptyAttributes,

readme.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ if `closeSelfClosing: true`.
9191
###### `options.tightCommaSeparatedLists`
9292

9393
Join known comma-separated attribute values with just a comma (`,`),
94-
instead of padding them on the right as well (`,`) (`boolean`,
95-
default: `false`).
94+
instead of padding them on the right as well (`,·`, where `·` represents a
95+
space) (`boolean`, default: `false`).
9696

9797
###### `options.tightAttributes`
9898

@@ -101,6 +101,12 @@ Join attributes together, without white-space, if possible:
101101
instead to save bytes (`boolean`, default: `false`). **Note**: creates
102102
invalid (but working) markup.
103103

104+
###### `options.tightDoctype`
105+
106+
Drop unneeded spaces in doctypes: `<!doctypehtml>` instead of `<!doctype html>`
107+
to save bytes (`boolean`, default: `false`). **Note**: creates
108+
invalid (but working) markup.
109+
104110
###### `options.allowParseErrors`
105111

106112
Do not encode characters which trigger parse errors (even though they

test/doctype.js

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ test('`text`', function(t) {
1717
'should stringify doctypes with `name`'
1818
)
1919

20+
t.deepEqual(
21+
to(u('doctype', {name: 'html'}), {tightDoctype: true}),
22+
'<!doctypehtml>',
23+
'should stringify doctypes with `name` tightly in `tightDoctype` mode'
24+
)
25+
2026
t.deepEqual(
2127
to(
2228
u('doctype', {
@@ -32,13 +38,28 @@ test('`text`', function(t) {
3238
to(
3339
u('doctype', {
3440
name: 'html',
35-
system: 'about:legacy-compat'
36-
})
41+
public: '-//W3C//DTD XHTML 1.0 Transitional//EN'
42+
}),
43+
{tightDoctype: true}
3744
),
45+
'<!doctypehtml public"-//W3C//DTD XHTML 1.0 Transitional//EN">',
46+
'should stringify doctypes with a public identifier tightly in `tightDoctype` mode'
47+
)
48+
49+
t.deepEqual(
50+
to(u('doctype', {name: 'html', system: 'about:legacy-compat'})),
3851
'<!doctype html system "about:legacy-compat">',
3952
'should stringify doctypes with a system identifier'
4053
)
4154

55+
t.deepEqual(
56+
to(u('doctype', {name: 'html', system: 'about:legacy-compat'}), {
57+
tightDoctype: true
58+
}),
59+
'<!doctypehtml system"about:legacy-compat">',
60+
'should stringify doctypes with a system identifier tightly in `tightDoctype` mode'
61+
)
62+
4263
t.deepEqual(
4364
to(
4465
u('doctype', {
@@ -51,6 +72,19 @@ test('`text`', function(t) {
5172
'should stringify doctypes with both identifiers'
5273
)
5374

75+
t.deepEqual(
76+
to(
77+
u('doctype', {
78+
name: 'html',
79+
public: '-//W3C//DTD HTML 4.01//',
80+
system: 'http://www.w3.org/TR/html4/strict.dtd'
81+
}),
82+
{tightDoctype: true}
83+
),
84+
'<!doctypehtml public"-//W3C//DTD HTML 4.01//""http://www.w3.org/TR/html4/strict.dtd">',
85+
'should stringify doctypes with both identifiers tightly in `tightDoctype` mode'
86+
)
87+
5488
t.deepEqual(
5589
to(
5690
u('doctype', {

0 commit comments

Comments
 (0)