Skip to content

Commit a91dfcb

Browse files
Transform http
1 parent d2246ac commit a91dfcb

File tree

1 file changed

+61
-63
lines changed

1 file changed

+61
-63
lines changed

src/languages/http.js

Lines changed: 61 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { insertBefore } from '../util/language-util.js';
2-
31
/** @type {import('../types.d.ts').LanguageProto<'http'>} */
42
export default {
53
id: 'http',
@@ -13,7 +11,64 @@ export default {
1311
return RegExp('(^(?:' + name + '):[ \t]*(?![ \t]))[^]+', 'i');
1412
}
1513

16-
const http = {
14+
// Create a mapping of Content-Type headers to language definitions
15+
const httpLanguages = {
16+
'application/javascript': 'javascript',
17+
'application/json': getOptionalLanguage('json') || 'javascript',
18+
'application/xml': 'xml',
19+
'text/xml': 'xml',
20+
'text/html': 'html',
21+
'text/css': 'css',
22+
'text/plain': 'plain',
23+
};
24+
25+
// Declare which types can also be suffixes
26+
const suffixTypes = {
27+
'application/json': true,
28+
'application/xml': true,
29+
};
30+
31+
/**
32+
* Returns a pattern for the given content type which matches it and any type which has it as a suffix.
33+
*
34+
* @param {string} contentType
35+
* @returns {string}
36+
*/
37+
function getSuffixPattern (contentType) {
38+
const suffix = contentType.replace(/^[a-z]+\//, '');
39+
const suffixPattern = '\\w+/(?:[\\w.-]+\\+)+' + suffix + '(?![+\\w.-])';
40+
return '(?:' + contentType + '|' + suffixPattern + ')';
41+
}
42+
43+
// Insert each content type parser that has its associated language
44+
// currently loaded.
45+
46+
const options = /** @type {import('../types.d.ts').GrammarTokens} */ ({});
47+
for (const key in httpLanguages) {
48+
const contentType = key;
49+
50+
const pattern = suffixTypes[contentType] ? getSuffixPattern(contentType) : contentType;
51+
options[contentType.replace(/\//g, '-')] = {
52+
pattern: RegExp(
53+
'(' +
54+
/content-type:\s*/.source +
55+
pattern +
56+
/(?:(?:\r\n?|\n)[\w-].*)*(?:\r(?:\n|(?!\n))|\n)/.source +
57+
')' +
58+
// This is a little interesting:
59+
// The HTTP format spec required 1 empty line before the body to make everything unambiguous.
60+
// However, when writing code by hand (e.g. to display on a website) people can forget about this,
61+
// so we want to be liberal here. We will allow the empty line to be omitted if the first line of
62+
// the body does not start with a [\w-] character (as headers do).
63+
/[^ \t\w-][\s\S]*/.source,
64+
'i'
65+
),
66+
lookbehind: true,
67+
inside: httpLanguages[contentType],
68+
};
69+
}
70+
71+
return {
1772
'request-line': {
1873
pattern:
1974
/^(?:CONNECT|DELETE|GET|HEAD|OPTIONS|PATCH|POST|PRI|PUT|SEARCH|TRACE)\s(?:https?:\/\/|\/)\S*\sHTTP\/[\d.]+/m,
@@ -94,66 +149,9 @@ export default {
94149
'punctuation': /^:/,
95150
},
96151
},
152+
$insertBefore: {
153+
'header': options,
154+
},
97155
};
98-
99-
// Create a mapping of Content-Type headers to language definitions
100-
const httpLanguages = {
101-
'application/javascript': 'javascript',
102-
'application/json': getOptionalLanguage('json') || 'javascript',
103-
'application/xml': 'xml',
104-
'text/xml': 'xml',
105-
'text/html': 'html',
106-
'text/css': 'css',
107-
'text/plain': 'plain',
108-
};
109-
110-
// Declare which types can also be suffixes
111-
const suffixTypes = {
112-
'application/json': true,
113-
'application/xml': true,
114-
};
115-
116-
/**
117-
* Returns a pattern for the given content type which matches it and any type which has it as a suffix.
118-
*
119-
* @param {string} contentType
120-
* @returns {string}
121-
*/
122-
function getSuffixPattern (contentType) {
123-
const suffix = contentType.replace(/^[a-z]+\//, '');
124-
const suffixPattern = '\\w+/(?:[\\w.-]+\\+)+' + suffix + '(?![+\\w.-])';
125-
return '(?:' + contentType + '|' + suffixPattern + ')';
126-
}
127-
128-
// Insert each content type parser that has its associated language
129-
// currently loaded.
130-
/** @type {import('../types.d.ts').Grammar} */
131-
const options = {};
132-
for (const key in httpLanguages) {
133-
const contentType = key;
134-
135-
const pattern = suffixTypes[contentType] ? getSuffixPattern(contentType) : contentType;
136-
options[contentType.replace(/\//g, '-')] = {
137-
pattern: RegExp(
138-
'(' +
139-
/content-type:\s*/.source +
140-
pattern +
141-
/(?:(?:\r\n?|\n)[\w-].*)*(?:\r(?:\n|(?!\n))|\n)/.source +
142-
')' +
143-
// This is a little interesting:
144-
// The HTTP format spec required 1 empty line before the body to make everything unambiguous.
145-
// However, when writing code by hand (e.g. to display on a website) people can forget about this,
146-
// so we want to be liberal here. We will allow the empty line to be omitted if the first line of
147-
// the body does not start with a [\w-] character (as headers do).
148-
/[^ \t\w-][\s\S]*/.source,
149-
'i'
150-
),
151-
lookbehind: true,
152-
inside: httpLanguages[contentType],
153-
};
154-
}
155-
insertBefore(http, 'header', options);
156-
157-
return http;
158156
},
159157
};

0 commit comments

Comments
 (0)