antsibull-docs
Advanced tools
Comparing version 0.1.0 to 0.2.0
@@ -54,3 +54,3 @@ "use strict"; | ||
if (part.plugin && opts.pluginOptionLikeLink) { | ||
url = opts.pluginOptionLikeLink(part.plugin, 'option', part.link, part.plugin === opts.current_plugin); | ||
url = opts.pluginOptionLikeLink(part.plugin, part.entrypoint, 'option', part.link, part.plugin === opts.current_plugin); | ||
} | ||
@@ -74,3 +74,3 @@ destination.push(opts.formatOptionName(part, url)); | ||
if (part.plugin && opts.pluginOptionLikeLink) { | ||
url = opts.pluginOptionLikeLink(part.plugin, 'retval', part.link, part.plugin === opts.current_plugin); | ||
url = opts.pluginOptionLikeLink(part.plugin, part.entrypoint, 'retval', part.link, part.plugin === opts.current_plugin); | ||
} | ||
@@ -77,0 +77,0 @@ destination.push(opts.formatReturnValue(part, url)); |
@@ -8,3 +8,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.toHTML = exports.quoteHTML = void 0; | ||
exports.toHTML = exports.quoteHTMLArg = exports.quoteHTML = void 0; | ||
const opts_1 = require("./opts"); | ||
@@ -16,2 +16,6 @@ const format_1 = require("./format"); | ||
exports.quoteHTML = quoteHTML; | ||
function quoteHTMLArg(text) { | ||
return quoteHTML(text).replace(/"/g, '"'); | ||
} | ||
exports.quoteHTMLArg = quoteHTMLArg; | ||
function formatOptionLikePlain(part, url, what) { | ||
@@ -21,3 +25,3 @@ let link_start = ''; | ||
if (url) { | ||
link_start = `<a href="${quoteHTML(encodeURI(url))}">`; | ||
link_start = `<a href="${quoteHTMLArg(encodeURI(url))}">`; | ||
link_end = '</a>'; | ||
@@ -40,6 +44,8 @@ } | ||
formatItalic: (part) => `<em>${quoteHTML(part.text)}</em>`, | ||
formatLink: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatModule: (part, url) => url ? `<a href='${url}'>${quoteHTML(part.fqcn)}</a>` : `<span>${quoteHTML(part.fqcn)}</span>`, | ||
formatLink: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatModule: (part, url) => url | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}'>${quoteHTML(part.fqcn)}</a>` | ||
: `<span>${quoteHTML(part.fqcn)}</span>`, | ||
formatRSTRef: (part) => `<span>${quoteHTML(part.text)}</span>`, | ||
formatURL: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatURL: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatText: (part) => quoteHTML(part.text), | ||
@@ -49,3 +55,5 @@ formatEnvVariable: (part) => `<code>${quoteHTML(part.name)}</code>`, | ||
formatOptionValue: (part) => `<code>${quoteHTML(part.value)}</code>`, | ||
formatPlugin: (part, url) => url ? `<a href='${url}'>${quoteHTML(part.plugin.fqcn)}</a>` : `<span>${quoteHTML(part.plugin.fqcn)}</span>`, | ||
formatPlugin: (part, url) => url | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}'>${quoteHTML(part.plugin.fqcn)}</a>` | ||
: `<span>${quoteHTML(part.plugin.fqcn)}</span>`, | ||
formatReturnValue: (part, url) => formatOptionLikePlain(part, url, 'retval'), | ||
@@ -57,3 +65,3 @@ }; | ||
if (url) { | ||
link_start = `<a class="reference internal" href="${quoteHTML(encodeURI(url))}"><span class="std std-ref"><span class="pre">`; | ||
link_start = `<a class="reference internal" href="${quoteHTMLArg(encodeURI(url))}"><span class="std std-ref"><span class="pre">`; | ||
link_end = '</span></span></a>'; | ||
@@ -92,8 +100,8 @@ } | ||
formatItalic: (part) => `<em>${quoteHTML(part.text)}</em>`, | ||
formatLink: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatLink: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatModule: (part, url) => url | ||
? `<a href='${url}' class='module'>${quoteHTML(part.fqcn)}</a>` | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}' class='module'>${quoteHTML(part.fqcn)}</a>` | ||
: `<span class='module'>${quoteHTML(part.fqcn)}</span>`, | ||
formatRSTRef: (part) => `<span class='module'>${quoteHTML(part.text)}</span>`, | ||
formatURL: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatURL: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatText: (part) => quoteHTML(part.text), | ||
@@ -104,3 +112,3 @@ formatEnvVariable: (part) => `<code class="xref std std-envvar literal notranslate">${quoteHTML(part.name)}</code>`, | ||
formatPlugin: (part, url) => url | ||
? `<a href='${url}' class='module'>${quoteHTML(part.plugin.fqcn)}</a>` | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}' class='module'>${quoteHTML(part.plugin.fqcn)}</a>` | ||
: `<span class='module'>${quoteHTML(part.plugin.fqcn)}</span>`, | ||
@@ -107,0 +115,0 @@ formatReturnValue: (part, url) => formatOptionLikeAntsibullDocs(part, url, 'retval'), |
@@ -31,3 +31,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.toRST = exports.quoteRST = exports.toMD = exports.quoteMD = exports.toHTML = exports.quoteHTML = exports.dom = exports.parse = void 0; | ||
exports.toRST = exports.quoteRST = exports.toMD = exports.quoteMD = exports.toHTML = exports.quoteHTML = exports.toAnsibleDocText = exports.dom = exports.parse = void 0; | ||
// Parser | ||
@@ -38,2 +38,4 @@ var parser_1 = require("./parser"); | ||
// Output | ||
var ansible_doc_text_1 = require("./ansible-doc-text"); | ||
Object.defineProperty(exports, "toAnsibleDocText", { enumerable: true, get: function () { return ansible_doc_text_1.toAnsibleDocText; } }); | ||
var html_1 = require("./html"); | ||
@@ -40,0 +42,0 @@ Object.defineProperty(exports, "quoteHTML", { enumerable: true, get: function () { return html_1.quoteHTML; } }); |
@@ -11,2 +11,3 @@ "use strict"; | ||
const opts_1 = require("./opts"); | ||
const html_1 = require("./html"); | ||
const format_1 = require("./format"); | ||
@@ -21,3 +22,3 @@ function quoteMD(text) { | ||
if (url) { | ||
link_start = `<a href="${quoteMD(encodeURI(url))}">`; | ||
link_start = `<a href="${quoteMD((0, html_1.quoteHTMLArg)(encodeURI(url)))}">`; | ||
link_end = '</a>'; | ||
@@ -24,0 +25,0 @@ } |
@@ -13,3 +13,3 @@ "use strict"; | ||
const IGNORE_MARKER = 'ignore:'; | ||
function parseOptionLike(text, opts, type) { | ||
function parseOptionLike(text, opts, type, source) { | ||
let value; | ||
@@ -23,2 +23,3 @@ const eq = text.indexOf('='); | ||
let plugin; | ||
let entrypoint; | ||
if (m) { | ||
@@ -42,3 +43,14 @@ const pluginFqcn = m[1]; | ||
plugin = opts.current_plugin; | ||
entrypoint = opts.role_entrypoint; | ||
} | ||
if ((plugin === null || plugin === void 0 ? void 0 : plugin.type) === 'role') { | ||
const idx = text.indexOf(':'); | ||
if (idx >= 0) { | ||
entrypoint = text.substr(0, idx); | ||
text = text.substr(idx + 1); | ||
} | ||
if (entrypoint === undefined) { | ||
throw Error('Role reference is missing entrypoint'); | ||
} | ||
} | ||
if (/[:#]/.test(text)) { | ||
@@ -50,5 +62,7 @@ throw Error(`Invalid option/return value name "${text}"`); | ||
plugin: plugin, | ||
entrypoint: entrypoint, | ||
link: text.replace(/\[([^\]]*)\]/g, '').split('.'), | ||
name: text, | ||
value: value, | ||
source: source, | ||
}; | ||
@@ -62,5 +76,5 @@ } | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0]; | ||
return { type: dom_1.PartType.ITALIC, text: text }; | ||
return { type: dom_1.PartType.ITALIC, text: text, source: source }; | ||
}, | ||
@@ -72,5 +86,5 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0]; | ||
return { type: dom_1.PartType.BOLD, text: text }; | ||
return { type: dom_1.PartType.BOLD, text: text, source: source }; | ||
}, | ||
@@ -82,3 +96,3 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const fqcn = args[0]; | ||
@@ -88,3 +102,3 @@ if (!(0, ansible_1.isFQCN)(fqcn)) { | ||
} | ||
return { type: dom_1.PartType.MODULE, fqcn: fqcn }; | ||
return { type: dom_1.PartType.MODULE, fqcn: fqcn, source: source }; | ||
}, | ||
@@ -96,5 +110,5 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const url = args[0]; | ||
return { type: dom_1.PartType.URL, url: url }; | ||
return { type: dom_1.PartType.URL, url: url, source: source }; | ||
}, | ||
@@ -106,6 +120,6 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0]; | ||
const url = args[1]; | ||
return { type: dom_1.PartType.LINK, text: text, url: url }; | ||
return { type: dom_1.PartType.LINK, text: text, url: url, source: source }; | ||
}, | ||
@@ -117,6 +131,6 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0]; | ||
const ref = args[1]; | ||
return { type: dom_1.PartType.RST_REF, text: text, ref: ref }; | ||
return { type: dom_1.PartType.RST_REF, text: text, ref: ref, source: source }; | ||
}, | ||
@@ -128,5 +142,5 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0]; | ||
return { type: dom_1.PartType.CODE, text: text }; | ||
return { type: dom_1.PartType.CODE, text: text, source: source }; | ||
}, | ||
@@ -138,4 +152,4 @@ }, | ||
old_markup: true, | ||
process: () => { | ||
return { type: dom_1.PartType.HORIZONTAL_LINE }; | ||
process: (_, __, source) => { | ||
return { type: dom_1.PartType.HORIZONTAL_LINE, source: source }; | ||
}, | ||
@@ -147,5 +161,5 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args) => { | ||
const m = /^([^).]+\.[^).]+\.[^#]+)#(.+)$/.exec(args[0]); | ||
escapedArguments: true, | ||
process: (args, _, source) => { | ||
const m = /^([^#]*)#(.*)$/.exec(args[0]); | ||
if (!m) { | ||
@@ -162,3 +176,3 @@ throw Error(`Parameter "${args[0]}" is not of the form FQCN#type`); | ||
} | ||
return { type: dom_1.PartType.PLUGIN, plugin: { fqcn: fqcn, type: type } }; | ||
return { type: dom_1.PartType.PLUGIN, plugin: { fqcn: fqcn, type: type }, source: source }; | ||
}, | ||
@@ -169,6 +183,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args) => { | ||
escapedArguments: true, | ||
process: (args, _, source) => { | ||
const env = args[0]; | ||
return { type: dom_1.PartType.ENV_VARIABLE, name: env }; | ||
return { type: dom_1.PartType.ENV_VARIABLE, name: env, source: source }; | ||
}, | ||
@@ -179,6 +193,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args) => { | ||
escapedArguments: true, | ||
process: (args, _, source) => { | ||
const value = args[0]; | ||
return { type: dom_1.PartType.OPTION_VALUE, value: value }; | ||
return { type: dom_1.PartType.OPTION_VALUE, value: value, source: source }; | ||
}, | ||
@@ -189,6 +203,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args, opts) => { | ||
escapedArguments: true, | ||
process: (args, opts, source) => { | ||
const value = args[0]; | ||
return parseOptionLike(value, opts, dom_1.PartType.OPTION_NAME); | ||
return parseOptionLike(value, opts, dom_1.PartType.OPTION_NAME, source); | ||
}, | ||
@@ -199,6 +213,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args, opts) => { | ||
escapedArguments: true, | ||
process: (args, opts, source) => { | ||
const value = args[0]; | ||
return parseOptionLike(value, opts, dom_1.PartType.RETURN_VALUE); | ||
return parseOptionLike(value, opts, dom_1.PartType.RETURN_VALUE, source); | ||
}, | ||
@@ -224,2 +238,3 @@ }, | ||
function parseString(input, commandRE, commands, opts, where) { | ||
var _a; | ||
const result = []; | ||
@@ -233,5 +248,7 @@ const length = input.length; | ||
if (index < length) { | ||
const text = input.slice(index); | ||
result.push({ | ||
type: dom_1.PartType.TEXT, | ||
text: input.slice(index), | ||
text: text, | ||
source: opts.addSource ? text : undefined, | ||
}); | ||
@@ -242,5 +259,7 @@ } | ||
if (match.index > index) { | ||
const text = input.slice(index, match.index); | ||
result.push({ | ||
type: dom_1.PartType.TEXT, | ||
text: input.slice(index, match.index), | ||
text: text, | ||
source: opts.addSource ? text : undefined, | ||
}); | ||
@@ -263,3 +282,3 @@ } | ||
} | ||
else if (command.escaped_arguments) { | ||
else if (command.escapedArguments) { | ||
[args, endIndex, error] = (0, parser_impl_1.parseEscapedArgs)(input, endIndex, command.parameters); | ||
@@ -270,12 +289,19 @@ } | ||
} | ||
const source = opts.addSource ? input.slice(index, endIndex) : undefined; | ||
if (error === undefined) { | ||
try { | ||
result.push(command.process(args, opts)); | ||
result.push(command.process(args, opts, source)); | ||
} | ||
catch (exc) { | ||
error = `${exc}`; | ||
if ((exc === null || exc === void 0 ? void 0 : exc.message) !== undefined) { | ||
error = `${exc.message}`; | ||
} | ||
} | ||
} | ||
if (error !== undefined) { | ||
error = `While parsing ${cmd}${command.parameters > 0 ? '()' : ''} at index ${match.index + 1}${where}: ${error}`; | ||
const errorSource = ((_a = opts.helpfulErrors) !== null && _a !== void 0 ? _a : true) | ||
? `"${input.slice(index, endIndex)}"` | ||
: `${cmd}${command.parameters > 0 ? '()' : ''}`; | ||
error = `While parsing ${errorSource} at index ${match.index + 1}${where}: ${error}`; | ||
switch (opts.errors || 'message') { | ||
@@ -288,2 +314,3 @@ case 'ignore': | ||
message: error, | ||
source: source, | ||
}); | ||
@@ -310,3 +337,3 @@ break; | ||
const opts_ = opts || {}; | ||
const commandRE = opts_.only_classic_markup ? CLASSIC_COMMAND_RE : COMMAND_RE; | ||
const commandRE = opts_.onlyClassicMarkup ? CLASSIC_COMMAND_RE : COMMAND_RE; | ||
return input.map((par, index) => parseString('' + par, commandRE, PARSER_COMMANDS, opts_, hasParagraphs ? ` of paragraph ${index + 1}` : '')); | ||
@@ -313,0 +340,0 @@ } |
@@ -30,2 +30,6 @@ "use strict"; | ||
} | ||
if (part.entrypoint !== undefined) { | ||
result.push(part.entrypoint); | ||
result.push(':'); | ||
} | ||
result.push(part.name); | ||
@@ -32,0 +36,0 @@ if (part.value !== undefined) { |
@@ -21,2 +21,3 @@ import { PluginIdentifier } from './opts'; | ||
type: PartType; | ||
source: string | undefined; | ||
} | ||
@@ -64,2 +65,3 @@ export interface TextPart extends Part { | ||
plugin: PluginIdentifier | undefined; | ||
entrypoint: string | undefined; | ||
link: string[]; | ||
@@ -80,2 +82,3 @@ name: string; | ||
plugin: PluginIdentifier | undefined; | ||
entrypoint: string | undefined; | ||
link: string[]; | ||
@@ -82,0 +85,0 @@ name: string; |
@@ -51,3 +51,3 @@ /* | ||
if (part.plugin && opts.pluginOptionLikeLink) { | ||
url = opts.pluginOptionLikeLink(part.plugin, 'option', part.link, part.plugin === opts.current_plugin); | ||
url = opts.pluginOptionLikeLink(part.plugin, part.entrypoint, 'option', part.link, part.plugin === opts.current_plugin); | ||
} | ||
@@ -71,3 +71,3 @@ destination.push(opts.formatOptionName(part, url)); | ||
if (part.plugin && opts.pluginOptionLikeLink) { | ||
url = opts.pluginOptionLikeLink(part.plugin, 'retval', part.link, part.plugin === opts.current_plugin); | ||
url = opts.pluginOptionLikeLink(part.plugin, part.entrypoint, 'retval', part.link, part.plugin === opts.current_plugin); | ||
} | ||
@@ -74,0 +74,0 @@ destination.push(opts.formatReturnValue(part, url)); |
import { HTMLOptions } from './opts'; | ||
import { Paragraph } from './dom'; | ||
export declare function quoteHTML(text: string): string; | ||
export declare function quoteHTMLArg(text: string): string; | ||
export declare function toHTML(paragraphs: Paragraph[], opts?: HTMLOptions): string; | ||
//# sourceMappingURL=html.d.ts.map |
@@ -11,2 +11,5 @@ /* | ||
} | ||
export function quoteHTMLArg(text) { | ||
return quoteHTML(text).replace(/"/g, '"'); | ||
} | ||
function formatOptionLikePlain(part, url, what) { | ||
@@ -16,3 +19,3 @@ let link_start = ''; | ||
if (url) { | ||
link_start = `<a href="${quoteHTML(encodeURI(url))}">`; | ||
link_start = `<a href="${quoteHTMLArg(encodeURI(url))}">`; | ||
link_end = '</a>'; | ||
@@ -35,6 +38,8 @@ } | ||
formatItalic: (part) => `<em>${quoteHTML(part.text)}</em>`, | ||
formatLink: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatModule: (part, url) => url ? `<a href='${url}'>${quoteHTML(part.fqcn)}</a>` : `<span>${quoteHTML(part.fqcn)}</span>`, | ||
formatLink: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatModule: (part, url) => url | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}'>${quoteHTML(part.fqcn)}</a>` | ||
: `<span>${quoteHTML(part.fqcn)}</span>`, | ||
formatRSTRef: (part) => `<span>${quoteHTML(part.text)}</span>`, | ||
formatURL: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatURL: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatText: (part) => quoteHTML(part.text), | ||
@@ -44,3 +49,5 @@ formatEnvVariable: (part) => `<code>${quoteHTML(part.name)}</code>`, | ||
formatOptionValue: (part) => `<code>${quoteHTML(part.value)}</code>`, | ||
formatPlugin: (part, url) => url ? `<a href='${url}'>${quoteHTML(part.plugin.fqcn)}</a>` : `<span>${quoteHTML(part.plugin.fqcn)}</span>`, | ||
formatPlugin: (part, url) => url | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}'>${quoteHTML(part.plugin.fqcn)}</a>` | ||
: `<span>${quoteHTML(part.plugin.fqcn)}</span>`, | ||
formatReturnValue: (part, url) => formatOptionLikePlain(part, url, 'retval'), | ||
@@ -52,3 +59,3 @@ }; | ||
if (url) { | ||
link_start = `<a class="reference internal" href="${quoteHTML(encodeURI(url))}"><span class="std std-ref"><span class="pre">`; | ||
link_start = `<a class="reference internal" href="${quoteHTMLArg(encodeURI(url))}"><span class="std std-ref"><span class="pre">`; | ||
link_end = '</span></span></a>'; | ||
@@ -87,8 +94,8 @@ } | ||
formatItalic: (part) => `<em>${quoteHTML(part.text)}</em>`, | ||
formatLink: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatLink: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatModule: (part, url) => url | ||
? `<a href='${url}' class='module'>${quoteHTML(part.fqcn)}</a>` | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}' class='module'>${quoteHTML(part.fqcn)}</a>` | ||
: `<span class='module'>${quoteHTML(part.fqcn)}</span>`, | ||
formatRSTRef: (part) => `<span class='module'>${quoteHTML(part.text)}</span>`, | ||
formatURL: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatURL: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatText: (part) => quoteHTML(part.text), | ||
@@ -99,3 +106,3 @@ formatEnvVariable: (part) => `<code class="xref std std-envvar literal notranslate">${quoteHTML(part.name)}</code>`, | ||
formatPlugin: (part, url) => url | ||
? `<a href='${url}' class='module'>${quoteHTML(part.plugin.fqcn)}</a>` | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}' class='module'>${quoteHTML(part.plugin.fqcn)}</a>` | ||
: `<span class='module'>${quoteHTML(part.plugin.fqcn)}</span>`, | ||
@@ -102,0 +109,0 @@ formatReturnValue: (part, url) => formatOptionLikeAntsibullDocs(part, url, 'retval'), |
export { parse } from './parser'; | ||
export * as dom from './dom'; | ||
export { toAnsibleDocText } from './ansible-doc-text'; | ||
export { quoteHTML, toHTML } from './html'; | ||
@@ -4,0 +5,0 @@ export { quoteMD, toMD } from './md'; |
@@ -10,2 +10,3 @@ /* | ||
// Output | ||
export { toAnsibleDocText } from './ansible-doc-text'; | ||
export { quoteHTML, toHTML } from './html'; | ||
@@ -12,0 +13,0 @@ export { quoteMD, toMD } from './md'; |
@@ -8,2 +8,3 @@ /* | ||
import { mergeOpts } from './opts'; | ||
import { quoteHTMLArg } from './html'; | ||
import { addToDestination } from './format'; | ||
@@ -17,3 +18,3 @@ export function quoteMD(text) { | ||
if (url) { | ||
link_start = `<a href="${quoteMD(encodeURI(url))}">`; | ||
link_start = `<a href="${quoteMD(quoteHTMLArg(encodeURI(url)))}">`; | ||
link_end = '</a>'; | ||
@@ -20,0 +21,0 @@ } |
@@ -20,4 +20,10 @@ import { TextPart, ItalicPart, BoldPart, ModulePart, PluginPart, URLPart, LinkPart, RSTRefPart, CodePart, OptionNamePart, OptionValuePart, EnvVariablePart, ReturnValuePart, HorizontalLinePart, ErrorPart } from './dom'; | ||
current_plugin?: PluginIdentifier; | ||
/** Should be provided if parsing documentation of a specific role's entrypoint. */ | ||
role_entrypoint?: string; | ||
/** If set to 'true', only 'classic' Ansible docs markup is accepted. */ | ||
only_classic_markup?: boolean; | ||
onlyClassicMarkup?: boolean; | ||
/** If set to 'true' (default is 'false'), add source information to every part ('source' attribute). */ | ||
addSource?: boolean; | ||
/** If set to 'true' (default is 'true'), include the faulty markup in error messages. */ | ||
helpfulErrors?: boolean; | ||
} | ||
@@ -66,3 +72,3 @@ export interface CommonExportOptions extends ErrorHandlingOptions { | ||
/** Provides a link to a plugin's option or return value. */ | ||
pluginOptionLikeLink?: (plugin: PluginIdentifier, what: 'option' | 'retval', name: string[], current_plugin: boolean) => string | undefined; | ||
pluginOptionLikeLink?: (plugin: PluginIdentifier, entrypoint: string | undefined, what: 'option' | 'retval', name: string[], current_plugin: boolean) => string | undefined; | ||
} | ||
@@ -81,4 +87,6 @@ export interface HTMLOptions extends CommonExportOptions, CommonFormatOptions, LinkProviders { | ||
} | ||
export interface AnsibleDocTextOptions extends CommonExportOptions, CommonFormatOptions { | ||
} | ||
export declare function mergeOpts<T extends CommonFormatOptions>(options: T, fallback: AllFormatOptions): T & AllFormatOptions; | ||
export {}; | ||
//# sourceMappingURL=opts.d.ts.map |
@@ -6,4 +6,4 @@ import { ParsingOptions } from './opts'; | ||
parameters: number; | ||
escaped_arguments?: boolean; | ||
process: (args: string[], opts: ParsingOptions) => AnyPart; | ||
escapedArguments?: boolean; | ||
process: (args: string[], opts: ParsingOptions, source: string | undefined) => AnyPart; | ||
} | ||
@@ -10,0 +10,0 @@ export declare function composeCommandMap(commands: CommandParser[]): Map<string, CommandParser>; |
@@ -10,3 +10,3 @@ /* | ||
const IGNORE_MARKER = 'ignore:'; | ||
function parseOptionLike(text, opts, type) { | ||
function parseOptionLike(text, opts, type, source) { | ||
let value; | ||
@@ -20,2 +20,3 @@ const eq = text.indexOf('='); | ||
let plugin; | ||
let entrypoint; | ||
if (m) { | ||
@@ -39,3 +40,14 @@ const pluginFqcn = m[1]; | ||
plugin = opts.current_plugin; | ||
entrypoint = opts.role_entrypoint; | ||
} | ||
if ((plugin === null || plugin === void 0 ? void 0 : plugin.type) === 'role') { | ||
const idx = text.indexOf(':'); | ||
if (idx >= 0) { | ||
entrypoint = text.substr(0, idx); | ||
text = text.substr(idx + 1); | ||
} | ||
if (entrypoint === undefined) { | ||
throw Error('Role reference is missing entrypoint'); | ||
} | ||
} | ||
if (/[:#]/.test(text)) { | ||
@@ -47,5 +59,7 @@ throw Error(`Invalid option/return value name "${text}"`); | ||
plugin: plugin, | ||
entrypoint: entrypoint, | ||
link: text.replace(/\[([^\]]*)\]/g, '').split('.'), | ||
name: text, | ||
value: value, | ||
source: source, | ||
}; | ||
@@ -59,5 +73,5 @@ } | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0]; | ||
return { type: PartType.ITALIC, text: text }; | ||
return { type: PartType.ITALIC, text: text, source: source }; | ||
}, | ||
@@ -69,5 +83,5 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0]; | ||
return { type: PartType.BOLD, text: text }; | ||
return { type: PartType.BOLD, text: text, source: source }; | ||
}, | ||
@@ -79,3 +93,3 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const fqcn = args[0]; | ||
@@ -85,3 +99,3 @@ if (!isFQCN(fqcn)) { | ||
} | ||
return { type: PartType.MODULE, fqcn: fqcn }; | ||
return { type: PartType.MODULE, fqcn: fqcn, source: source }; | ||
}, | ||
@@ -93,5 +107,5 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const url = args[0]; | ||
return { type: PartType.URL, url: url }; | ||
return { type: PartType.URL, url: url, source: source }; | ||
}, | ||
@@ -103,6 +117,6 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0]; | ||
const url = args[1]; | ||
return { type: PartType.LINK, text: text, url: url }; | ||
return { type: PartType.LINK, text: text, url: url, source: source }; | ||
}, | ||
@@ -114,6 +128,6 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0]; | ||
const ref = args[1]; | ||
return { type: PartType.RST_REF, text: text, ref: ref }; | ||
return { type: PartType.RST_REF, text: text, ref: ref, source: source }; | ||
}, | ||
@@ -125,5 +139,5 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0]; | ||
return { type: PartType.CODE, text: text }; | ||
return { type: PartType.CODE, text: text, source: source }; | ||
}, | ||
@@ -135,4 +149,4 @@ }, | ||
old_markup: true, | ||
process: () => { | ||
return { type: PartType.HORIZONTAL_LINE }; | ||
process: (_, __, source) => { | ||
return { type: PartType.HORIZONTAL_LINE, source: source }; | ||
}, | ||
@@ -144,5 +158,5 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args) => { | ||
const m = /^([^).]+\.[^).]+\.[^#]+)#(.+)$/.exec(args[0]); | ||
escapedArguments: true, | ||
process: (args, _, source) => { | ||
const m = /^([^#]*)#(.*)$/.exec(args[0]); | ||
if (!m) { | ||
@@ -159,3 +173,3 @@ throw Error(`Parameter "${args[0]}" is not of the form FQCN#type`); | ||
} | ||
return { type: PartType.PLUGIN, plugin: { fqcn: fqcn, type: type } }; | ||
return { type: PartType.PLUGIN, plugin: { fqcn: fqcn, type: type }, source: source }; | ||
}, | ||
@@ -166,6 +180,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args) => { | ||
escapedArguments: true, | ||
process: (args, _, source) => { | ||
const env = args[0]; | ||
return { type: PartType.ENV_VARIABLE, name: env }; | ||
return { type: PartType.ENV_VARIABLE, name: env, source: source }; | ||
}, | ||
@@ -176,6 +190,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args) => { | ||
escapedArguments: true, | ||
process: (args, _, source) => { | ||
const value = args[0]; | ||
return { type: PartType.OPTION_VALUE, value: value }; | ||
return { type: PartType.OPTION_VALUE, value: value, source: source }; | ||
}, | ||
@@ -186,6 +200,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args, opts) => { | ||
escapedArguments: true, | ||
process: (args, opts, source) => { | ||
const value = args[0]; | ||
return parseOptionLike(value, opts, PartType.OPTION_NAME); | ||
return parseOptionLike(value, opts, PartType.OPTION_NAME, source); | ||
}, | ||
@@ -196,6 +210,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args, opts) => { | ||
escapedArguments: true, | ||
process: (args, opts, source) => { | ||
const value = args[0]; | ||
return parseOptionLike(value, opts, PartType.RETURN_VALUE); | ||
return parseOptionLike(value, opts, PartType.RETURN_VALUE, source); | ||
}, | ||
@@ -219,2 +233,3 @@ }, | ||
export function parseString(input, commandRE, commands, opts, where) { | ||
var _a; | ||
const result = []; | ||
@@ -228,5 +243,7 @@ const length = input.length; | ||
if (index < length) { | ||
const text = input.slice(index); | ||
result.push({ | ||
type: PartType.TEXT, | ||
text: input.slice(index), | ||
text: text, | ||
source: opts.addSource ? text : undefined, | ||
}); | ||
@@ -237,5 +254,7 @@ } | ||
if (match.index > index) { | ||
const text = input.slice(index, match.index); | ||
result.push({ | ||
type: PartType.TEXT, | ||
text: input.slice(index, match.index), | ||
text: text, | ||
source: opts.addSource ? text : undefined, | ||
}); | ||
@@ -258,3 +277,3 @@ } | ||
} | ||
else if (command.escaped_arguments) { | ||
else if (command.escapedArguments) { | ||
[args, endIndex, error] = parseEscapedArgs(input, endIndex, command.parameters); | ||
@@ -265,12 +284,19 @@ } | ||
} | ||
const source = opts.addSource ? input.slice(index, endIndex) : undefined; | ||
if (error === undefined) { | ||
try { | ||
result.push(command.process(args, opts)); | ||
result.push(command.process(args, opts, source)); | ||
} | ||
catch (exc) { | ||
error = `${exc}`; | ||
if ((exc === null || exc === void 0 ? void 0 : exc.message) !== undefined) { | ||
error = `${exc.message}`; | ||
} | ||
} | ||
} | ||
if (error !== undefined) { | ||
error = `While parsing ${cmd}${command.parameters > 0 ? '()' : ''} at index ${match.index + 1}${where}: ${error}`; | ||
const errorSource = ((_a = opts.helpfulErrors) !== null && _a !== void 0 ? _a : true) | ||
? `"${input.slice(index, endIndex)}"` | ||
: `${cmd}${command.parameters > 0 ? '()' : ''}`; | ||
error = `While parsing ${errorSource} at index ${match.index + 1}${where}: ${error}`; | ||
switch (opts.errors || 'message') { | ||
@@ -283,2 +309,3 @@ case 'ignore': | ||
message: error, | ||
source: source, | ||
}); | ||
@@ -304,5 +331,5 @@ break; | ||
const opts_ = opts || {}; | ||
const commandRE = opts_.only_classic_markup ? CLASSIC_COMMAND_RE : COMMAND_RE; | ||
const commandRE = opts_.onlyClassicMarkup ? CLASSIC_COMMAND_RE : COMMAND_RE; | ||
return input.map((par, index) => parseString('' + par, commandRE, PARSER_COMMANDS, opts_, hasParagraphs ? ` of paragraph ${index + 1}` : '')); | ||
} | ||
//# sourceMappingURL=parser.js.map |
@@ -26,2 +26,6 @@ /* | ||
} | ||
if (part.entrypoint !== undefined) { | ||
result.push(part.entrypoint); | ||
result.push(':'); | ||
} | ||
result.push(part.name); | ||
@@ -28,0 +32,0 @@ if (part.value !== undefined) { |
{ | ||
"name": "antsibull-docs", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "TypeScript library for processing Ansible documentation markup", | ||
@@ -51,5 +51,5 @@ "main": "dist/cjs/index.js", | ||
"ts-jest": "^29.0.5", | ||
"typescript": "^4.9.5", | ||
"typescript": "^5.0.2", | ||
"yaml": "^2.2.1" | ||
} | ||
} |
@@ -108,3 +108,3 @@ <!-- | ||
2. Create `changelogs/fragments/<version>.yml` with a `release_summary` section. | ||
3. Run `rm -rf build && npm run build`. | ||
3. Run `rm -rf dist && npm run build`. | ||
4. Run `npm publish --dry-run` and check the output. | ||
@@ -115,3 +115,3 @@ 5. Run `antsibull-changelog release` and add the updated files to git. | ||
8. Once CI passes on GitHub, run `npm publish`. | ||
9. On success, do `git push upstream --tags`. | ||
9. On success, do `git push upstream --tags` and create a GitHub release. | ||
10. Add `.post0` to the version in `package.json`, commit as `Post-release version bump.`, and push to GitHub. |
@@ -29,2 +29,3 @@ /* | ||
type: PartType; | ||
source: string | undefined; | ||
} | ||
@@ -82,2 +83,3 @@ | ||
plugin: PluginIdentifier | undefined; | ||
entrypoint: string | undefined; // provided iff plugin.type == 'role' | ||
link: string[]; | ||
@@ -101,2 +103,3 @@ name: string; | ||
plugin: PluginIdentifier | undefined; | ||
entrypoint: string | undefined; // provided iff plugin.type == 'role' | ||
link: string[]; | ||
@@ -103,0 +106,0 @@ name: string; |
@@ -58,3 +58,9 @@ /* | ||
if (part.plugin && opts.pluginOptionLikeLink) { | ||
url = opts.pluginOptionLikeLink(part.plugin, 'option', part.link, part.plugin === opts.current_plugin); | ||
url = opts.pluginOptionLikeLink( | ||
part.plugin, | ||
part.entrypoint, | ||
'option', | ||
part.link, | ||
part.plugin === opts.current_plugin, | ||
); | ||
} | ||
@@ -78,3 +84,9 @@ destination.push(opts.formatOptionName(part, url)); | ||
if (part.plugin && opts.pluginOptionLikeLink) { | ||
url = opts.pluginOptionLikeLink(part.plugin, 'retval', part.link, part.plugin === opts.current_plugin); | ||
url = opts.pluginOptionLikeLink( | ||
part.plugin, | ||
part.entrypoint, | ||
'retval', | ||
part.link, | ||
part.plugin === opts.current_plugin, | ||
); | ||
} | ||
@@ -81,0 +93,0 @@ destination.push(opts.formatReturnValue(part, url)); |
@@ -15,2 +15,6 @@ /* | ||
export function quoteHTMLArg(text: string): string { | ||
return quoteHTML(text).replace(/"/g, '"'); | ||
} | ||
function formatOptionLikePlain( | ||
@@ -24,3 +28,3 @@ part: OptionNamePart | ReturnValuePart, | ||
if (url) { | ||
link_start = `<a href="${quoteHTML(encodeURI(url))}">`; | ||
link_start = `<a href="${quoteHTMLArg(encodeURI(url))}">`; | ||
link_end = '</a>'; | ||
@@ -44,7 +48,9 @@ } | ||
formatItalic: (part) => `<em>${quoteHTML(part.text)}</em>`, | ||
formatLink: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatLink: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatModule: (part, url) => | ||
url ? `<a href='${url}'>${quoteHTML(part.fqcn)}</a>` : `<span>${quoteHTML(part.fqcn)}</span>`, | ||
url | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}'>${quoteHTML(part.fqcn)}</a>` | ||
: `<span>${quoteHTML(part.fqcn)}</span>`, | ||
formatRSTRef: (part) => `<span>${quoteHTML(part.text)}</span>`, | ||
formatURL: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatURL: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatText: (part) => quoteHTML(part.text), | ||
@@ -55,3 +61,5 @@ formatEnvVariable: (part) => `<code>${quoteHTML(part.name)}</code>`, | ||
formatPlugin: (part, url) => | ||
url ? `<a href='${url}'>${quoteHTML(part.plugin.fqcn)}</a>` : `<span>${quoteHTML(part.plugin.fqcn)}</span>`, | ||
url | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}'>${quoteHTML(part.plugin.fqcn)}</a>` | ||
: `<span>${quoteHTML(part.plugin.fqcn)}</span>`, | ||
formatReturnValue: (part, url) => formatOptionLikePlain(part, url, 'retval'), | ||
@@ -68,3 +76,3 @@ }; | ||
if (url) { | ||
link_start = `<a class="reference internal" href="${quoteHTML( | ||
link_start = `<a class="reference internal" href="${quoteHTMLArg( | ||
encodeURI(url), | ||
@@ -105,9 +113,9 @@ )}"><span class="std std-ref"><span class="pre">`; | ||
formatItalic: (part) => `<em>${quoteHTML(part.text)}</em>`, | ||
formatLink: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatLink: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(part.text)}</a>`, | ||
formatModule: (part, url) => | ||
url | ||
? `<a href='${url}' class='module'>${quoteHTML(part.fqcn)}</a>` | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}' class='module'>${quoteHTML(part.fqcn)}</a>` | ||
: `<span class='module'>${quoteHTML(part.fqcn)}</span>`, | ||
formatRSTRef: (part) => `<span class='module'>${quoteHTML(part.text)}</span>`, | ||
formatURL: (part) => `<a href='${quoteHTML(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatURL: (part) => `<a href='${quoteHTMLArg(encodeURI(part.url))}'>${quoteHTML(encodeURI(part.url))}</a>`, | ||
formatText: (part) => quoteHTML(part.text), | ||
@@ -119,3 +127,3 @@ formatEnvVariable: (part) => `<code class="xref std std-envvar literal notranslate">${quoteHTML(part.name)}</code>`, | ||
url | ||
? `<a href='${url}' class='module'>${quoteHTML(part.plugin.fqcn)}</a>` | ||
? `<a href='${quoteHTMLArg(encodeURI(url))}' class='module'>${quoteHTML(part.plugin.fqcn)}</a>` | ||
: `<span class='module'>${quoteHTML(part.plugin.fqcn)}</span>`, | ||
@@ -122,0 +130,0 @@ formatReturnValue: (part, url) => formatOptionLikeAntsibullDocs(part, url, 'retval'), |
@@ -12,4 +12,5 @@ /* | ||
// Output | ||
export { toAnsibleDocText } from './ansible-doc-text'; | ||
export { quoteHTML, toHTML } from './html'; | ||
export { quoteMD, toMD } from './md'; | ||
export { quoteRST, toRST } from './rst'; |
@@ -11,2 +11,3 @@ /* | ||
import { OptionNamePart, Paragraph, ReturnValuePart } from './dom'; | ||
import { quoteHTMLArg } from './html'; | ||
import { addToDestination } from './format'; | ||
@@ -26,3 +27,3 @@ | ||
if (url) { | ||
link_start = `<a href="${quoteMD(encodeURI(url))}">`; | ||
link_start = `<a href="${quoteMD(quoteHTMLArg(encodeURI(url)))}">`; | ||
link_end = '</a>'; | ||
@@ -29,0 +30,0 @@ } |
@@ -46,4 +46,13 @@ /* | ||
/** Should be provided if parsing documentation of a specific role's entrypoint. */ | ||
role_entrypoint?: string; | ||
/** If set to 'true', only 'classic' Ansible docs markup is accepted. */ | ||
only_classic_markup?: boolean; | ||
onlyClassicMarkup?: boolean; | ||
/** If set to 'true' (default is 'false'), add source information to every part ('source' attribute). */ | ||
addSource?: boolean; | ||
/** If set to 'true' (default is 'true'), include the faulty markup in error messages. */ | ||
helpfulErrors?: boolean; | ||
} | ||
@@ -99,2 +108,3 @@ | ||
plugin: PluginIdentifier, | ||
entrypoint: string | undefined, | ||
what: 'option' | 'retval', | ||
@@ -121,2 +131,4 @@ name: string[], | ||
export interface AnsibleDocTextOptions extends CommonExportOptions, CommonFormatOptions {} | ||
export function mergeOpts<T extends CommonFormatOptions>(options: T, fallback: AllFormatOptions): T & AllFormatOptions { | ||
@@ -123,0 +135,0 @@ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ |
@@ -18,4 +18,7 @@ /* | ||
it('simple string', (): void => { | ||
expect(parse('test')).toEqual([[{ type: PartType.TEXT, text: 'test' }]]); | ||
expect(parse('test')).toEqual([[{ type: PartType.TEXT, text: 'test', source: undefined }]]); | ||
}); | ||
it('simple string (with source)', (): void => { | ||
expect(parse('test', { addSource: true })).toEqual([[{ type: PartType.TEXT, text: 'test', source: 'test' }]]); | ||
}); | ||
it('classic markup test', (): void => { | ||
@@ -28,21 +31,48 @@ expect( | ||
[ | ||
{ type: PartType.TEXT, text: 'foo ' }, | ||
{ type: PartType.ITALIC, text: 'bar' }, | ||
{ type: PartType.TEXT, text: ' baz ' }, | ||
{ type: PartType.CODE, text: ' bam ' }, | ||
{ type: PartType.TEXT, text: ' ' }, | ||
{ type: PartType.BOLD, text: ' ( boo ' }, | ||
{ type: PartType.TEXT, text: ' ) ' }, | ||
{ type: PartType.URL, url: 'https://example.com/?foo=bar' }, | ||
{ type: PartType.HORIZONTAL_LINE }, | ||
{ type: PartType.TEXT, text: ' ' }, | ||
{ type: PartType.LINK, text: 'foo', url: 'https://bar.com' }, | ||
{ type: PartType.TEXT, text: ' ' }, | ||
{ type: PartType.RST_REF, text: ' a', ref: 'b ' }, | ||
{ type: PartType.MODULE, fqcn: 'foo.bar.baz' }, | ||
{ type: PartType.TEXT, text: 'HORIZONTALLINEx ' }, | ||
{ type: PartType.MODULE, fqcn: 'foo.bar.baz.bam' }, | ||
{ type: PartType.TEXT, text: 'foo ', source: undefined }, | ||
{ type: PartType.ITALIC, text: 'bar', source: undefined }, | ||
{ type: PartType.TEXT, text: ' baz ', source: undefined }, | ||
{ type: PartType.CODE, text: ' bam ', source: undefined }, | ||
{ type: PartType.TEXT, text: ' ', source: undefined }, | ||
{ type: PartType.BOLD, text: ' ( boo ', source: undefined }, | ||
{ type: PartType.TEXT, text: ' ) ', source: undefined }, | ||
{ type: PartType.URL, url: 'https://example.com/?foo=bar', source: undefined }, | ||
{ type: PartType.HORIZONTAL_LINE, source: undefined }, | ||
{ type: PartType.TEXT, text: ' ', source: undefined }, | ||
{ type: PartType.LINK, text: 'foo', url: 'https://bar.com', source: undefined }, | ||
{ type: PartType.TEXT, text: ' ', source: undefined }, | ||
{ type: PartType.RST_REF, text: ' a', ref: 'b ', source: undefined }, | ||
{ type: PartType.MODULE, fqcn: 'foo.bar.baz', source: undefined }, | ||
{ type: PartType.TEXT, text: 'HORIZONTALLINEx ', source: undefined }, | ||
{ type: PartType.MODULE, fqcn: 'foo.bar.baz.bam', source: undefined }, | ||
], | ||
]); | ||
}); | ||
it('classic markup test (with source)', (): void => { | ||
expect( | ||
parse( | ||
'foo I(bar) baz C( bam ) B( ( boo ) ) U(https://example.com/?foo=bar)HORIZONTALLINE L(foo , https://bar.com) R( a , b )M(foo.bar.baz)HORIZONTALLINEx M(foo.bar.baz.bam)', | ||
{ addSource: true }, | ||
), | ||
).toEqual([ | ||
[ | ||
{ type: PartType.TEXT, text: 'foo ', source: 'foo ' }, | ||
{ type: PartType.ITALIC, text: 'bar', source: 'I(bar)' }, | ||
{ type: PartType.TEXT, text: ' baz ', source: ' baz ' }, | ||
{ type: PartType.CODE, text: ' bam ', source: 'C( bam )' }, | ||
{ type: PartType.TEXT, text: ' ', source: ' ' }, | ||
{ type: PartType.BOLD, text: ' ( boo ', source: 'B( ( boo )' }, | ||
{ type: PartType.TEXT, text: ' ) ', source: ' ) ' }, | ||
{ type: PartType.URL, url: 'https://example.com/?foo=bar', source: 'U(https://example.com/?foo=bar)' }, | ||
{ type: PartType.HORIZONTAL_LINE, source: 'HORIZONTALLINE' }, | ||
{ type: PartType.TEXT, text: ' ', source: ' ' }, | ||
{ type: PartType.LINK, text: 'foo', url: 'https://bar.com', source: 'L(foo , https://bar.com)' }, | ||
{ type: PartType.TEXT, text: ' ', source: ' ' }, | ||
{ type: PartType.RST_REF, text: ' a', ref: 'b ', source: 'R( a , b )' }, | ||
{ type: PartType.MODULE, fqcn: 'foo.bar.baz', source: 'M(foo.bar.baz)' }, | ||
{ type: PartType.TEXT, text: 'HORIZONTALLINEx ', source: 'HORIZONTALLINEx ' }, | ||
{ type: PartType.MODULE, fqcn: 'foo.bar.baz.bam', source: 'M(foo.bar.baz.bam)' }, | ||
], | ||
]); | ||
}); | ||
it('classic markup test II', (): void => { | ||
@@ -52,22 +82,22 @@ expect( | ||
'foo I(bar) baz C( bam ) B( ( boo ) ) U(https://example.com/?foo=bar)HORIZONTALLINE L(foo , https://bar.com) R( a , b )M(foo.bar.baz)HORIZONTALLINEx M(foo.bar.baz.bam)', | ||
{ only_classic_markup: true }, | ||
{ onlyClassicMarkup: true }, | ||
), | ||
).toEqual([ | ||
[ | ||
{ type: PartType.TEXT, text: 'foo ' }, | ||
{ type: PartType.ITALIC, text: 'bar' }, | ||
{ type: PartType.TEXT, text: ' baz ' }, | ||
{ type: PartType.CODE, text: ' bam ' }, | ||
{ type: PartType.TEXT, text: ' ' }, | ||
{ type: PartType.BOLD, text: ' ( boo ' }, | ||
{ type: PartType.TEXT, text: ' ) ' }, | ||
{ type: PartType.URL, url: 'https://example.com/?foo=bar' }, | ||
{ type: PartType.HORIZONTAL_LINE }, | ||
{ type: PartType.TEXT, text: ' ' }, | ||
{ type: PartType.LINK, text: 'foo', url: 'https://bar.com' }, | ||
{ type: PartType.TEXT, text: ' ' }, | ||
{ type: PartType.RST_REF, text: ' a', ref: 'b ' }, | ||
{ type: PartType.MODULE, fqcn: 'foo.bar.baz' }, | ||
{ type: PartType.TEXT, text: 'HORIZONTALLINEx ' }, | ||
{ type: PartType.MODULE, fqcn: 'foo.bar.baz.bam' }, | ||
{ type: PartType.TEXT, text: 'foo ', source: undefined }, | ||
{ type: PartType.ITALIC, text: 'bar', source: undefined }, | ||
{ type: PartType.TEXT, text: ' baz ', source: undefined }, | ||
{ type: PartType.CODE, text: ' bam ', source: undefined }, | ||
{ type: PartType.TEXT, text: ' ', source: undefined }, | ||
{ type: PartType.BOLD, text: ' ( boo ', source: undefined }, | ||
{ type: PartType.TEXT, text: ' ) ', source: undefined }, | ||
{ type: PartType.URL, url: 'https://example.com/?foo=bar', source: undefined }, | ||
{ type: PartType.HORIZONTAL_LINE, source: undefined }, | ||
{ type: PartType.TEXT, text: ' ', source: undefined }, | ||
{ type: PartType.LINK, text: 'foo', url: 'https://bar.com', source: undefined }, | ||
{ type: PartType.TEXT, text: ' ', source: undefined }, | ||
{ type: PartType.RST_REF, text: ' a', ref: 'b ', source: undefined }, | ||
{ type: PartType.MODULE, fqcn: 'foo.bar.baz', source: undefined }, | ||
{ type: PartType.TEXT, text: 'HORIZONTALLINEx ', source: undefined }, | ||
{ type: PartType.MODULE, fqcn: 'foo.bar.baz.bam', source: undefined }, | ||
], | ||
@@ -79,14 +109,47 @@ ]); | ||
[ | ||
{ type: PartType.TEXT, text: 'foo ' }, | ||
{ type: PartType.ENV_VARIABLE, name: 'a),b' }, | ||
{ type: PartType.TEXT, text: ' ' }, | ||
{ type: PartType.PLUGIN, plugin: { fqcn: 'foo.bar.baz', type: 'bam' } }, | ||
{ type: PartType.TEXT, text: ' baz ' }, | ||
{ type: PartType.OPTION_VALUE, value: ' b,na)\\m, ' }, | ||
{ type: PartType.TEXT, text: ' ' }, | ||
{ type: PartType.OPTION_NAME, plugin: undefined, link: ['foo'], name: 'foo', value: undefined }, | ||
{ type: PartType.TEXT, text: ' ' }, | ||
{ type: PartType.TEXT, text: 'foo ', source: undefined }, | ||
{ type: PartType.ENV_VARIABLE, name: 'a),b', source: undefined }, | ||
{ type: PartType.TEXT, text: ' ', source: undefined }, | ||
{ type: PartType.PLUGIN, plugin: { fqcn: 'foo.bar.baz', type: 'bam' }, source: undefined }, | ||
{ type: PartType.TEXT, text: ' baz ', source: undefined }, | ||
{ type: PartType.OPTION_VALUE, value: ' b,na)\\m, ', source: undefined }, | ||
{ type: PartType.TEXT, text: ' ', source: undefined }, | ||
{ | ||
type: PartType.OPTION_NAME, | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
{ type: PartType.TEXT, text: ' ', source: undefined }, | ||
], | ||
]); | ||
}); | ||
it('semantic markup test (with source)', (): void => { | ||
expect(parse('foo E(a\\),b) P(foo.bar.baz#bam) baz V( b\\,\\na\\)\\\\m\\, ) O(foo) ', { addSource: true })).toEqual( | ||
[ | ||
[ | ||
{ type: PartType.TEXT, text: 'foo ', source: 'foo ' }, | ||
{ type: PartType.ENV_VARIABLE, name: 'a),b', source: 'E(a\\),b)' }, | ||
{ type: PartType.TEXT, text: ' ', source: ' ' }, | ||
{ type: PartType.PLUGIN, plugin: { fqcn: 'foo.bar.baz', type: 'bam' }, source: 'P(foo.bar.baz#bam)' }, | ||
{ type: PartType.TEXT, text: ' baz ', source: ' baz ' }, | ||
{ type: PartType.OPTION_VALUE, value: ' b,na)\\m, ', source: 'V( b\\,\\na\\)\\\\m\\, )' }, | ||
{ type: PartType.TEXT, text: ' ', source: ' ' }, | ||
{ | ||
type: PartType.OPTION_NAME, | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: undefined, | ||
source: 'O(foo)', | ||
}, | ||
{ type: PartType.TEXT, text: ' ', source: ' ' }, | ||
], | ||
], | ||
); | ||
}); | ||
it('semantic markup option name', (): void => { | ||
@@ -98,5 +161,7 @@ expect(parse('O(foo)')).toEqual([ | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -110,5 +175,7 @@ ], | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -122,5 +189,7 @@ ], | ||
plugin: { fqcn: 'foo.bar.baz', type: 'bam' }, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -134,5 +203,7 @@ ], | ||
plugin: { fqcn: 'foo.bar.baz', type: 'bam' }, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -146,5 +217,7 @@ ], | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: 'bar', | ||
source: undefined, | ||
}, | ||
@@ -158,5 +231,7 @@ ], | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo', 'baz'], | ||
name: 'foo.baz', | ||
value: 'bam', | ||
source: undefined, | ||
}, | ||
@@ -170,5 +245,7 @@ ], | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo', 'baz', 'boo'], | ||
name: 'foo[1].baz[bam.bar.boing].boo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -182,5 +259,7 @@ ], | ||
plugin: { fqcn: 'bar.baz.bam.boo', type: 'lookup' }, | ||
entrypoint: undefined, | ||
link: ['foo', 'baz', 'boo'], | ||
name: 'foo[1].baz[bam.bar.boing].boo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -196,5 +275,7 @@ ], | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -208,5 +289,7 @@ ], | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -220,5 +303,7 @@ ], | ||
plugin: { fqcn: 'foo.bar.baz', type: 'bam' }, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -232,5 +317,7 @@ ], | ||
plugin: { fqcn: 'foo.bar.baz', type: 'bam' }, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -244,5 +331,7 @@ ], | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo'], | ||
name: 'foo', | ||
value: 'bar', | ||
source: undefined, | ||
}, | ||
@@ -256,5 +345,7 @@ ], | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo', 'baz'], | ||
name: 'foo.baz', | ||
value: 'bam', | ||
source: undefined, | ||
}, | ||
@@ -268,5 +359,7 @@ ], | ||
plugin: undefined, | ||
entrypoint: undefined, | ||
link: ['foo', 'baz', 'boo'], | ||
name: 'foo[1].baz[bam.bar.boing].boo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -280,5 +373,7 @@ ], | ||
plugin: { fqcn: 'bar.baz.bam.boo', type: 'lookup' }, | ||
entrypoint: undefined, | ||
link: ['foo', 'baz', 'boo'], | ||
name: 'foo[1].baz[bam.bar.boing].boo', | ||
value: undefined, | ||
source: undefined, | ||
}, | ||
@@ -289,21 +384,21 @@ ], | ||
it('bad parameter parsing (no escaping, throw error)', (): void => { | ||
expect(async () => parse('M(', { errors: 'exception' })).rejects.toThrow( | ||
expect(async () => parse('M(', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing M() at index 1: Cannot find closing ")" after last parameter', | ||
); | ||
expect(async () => parse('M(foo', { errors: 'exception' })).rejects.toThrow( | ||
expect(async () => parse('M(foo', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing M() at index 1: Cannot find closing ")" after last parameter', | ||
); | ||
expect(async () => parse('L(foo)', { errors: 'exception' })).rejects.toThrow( | ||
expect(async () => parse('L(foo)', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing L() at index 1: Cannot find comma separating parameter 1 from the next one', | ||
); | ||
expect(async () => parse('L(foo,bar', { errors: 'exception' })).rejects.toThrow( | ||
expect(async () => parse('L(foo,bar', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing L() at index 1: Cannot find closing ")" after last parameter', | ||
); | ||
expect(async () => parse('L(foo), bar', { errors: 'exception' })).rejects.toThrow( | ||
expect(async () => parse('L(foo), bar', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing L() at index 1: Cannot find closing ")" after last parameter', | ||
); | ||
expect(async () => parse('P(', { errors: 'exception' })).rejects.toThrow( | ||
expect(async () => parse('P(', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing P() at index 1: Cannot find closing ")" after last parameter', | ||
); | ||
expect(async () => parse('P(foo', { errors: 'exception' })).rejects.toThrow( | ||
expect(async () => parse('P(foo', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing P() at index 1: Cannot find closing ")" after last parameter', | ||
@@ -313,45 +408,48 @@ ); | ||
it('bad module ref (throw error)', (): void => { | ||
expect(async () => parse('M(foo)', { errors: 'exception' })).rejects.toThrow( | ||
'While parsing M() at index 1: Error: Module name "foo" is not a FQCN', | ||
expect(async () => parse('M(foo)', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing M() at index 1: Module name "foo" is not a FQCN', | ||
); | ||
expect(async () => parse(' M(foo.bar)', { errors: 'exception' })).rejects.toThrow( | ||
'While parsing M() at index 2: Error: Module name "foo.bar" is not a FQCN', | ||
expect(async () => parse(' M(foo.bar)', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing M() at index 2: Module name "foo.bar" is not a FQCN', | ||
); | ||
expect(async () => parse(' M(foo. bar.baz)', { errors: 'exception' })).rejects.toThrow( | ||
'While parsing M() at index 3: Error: Module name "foo. bar.baz" is not a FQCN', | ||
expect(async () => parse(' M(foo. bar.baz)', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing M() at index 3: Module name "foo. bar.baz" is not a FQCN', | ||
); | ||
expect(async () => parse(' M(foo)', { errors: 'exception' })).rejects.toThrow( | ||
'While parsing M() at index 4: Error: Module name "foo" is not a FQCN', | ||
expect(async () => parse(' M(foo)', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing M() at index 4: Module name "foo" is not a FQCN', | ||
); | ||
}); | ||
it('bad plugin ref (throw error)', (): void => { | ||
expect(async () => parse('P(foo#bar)', { errors: 'exception' })).rejects.toThrow( | ||
'While parsing P() at index 1: Error: Parameter "foo#bar" is not of the form FQCN#type', | ||
expect(async () => parse('P(foo)', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing P() at index 1: Parameter "foo" is not of the form FQCN#type', | ||
); | ||
expect(async () => parse('P(f o.b r.b z#bar)', { errors: 'exception' })).rejects.toThrow( | ||
'While parsing P() at index 1: Error: Plugin name "f o.b r.b z" is not a FQCN', | ||
expect(async () => parse('P(f o.b r.b z#bar)', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing P() at index 1: Plugin name "f o.b r.b z" is not a FQCN', | ||
); | ||
expect(async () => parse('P(foo.bar.baz#b m)', { errors: 'exception' })).rejects.toThrow( | ||
'While parsing P() at index 1: Error: Plugin type "b m" is not valid', | ||
expect(async () => parse('P(foo.bar.baz#b m)', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing P() at index 1: Plugin type "b m" is not valid', | ||
); | ||
}); | ||
it('bad option name/return value (throw error)', (): void => { | ||
expect(async () => parse('O(f o.b r.b z#bam:foobar)', { errors: 'exception' })).rejects.toThrow( | ||
'While parsing O() at index 1: Error: Plugin name "f o.b r.b z" is not a FQCN', | ||
expect(async () => | ||
parse('O(f o.b r.b z#bam:foobar)', { errors: 'exception', helpfulErrors: false }), | ||
).rejects.toThrow('While parsing O() at index 1: Plugin name "f o.b r.b z" is not a FQCN'); | ||
expect(async () => | ||
parse('O(foo.bar.baz#b m:foobar)', { errors: 'exception', helpfulErrors: false }), | ||
).rejects.toThrow('While parsing O() at index 1: Plugin type "b m" is not valid'); | ||
expect(async () => parse('O(foo:bar:baz)', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing O() at index 1: Invalid option/return value name "foo:bar:baz"', | ||
); | ||
expect(async () => parse('O(foo.bar.baz#b m:foobar)', { errors: 'exception' })).rejects.toThrow( | ||
'While parsing O() at index 1: Error: Plugin type "b m" is not valid', | ||
expect(async () => parse('O(foo.bar.baz#role:bam)', { errors: 'exception', helpfulErrors: false })).rejects.toThrow( | ||
'While parsing O() at index 1: Role reference is missing entrypoint', | ||
); | ||
expect(async () => parse('O(foo:bar:baz)', { errors: 'exception' })).rejects.toThrow( | ||
'While parsing O() at index 1: Error: Invalid option/return value name "foo:bar:baz"', | ||
); | ||
}); | ||
it('bad parameter parsing (no escaping, error message)', (): void => { | ||
expect(parse('M(')).toEqual([ | ||
expect(parse('M(', { helpfulErrors: false })).toEqual([ | ||
[{ type: PartType.ERROR, message: 'While parsing M() at index 1: Cannot find closing ")" after last parameter' }], | ||
]); | ||
expect(parse('M(foo', { errors: 'message' })).toEqual([ | ||
expect(parse('M(foo', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[{ type: PartType.ERROR, message: 'While parsing M() at index 1: Cannot find closing ")" after last parameter' }], | ||
]); | ||
expect(parse('L(foo)', { errors: 'message' })).toEqual([ | ||
expect(parse('L(foo)', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[ | ||
@@ -364,12 +462,12 @@ { | ||
]); | ||
expect(parse('L(foo,bar', { errors: 'message' })).toEqual([ | ||
expect(parse('L(foo,bar', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[{ type: PartType.ERROR, message: 'While parsing L() at index 1: Cannot find closing ")" after last parameter' }], | ||
]); | ||
expect(parse('L(foo), bar', { errors: 'message' })).toEqual([ | ||
expect(parse('L(foo), bar', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[{ type: PartType.ERROR, message: 'While parsing L() at index 1: Cannot find closing ")" after last parameter' }], | ||
]); | ||
expect(parse('P(')).toEqual([ | ||
expect(parse('P(', { helpfulErrors: false })).toEqual([ | ||
[{ type: PartType.ERROR, message: 'While parsing P() at index 1: Cannot find closing ")" after last parameter' }], | ||
]); | ||
expect(parse('P(foo', { errors: 'message' })).toEqual([ | ||
expect(parse('P(foo', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[{ type: PartType.ERROR, message: 'While parsing P() at index 1: Cannot find closing ")" after last parameter' }], | ||
@@ -379,12 +477,12 @@ ]); | ||
it('bad module ref (error message)', (): void => { | ||
expect(parse('M(foo)')).toEqual([ | ||
[{ type: PartType.ERROR, message: 'While parsing M() at index 1: Error: Module name "foo" is not a FQCN' }], | ||
expect(parse('M(foo)', { helpfulErrors: false })).toEqual([ | ||
[{ type: PartType.ERROR, message: 'While parsing M() at index 1: Module name "foo" is not a FQCN' }], | ||
]); | ||
expect(parse(' M(foo.bar)', { errors: 'message' })).toEqual([ | ||
expect(parse(' M(foo.bar)', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[ | ||
{ type: PartType.TEXT, text: ' ' }, | ||
{ type: PartType.ERROR, message: 'While parsing M() at index 2: Error: Module name "foo.bar" is not a FQCN' }, | ||
{ type: PartType.ERROR, message: 'While parsing M() at index 2: Module name "foo.bar" is not a FQCN' }, | ||
], | ||
]); | ||
expect(parse(' M(foo. bar.baz)', { errors: 'message' })).toEqual([ | ||
expect(parse(' M(foo. bar.baz)', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[ | ||
@@ -394,10 +492,10 @@ { type: PartType.TEXT, text: ' ' }, | ||
type: PartType.ERROR, | ||
message: 'While parsing M() at index 3: Error: Module name "foo. bar.baz" is not a FQCN', | ||
message: 'While parsing M() at index 3: Module name "foo. bar.baz" is not a FQCN', | ||
}, | ||
], | ||
]); | ||
expect(parse(' M(foo) baz', { errors: 'message' })).toEqual([ | ||
expect(parse(' M(foo) baz', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[ | ||
{ type: PartType.TEXT, text: ' ' }, | ||
{ type: PartType.ERROR, message: 'While parsing M() at index 4: Error: Module name "foo" is not a FQCN' }, | ||
{ type: PartType.ERROR, message: 'While parsing M() at index 4: Module name "foo" is not a FQCN' }, | ||
{ type: PartType.TEXT, text: ' baz' }, | ||
@@ -408,23 +506,23 @@ ], | ||
it('bad plugin ref (error message)', (): void => { | ||
expect(parse('P(foo#bar)')).toEqual([ | ||
expect(parse('P(foo)', { helpfulErrors: false })).toEqual([ | ||
[ | ||
{ | ||
type: PartType.ERROR, | ||
message: 'While parsing P() at index 1: Error: Parameter "foo#bar" is not of the form FQCN#type', | ||
message: 'While parsing P() at index 1: Parameter "foo" is not of the form FQCN#type', | ||
}, | ||
], | ||
]); | ||
expect(parse('P(f o.b r.b z#bar)', { errors: 'message' })).toEqual([ | ||
expect(parse('P(f o.b r.b z#bar)', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[ | ||
{ | ||
type: PartType.ERROR, | ||
message: 'While parsing P() at index 1: Error: Plugin name "f o.b r.b z" is not a FQCN', | ||
message: 'While parsing P() at index 1: Plugin name "f o.b r.b z" is not a FQCN', | ||
}, | ||
], | ||
]); | ||
expect(parse('P(foo.bar.baz#b m)', { errors: 'message' })).toEqual([ | ||
expect(parse('P(foo.bar.baz#b m)', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[ | ||
{ | ||
type: PartType.ERROR, | ||
message: 'While parsing P() at index 1: Error: Plugin type "b m" is not valid', | ||
message: 'While parsing P() at index 1: Plugin type "b m" is not valid', | ||
}, | ||
@@ -435,26 +533,34 @@ ], | ||
it('bad option name/return value (error message)', (): void => { | ||
expect(parse('O(f o.b r.b z#bam:foobar)')).toEqual([ | ||
expect(parse('O(f o.b r.b z#bam:foobar)', { helpfulErrors: false })).toEqual([ | ||
[ | ||
{ | ||
type: PartType.ERROR, | ||
message: 'While parsing O() at index 1: Error: Plugin name "f o.b r.b z" is not a FQCN', | ||
message: 'While parsing O() at index 1: Plugin name "f o.b r.b z" is not a FQCN', | ||
}, | ||
], | ||
]); | ||
expect(parse('O(foo.bar.baz#b m:foobar)', { errors: 'message' })).toEqual([ | ||
expect(parse('O(foo.bar.baz#b m:foobar)', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[ | ||
{ | ||
type: PartType.ERROR, | ||
message: 'While parsing O() at index 1: Error: Plugin type "b m" is not valid', | ||
message: 'While parsing O() at index 1: Plugin type "b m" is not valid', | ||
}, | ||
], | ||
]); | ||
expect(parse('O(foo:bar:baz)', { errors: 'message' })).toEqual([ | ||
expect(parse('O(foo:bar:baz)', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[ | ||
{ | ||
type: PartType.ERROR, | ||
message: 'While parsing O() at index 1: Error: Invalid option/return value name "foo:bar:baz"', | ||
message: 'While parsing O() at index 1: Invalid option/return value name "foo:bar:baz"', | ||
}, | ||
], | ||
]); | ||
expect(parse('O(foo.bar.baz#role:bam)', { errors: 'message', helpfulErrors: false })).toEqual([ | ||
[ | ||
{ | ||
type: PartType.ERROR, | ||
message: 'While parsing O() at index 1: Role reference is missing entrypoint', | ||
}, | ||
], | ||
]); | ||
}); | ||
@@ -490,2 +596,3 @@ it('bad parameter parsing (no escaping, ignore error)', (): void => { | ||
expect(parse('O(foo:bar:baz)', { errors: 'ignore' })).toEqual([[]]); | ||
expect(parse('O(foo.bar.baz#role:bam)', { errors: 'ignore' })).toEqual([[]]); | ||
}); | ||
@@ -527,4 +634,8 @@ }); | ||
it('combine wrong regexp with command map', (): void => { | ||
expect(parseString('A B()', commandsReA, commandsMapA, { helpfulErrors: false }, '')).toEqual([ | ||
{ message: 'While parsing A at index 1: boo!', type: PartType.ERROR }, | ||
{ text: ' B()', type: PartType.TEXT }, | ||
]); | ||
expect(parseString('A B()', commandsReA, commandsMapA, {}, '')).toEqual([ | ||
{ message: 'While parsing A at index 1: Error: boo!', type: PartType.ERROR }, | ||
{ message: 'While parsing "A" at index 1: boo!', type: PartType.ERROR }, | ||
{ text: ' B()', type: PartType.TEXT }, | ||
@@ -531,0 +642,0 @@ ]); |
@@ -37,2 +37,3 @@ /* | ||
type: PartType.OPTION_NAME | PartType.RETURN_VALUE, | ||
source: string | undefined, | ||
): OptionNamePart | ReturnValuePart { | ||
@@ -47,2 +48,3 @@ let value: string | undefined; | ||
let plugin: PluginIdentifier | undefined; | ||
let entrypoint: string | undefined; | ||
if (m) { | ||
@@ -64,3 +66,14 @@ const pluginFqcn = m[1] as string; | ||
plugin = opts.current_plugin; | ||
entrypoint = opts.role_entrypoint; | ||
} | ||
if (plugin?.type === 'role') { | ||
const idx = text.indexOf(':'); | ||
if (idx >= 0) { | ||
entrypoint = text.substr(0, idx); | ||
text = text.substr(idx + 1); | ||
} | ||
if (entrypoint === undefined) { | ||
throw Error('Role reference is missing entrypoint'); | ||
} | ||
} | ||
if (/[:#]/.test(text)) { | ||
@@ -72,5 +85,7 @@ throw Error(`Invalid option/return value name "${text}"`); | ||
plugin: plugin, | ||
entrypoint: entrypoint, | ||
link: text.replace(/\[([^\]]*)\]/g, '').split('.'), | ||
name: text, | ||
value: value, | ||
source: source, | ||
}; | ||
@@ -82,4 +97,4 @@ } | ||
parameters: number; | ||
escaped_arguments?: boolean; | ||
process: (args: string[], opts: ParsingOptions) => AnyPart; | ||
escapedArguments?: boolean; | ||
process: (args: string[], opts: ParsingOptions, source: string | undefined) => AnyPart; | ||
} | ||
@@ -97,5 +112,5 @@ | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0] as string; | ||
return <ItalicPart>{ type: PartType.ITALIC, text: text }; | ||
return <ItalicPart>{ type: PartType.ITALIC, text: text, source: source }; | ||
}, | ||
@@ -107,5 +122,5 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0] as string; | ||
return <BoldPart>{ type: PartType.BOLD, text: text }; | ||
return <BoldPart>{ type: PartType.BOLD, text: text, source: source }; | ||
}, | ||
@@ -117,3 +132,3 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const fqcn = args[0] as string; | ||
@@ -123,3 +138,3 @@ if (!isFQCN(fqcn)) { | ||
} | ||
return <ModulePart>{ type: PartType.MODULE, fqcn: fqcn }; | ||
return <ModulePart>{ type: PartType.MODULE, fqcn: fqcn, source: source }; | ||
}, | ||
@@ -131,5 +146,5 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const url = args[0] as string; | ||
return <URLPart>{ type: PartType.URL, url: url }; | ||
return <URLPart>{ type: PartType.URL, url: url, source: source }; | ||
}, | ||
@@ -141,6 +156,6 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0] as string; | ||
const url = args[1] as string; | ||
return <LinkPart>{ type: PartType.LINK, text: text, url: url }; | ||
return <LinkPart>{ type: PartType.LINK, text: text, url: url, source: source }; | ||
}, | ||
@@ -152,6 +167,6 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0] as string; | ||
const ref = args[1] as string; | ||
return <RSTRefPart>{ type: PartType.RST_REF, text: text, ref: ref }; | ||
return <RSTRefPart>{ type: PartType.RST_REF, text: text, ref: ref, source: source }; | ||
}, | ||
@@ -163,5 +178,5 @@ }, | ||
old_markup: true, | ||
process: (args) => { | ||
process: (args, _, source) => { | ||
const text = args[0] as string; | ||
return <CodePart>{ type: PartType.CODE, text: text }; | ||
return <CodePart>{ type: PartType.CODE, text: text, source: source }; | ||
}, | ||
@@ -173,4 +188,4 @@ }, | ||
old_markup: true, | ||
process: () => { | ||
return <HorizontalLinePart>{ type: PartType.HORIZONTAL_LINE }; | ||
process: (_, __, source) => { | ||
return <HorizontalLinePart>{ type: PartType.HORIZONTAL_LINE, source: source }; | ||
}, | ||
@@ -182,5 +197,5 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args) => { | ||
const m = /^([^).]+\.[^).]+\.[^#]+)#(.+)$/.exec(args[0] as string); | ||
escapedArguments: true, | ||
process: (args, _, source) => { | ||
const m = /^([^#]*)#(.*)$/.exec(args[0] as string); | ||
if (!m) { | ||
@@ -197,3 +212,3 @@ throw Error(`Parameter "${args[0]}" is not of the form FQCN#type`); | ||
} | ||
return <PluginPart>{ type: PartType.PLUGIN, plugin: { fqcn: fqcn, type: type } }; | ||
return <PluginPart>{ type: PartType.PLUGIN, plugin: { fqcn: fqcn, type: type }, source: source }; | ||
}, | ||
@@ -204,6 +219,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args) => { | ||
escapedArguments: true, | ||
process: (args, _, source) => { | ||
const env = args[0] as string; | ||
return <EnvVariablePart>{ type: PartType.ENV_VARIABLE, name: env }; | ||
return <EnvVariablePart>{ type: PartType.ENV_VARIABLE, name: env, source: source }; | ||
}, | ||
@@ -214,6 +229,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args) => { | ||
escapedArguments: true, | ||
process: (args, _, source) => { | ||
const value = args[0] as string; | ||
return <OptionValuePart>{ type: PartType.OPTION_VALUE, value: value }; | ||
return <OptionValuePart>{ type: PartType.OPTION_VALUE, value: value, source: source }; | ||
}, | ||
@@ -224,6 +239,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args, opts) => { | ||
escapedArguments: true, | ||
process: (args, opts, source) => { | ||
const value = args[0] as string; | ||
return parseOptionLike(value, opts, PartType.OPTION_NAME); | ||
return parseOptionLike(value, opts, PartType.OPTION_NAME, source); | ||
}, | ||
@@ -234,6 +249,6 @@ }, | ||
parameters: 1, | ||
escaped_arguments: true, | ||
process: (args, opts) => { | ||
escapedArguments: true, | ||
process: (args, opts, source) => { | ||
const value = args[0] as string; | ||
return parseOptionLike(value, opts, PartType.RETURN_VALUE); | ||
return parseOptionLike(value, opts, PartType.RETURN_VALUE, source); | ||
}, | ||
@@ -276,5 +291,7 @@ }, | ||
if (index < length) { | ||
const text = input.slice(index); | ||
result.push(<TextPart>{ | ||
type: PartType.TEXT, | ||
text: input.slice(index), | ||
text: text, | ||
source: opts.addSource ? text : undefined, | ||
}); | ||
@@ -285,5 +302,7 @@ } | ||
if (match.index > index) { | ||
const text = input.slice(index, match.index); | ||
result.push(<TextPart>{ | ||
type: PartType.TEXT, | ||
text: input.slice(index, match.index), | ||
text: text, | ||
source: opts.addSource ? text : undefined, | ||
}); | ||
@@ -305,3 +324,3 @@ } | ||
args = []; | ||
} else if (command.escaped_arguments) { | ||
} else if (command.escapedArguments) { | ||
[args, endIndex, error] = parseEscapedArgs(input, endIndex, command.parameters); | ||
@@ -311,11 +330,19 @@ } else { | ||
} | ||
const source = opts.addSource ? input.slice(index, endIndex) : undefined; | ||
if (error === undefined) { | ||
try { | ||
result.push(command.process(args, opts)); | ||
} catch (exc) { | ||
result.push(command.process(args, opts, source)); | ||
} catch (exc: any) { | ||
error = `${exc}`; | ||
if (exc?.message !== undefined) { | ||
error = `${exc.message}`; | ||
} | ||
} | ||
} | ||
if (error !== undefined) { | ||
error = `While parsing ${cmd}${command.parameters > 0 ? '()' : ''} at index ${match.index + 1}${where}: ${error}`; | ||
const errorSource = | ||
opts.helpfulErrors ?? true | ||
? `"${input.slice(index, endIndex)}"` | ||
: `${cmd}${command.parameters > 0 ? '()' : ''}`; | ||
error = `While parsing ${errorSource} at index ${match.index + 1}${where}: ${error}`; | ||
switch (opts.errors || 'message') { | ||
@@ -328,2 +355,3 @@ case 'ignore': | ||
message: error, | ||
source: source, | ||
}); | ||
@@ -350,3 +378,3 @@ break; | ||
const opts_ = opts || {}; | ||
const commandRE = opts_.only_classic_markup ? CLASSIC_COMMAND_RE : COMMAND_RE; | ||
const commandRE = opts_.onlyClassicMarkup ? CLASSIC_COMMAND_RE : COMMAND_RE; | ||
return input.map((par, index) => | ||
@@ -353,0 +381,0 @@ parseString('' + par, commandRE, PARSER_COMMANDS, opts_, hasParagraphs ? ` of paragraph ${index + 1}` : ''), |
@@ -31,2 +31,6 @@ /* | ||
} | ||
if (part.entrypoint !== undefined) { | ||
result.push(part.entrypoint); | ||
result.push(':'); | ||
} | ||
result.push(part.name); | ||
@@ -33,0 +37,0 @@ if (part.value !== undefined) { |
@@ -15,2 +15,3 @@ /* | ||
import { toRST } from './rst'; | ||
import { toAnsibleDocText } from './ansible-doc-text'; | ||
@@ -23,15 +24,15 @@ describe('vectors', (): void => { | ||
if (test_data.html_opts) { | ||
if (test_data.html_opts.pluginLink) { | ||
test_data.html_opts.pluginLink = eval(test_data.html_opts.pluginLink); | ||
if (test_data.html_opts['pluginLink.js']) { | ||
test_data.html_opts.pluginLink = eval(test_data.html_opts['pluginLink.js']); | ||
} | ||
if (test_data.html_opts.pluginOptionLikeLink) { | ||
test_data.html_opts.pluginOptionLikeLink = eval(test_data.html_opts.pluginOptionLikeLink); | ||
if (test_data.html_opts['pluginOptionLikeLink.js']) { | ||
test_data.html_opts.pluginOptionLikeLink = eval(test_data.html_opts['pluginOptionLikeLink.js']); | ||
} | ||
} | ||
if (test_data.md_opts) { | ||
if (test_data.md_opts.pluginLink) { | ||
test_data.md_opts.pluginLink = eval(test_data.md_opts.pluginLink); | ||
if (test_data.md_opts['pluginLink.js']) { | ||
test_data.md_opts.pluginLink = eval(test_data.md_opts['pluginLink.js']); | ||
} | ||
if (test_data.md_opts.pluginOptionLikeLink) { | ||
test_data.md_opts.pluginOptionLikeLink = eval(test_data.md_opts.pluginOptionLikeLink); | ||
if (test_data.md_opts['pluginOptionLikeLink.js']) { | ||
test_data.md_opts.pluginOptionLikeLink = eval(test_data.md_opts['pluginOptionLikeLink.js']); | ||
} | ||
@@ -61,3 +62,10 @@ } | ||
} | ||
if (test_data.source !== undefined && test_data.ansible_doc_text !== undefined) { | ||
it(`${test_name} (Ansible doc => ansible-doc text output)`, (): void => { | ||
expect( | ||
toAnsibleDocText(parse(test_data.source, test_data.parse_opts), test_data.ansible_doc_text_opts), | ||
).toEqual(test_data.ansible_doc_text); | ||
}); | ||
} | ||
} | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
361388
96
4147