-
-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
37 changed files
with
444 additions
and
372 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,11 @@ | ||
node_modules/ | ||
coverage/ | ||
node_modules/ | ||
packages/rehype/*.d.ts | ||
packages/rehype-cli/*.d.ts | ||
packages/rehype-parse/lib/*.d.ts | ||
packages/rehype-stringify/lib/*.d.ts | ||
script/*.d.ts | ||
test/*.d.ts | ||
.DS_Store | ||
*.log | ||
yarn.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"include": ["*.js"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// This wrapper exists because JS in TS can’t export a `@type` of a function. | ||
import type {Options, ErrorCode, ErrorSeverity} from './lib/index.js' | ||
import type {Root} from 'hast' | ||
import type {Plugin} from 'unified' | ||
const rehypeParse: Plugin<[Options] | [], Root, string> | ||
export default rehypeParse | ||
export type {Options, ErrorCode, ErrorSeverity} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,91 +1,2 @@ | ||
import Parser5 from 'parse5/lib/parser/index.js' | ||
import {fromParse5} from 'hast-util-from-parse5' | ||
import {errors} from './errors.js' | ||
|
||
const base = 'https://html.spec.whatwg.org/multipage/parsing.html#parse-error-' | ||
|
||
const fatalities = {2: true, 1: false, 0: null} | ||
|
||
export default function rehypeParse(options) { | ||
const settings = Object.assign({}, options, this.data('settings')) | ||
let position = settings.position | ||
|
||
position = typeof position === 'boolean' ? position : true | ||
|
||
this.Parser = parser | ||
|
||
function parser(doc, file) { | ||
const fn = settings.fragment ? 'parseFragment' : 'parse' | ||
const onParseError = settings.emitParseErrors ? onerror : null | ||
const parse5 = new Parser5({ | ||
sourceCodeLocationInfo: position, | ||
onParseError, | ||
scriptingEnabled: false | ||
}) | ||
|
||
return fromParse5(parse5[fn](doc), { | ||
space: settings.space, | ||
file, | ||
verbose: settings.verbose | ||
}) | ||
|
||
function onerror(error) { | ||
const code = error.code | ||
const name = camelcase(code) | ||
const setting = settings[name] | ||
const config = setting === undefined || setting === null ? true : setting | ||
const level = typeof config === 'number' ? config : config ? 1 : 0 | ||
const start = { | ||
line: error.startLine, | ||
column: error.startCol, | ||
offset: error.startOffset | ||
} | ||
const end = { | ||
line: error.endLine, | ||
column: error.endCol, | ||
offset: error.endOffset | ||
} | ||
let info | ||
let message | ||
|
||
if (level) { | ||
/* c8 ignore next */ | ||
info = errors[name] || {reason: '', description: ''} | ||
|
||
message = file.message(format(info.reason), {start, end}) | ||
message.source = 'parse-error' | ||
message.ruleId = code | ||
message.fatal = fatalities[level] | ||
message.note = format(info.description) | ||
message.url = info.url === false ? null : base + code | ||
} | ||
|
||
function format(value) { | ||
return value.replace(/%c(?:-(\d+))?/g, char).replace(/%x/g, encodedChar) | ||
} | ||
|
||
function char($0, $1) { | ||
const offset = $1 ? -Number.parseInt($1, 10) : 0 | ||
const char = doc.charAt(error.startOffset + offset) | ||
return char === '`' ? '` ` `' : char | ||
} | ||
|
||
function encodedChar() { | ||
const char = doc | ||
.charCodeAt(error.startOffset) | ||
.toString(16) | ||
.toUpperCase() | ||
|
||
return '0x' + char | ||
} | ||
} | ||
} | ||
} | ||
|
||
function camelcase(value) { | ||
return value.replace(/-[a-z]/g, replacer) | ||
} | ||
|
||
function replacer($0) { | ||
return $0.charAt(1).toUpperCase() | ||
} | ||
import rehypeParse from './lib/index.js' | ||
export default rehypeParse |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/** | ||
* @typedef {import('hast').Root} Root | ||
* @typedef {Pick<import('hast-util-from-parse5').Options, 'space' | 'verbose'>} FromParse5Options | ||
* | ||
* @typedef {keyof errors} ErrorCode | ||
* @typedef {0|1|2|boolean|null|undefined} ErrorSeverity | ||
* @typedef {Partial<Record<ErrorCode, ErrorSeverity>>} ErrorFields | ||
* | ||
* @typedef ParseFields | ||
* @property {boolean|undefined} [position=true] | ||
* @property {boolean|undefined} [fragment=false] | ||
* Specify whether to parse a fragment, instead of a complete document. | ||
* In document mode, unopened `html`, `head`, and `body` elements are opened | ||
* in just the right places. | ||
* @property {boolean|undefined} [emitParseErrors=false] | ||
* > ⚠️ Parse errors are currently being added to HTML. | ||
* > Not all errors emitted by parse5 (or rehype-parse) are specced yet. | ||
* > Some documentation may still be missing. | ||
* | ||
* Emit parse errors while parsing on the vfile. | ||
* Setting this to `true` starts emitting HTML parse errors. | ||
* | ||
* Specific rules can be turned off by setting them to `false` (or `0`). | ||
* The default, when `emitParseErrors: true`, is `true` (or `1`), and means | ||
* that rules emit as warnings. | ||
* Rules can also be configured with `2`, to turn them into fatal errors. | ||
* | ||
* @typedef {FromParse5Options & ParseFields & ErrorFields} Options | ||
*/ | ||
|
||
// @ts-expect-error: remove when typed | ||
import Parser5 from 'parse5/lib/parser/index.js' | ||
import {fromParse5} from 'hast-util-from-parse5' | ||
import {errors} from './errors.js' | ||
|
||
const base = 'https://html.spec.whatwg.org/multipage/parsing.html#parse-error-' | ||
|
||
const fatalities = {2: true, 1: false, 0: null} | ||
|
||
/** @type {import('unified').Plugin<[Options?] | void[], string, Root>} */ | ||
export default function rehypeParse(options) { | ||
const processorSettings = /** @type {Options} */ (this.data('settings')) | ||
const settings = Object.assign({}, options, processorSettings) | ||
const position = | ||
typeof settings.position === 'boolean' ? settings.position : true | ||
|
||
Object.assign(this, {Parser: parser}) | ||
|
||
/** @type {import('unified').ParserFunction<Root>} */ | ||
function parser(doc, file) { | ||
const fn = settings.fragment ? 'parseFragment' : 'parse' | ||
const onParseError = settings.emitParseErrors ? onerror : null | ||
const parse5 = new Parser5({ | ||
sourceCodeLocationInfo: position, | ||
onParseError, | ||
scriptingEnabled: false | ||
}) | ||
|
||
// @ts-expect-error: `parse5` returns document or fragment, which are always | ||
// mapped to roots. | ||
return fromParse5(parse5[fn](doc), { | ||
space: settings.space, | ||
file, | ||
verbose: settings.verbose | ||
}) | ||
|
||
/** | ||
* @param {{code: string, startLine: number, startCol: number, startOffset: number, endLine: number, endCol: number, endOffset: number}} error | ||
*/ | ||
function onerror(error) { | ||
const code = error.code | ||
const name = camelcase(code) | ||
const setting = settings[name] | ||
const config = setting === undefined || setting === null ? true : setting | ||
const level = typeof config === 'number' ? config : config ? 1 : 0 | ||
const start = { | ||
line: error.startLine, | ||
column: error.startCol, | ||
offset: error.startOffset | ||
} | ||
const end = { | ||
line: error.endLine, | ||
column: error.endCol, | ||
offset: error.endOffset | ||
} | ||
if (level) { | ||
/* c8 ignore next */ | ||
const info = errors[name] || {reason: '', description: '', url: ''} | ||
const message = file.message(format(info.reason), {start, end}) | ||
message.source = 'parse-error' | ||
message.ruleId = code | ||
message.fatal = fatalities[level] | ||
message.note = format(info.description) | ||
message.url = 'url' in info && info.url === false ? null : base + code | ||
} | ||
|
||
/** | ||
* @param {string} value | ||
* @returns {string} | ||
*/ | ||
function format(value) { | ||
return value | ||
.replace(/%c(?:-(\d+))?/g, (_, /** @type {string} */ $1) => { | ||
const offset = $1 ? -Number.parseInt($1, 10) : 0 | ||
const char = doc.charAt(error.startOffset + offset) | ||
return char === '`' ? '` ` `' : char | ||
}) | ||
.replace( | ||
/%x/g, | ||
() => | ||
'0x' + | ||
doc.charCodeAt(error.startOffset).toString(16).toUpperCase() | ||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* @param {string} value | ||
* @returns {ErrorCode} | ||
*/ | ||
function camelcase(value) { | ||
// @ts-expect-error: this returns a valid error code. | ||
return value.replace(/-[a-z]/g, ($0) => $0.charAt(1).toUpperCase()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"include": ["lib/**/*.js"] | ||
} |
Oops, something went wrong.