@power-doctest/markdown
Version:
A Markdown parser for power-doctest.
147 lines (143 loc) • 4.03 kB
JavaScript
// Support doctest:xxx and doctest-xxx
// doctest:xxx is back compatible syntax.
const DISABLE_PATTERN = /doctest[:-]\s*?disable(:?d)?/;
const ENABLE_PATTERN = /doctest[:-]\s*?enable(:?d)?/;
const DOCTEST_OPTIONS = /doctest[:-]\w*?options:({[^}]+})/;
const DOCTEST_METADATA = /doctest[:-]\w*?meta:({[^}]+})/;
// doctest-error:SyntaxError
const ERROR_TYPE_PATTERN = /(?:doctest|doctest-error):\s*([\w\s]*?Error)/;
/**
* CodeBlockの手前に該当するHTMLコメントはdoctestの制御コードとして扱える
*
* @example
* 以下のは実行されないのでOKになる
*
* <!-- doctest:disable -->
* ```js
* 1; // => 2
* ```
*
* @example
* 次はdoctestの結果のError名を指定できる
*
* <!-- doctest: ReferenceError -->
* ```js
* NO_DEFINE++;
* ```
*
* @type {String}
*/
export class DocTestController {
comments;
_expectedErrorName;
/**
* @param {string[]} comments
*/
constructor(comments) {
this.comments = comments;
this._expectedErrorName = this._getExpectedErrorName(comments);
}
/**
* Return state of @power-doctest/types
*/
get state() {
for (const comment of this.comments) {
if (ENABLE_PATTERN.test(comment)) {
return "enabled";
}
else if (DISABLE_PATTERN.test(comment)) {
return "disabled";
}
}
// not defined
return "none";
}
/**
* @returns {string|undefined}
*/
get expectedErrorName() {
return this._expectedErrorName;
}
/**
* @returns {boolean}
*/
get hasExpectedError() {
return this.expectedErrorName !== undefined;
}
get doctestMetadata() {
const optionComment = this.comments.find((comment) => {
return DOCTEST_METADATA.test(comment);
});
if (!optionComment) {
return undefined;
}
const optionString = optionComment.match(DOCTEST_METADATA);
if (!optionString) {
return undefined;
}
try {
return JSON.parse(optionString[1]);
}
catch (_error) {
throw new Error(`Can not parsed the metadata.
doctest:metadata:{ ... } should be json string.
Actual: ${optionString}
`);
}
}
get doctestOptions() {
const optionComment = this.comments.find((comment) => {
return DOCTEST_OPTIONS.test(comment);
});
if (!optionComment) {
return undefined;
}
const optionString = optionComment.match(DOCTEST_OPTIONS);
if (!optionString) {
return undefined;
}
try {
return JSON.parse(optionString[1]);
}
catch (_error) {
throw new Error(`Can not parsed the options.
doctest:options:{ ... } should be json string.
Actual: ${optionString}
`);
}
}
/**
* Return true, if the `error` is expected error name
* If not defined expected error, return true.
* @param {Error} [error]
* @returns {boolean}
*/
isExpectedError(error) {
if (!this.hasExpectedError) {
return false;
}
const expectedErrorType = this.expectedErrorName;
if (!expectedErrorType) {
return true; // no expected error
}
return error.name === expectedErrorType;
}
/**
* Return expected Error name if expected is defined.
* @returns {string[]}
* @returns {string|undefined}
* @private
*/
_getExpectedErrorName(comments) {
const expectedErrorTypeComment = comments.find((comment) => {
return ERROR_TYPE_PATTERN.test(comment);
});
if (!expectedErrorTypeComment) {
return undefined;
}
const match = expectedErrorTypeComment.match(ERROR_TYPE_PATTERN);
const matched = match?.[1];
return matched ? matched : undefined;
}
}
//# sourceMappingURL=DocTestController.js.map