From be46a7257b36ce5519d56e50db12f91b82d194f4 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Fri, 10 Jan 2020 06:03:25 -0800 Subject: [PATCH] tools: update JSON header parsing for backticks Methods, events, and so on in headers in our documentation may (and should) be set off with backticks in the raw markdown. When that happens, the headers is misinterpreted by tools/json.js as not being a method or event. Update the JSON tool generator to accommodate backticks in this situation and add a test for this situation. Fixes: https://github.com/nodejs/node/issues/31290 PR-URL: https://github.com/nodejs/node/pull/31294 Reviewed-By: Richard Lau Reviewed-By: Anna Henningsen Reviewed-By: Luigi Pinca --- test/doctool/test-doctool-json.js | 68 +++++++++++++++++++ .../doc_with_backticks_in_headings.md | 13 ++++ tools/doc/json.js | 18 +++-- 3 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 test/fixtures/doc_with_backticks_in_headings.md diff --git a/test/doctool/test-doctool-json.js b/test/doctool/test-doctool-json.js index 7471a2e1f0693d..78afc818e9fae0 100644 --- a/test/doctool/test-doctool-json.js +++ b/test/doctool/test-doctool-json.js @@ -157,6 +157,74 @@ const testData = [ } ] } + }, + { + file: fixtures.path('doc_with_backticks_in_headings.md'), + json: { + type: 'module', + source: 'foo', + modules: [ + { + textRaw: 'Fhqwhgads', + name: 'fhqwhgads', + properties: [ + { + name: 'fullName', + textRaw: '`Fqhqwhgads.fullName`' + } + ], + classMethods: [ + { + name: 'again', + signatures: [ + { + params: [] + } + ], + textRaw: 'Class Method: `Fhqwhgads.again()`', + type: 'classMethod' + } + ], + classes: [ + { + textRaw: 'Class: `ComeOn`', + type: 'class', + name: 'ComeOn' + } + ], + ctors: [ + { + name: 'Fhqwhgads', + signatures: [ + { + params: [] + } + ], + textRaw: 'Constructor: `new Fhqwhgads()`', + type: 'ctor' + } + ], + methods: [ + { + textRaw: '`everybody.to(limit)`', + type: 'method', + name: 'to', + signatures: [{ params: [] }] + } + ], + events: [ + { + textRaw: "Event: `'FHQWHfest'`", + type: 'event', + name: 'FHQWHfest', + params: [] + } + ], + type: 'module', + displayName: 'Fhqwhgads' + } + ] + } } ]; diff --git a/test/fixtures/doc_with_backticks_in_headings.md b/test/fixtures/doc_with_backticks_in_headings.md new file mode 100644 index 00000000000000..74b4f3fd7ff39d --- /dev/null +++ b/test/fixtures/doc_with_backticks_in_headings.md @@ -0,0 +1,13 @@ +# Fhqwhgads + +## Class: `ComeOn` + +## `everybody.to(limit)` + +## Event: `'FHQWHfest'` + +## Constructor: `new Fhqwhgads()` + +## Class Method: `Fhqwhgads.again()` + +## `Fqhqwhgads.fullName` diff --git a/tools/doc/json.js b/tools/doc/json.js index e07486265cf0dd..94241d9903ef45 100644 --- a/tools/doc/json.js +++ b/tools/doc/json.js @@ -435,13 +435,15 @@ const r = String.raw; const eventPrefix = '^Event: +'; const classPrefix = '^[Cc]lass: +'; -const ctorPrefix = '^(?:[Cc]onstructor: +)?new +'; +const ctorPrefix = '^(?:[Cc]onstructor: +)?`?new +'; const classMethodPrefix = '^Class Method: +'; const maybeClassPropertyPrefix = '(?:Class Property: +)?'; const maybeQuote = '[\'"]?'; const notQuotes = '[^\'"]+'; +const maybeBacktick = '`?'; + // To include constructs like `readable\[Symbol.asyncIterator\]()` // or `readable.\_read(size)` (with Markdown escapes). const simpleId = r`(?:(?:\\?_)+|\b)\w+\b`; @@ -458,25 +460,27 @@ const noCallOrProp = '(?![.[(])'; const maybeExtends = `(?: +extends +${maybeAncestors}${classId})?`; +/* eslint-disable max-len */ const headingExpressions = [ { type: 'event', re: RegExp( - `${eventPrefix}${maybeQuote}(${notQuotes})${maybeQuote}$`, 'i') }, + `${eventPrefix}${maybeBacktick}${maybeQuote}(${notQuotes})${maybeQuote}${maybeBacktick}$`, 'i') }, { type: 'class', re: RegExp( - `${classPrefix}(${maybeAncestors}${classId})${maybeExtends}$`, '') }, + `${classPrefix}${maybeBacktick}(${maybeAncestors}${classId})${maybeExtends}${maybeBacktick}$`, '') }, { type: 'ctor', re: RegExp( - `${ctorPrefix}(${maybeAncestors}${classId})${callWithParams}$`, '') }, + `${ctorPrefix}(${maybeAncestors}${classId})${callWithParams}${maybeBacktick}$`, '') }, { type: 'classMethod', re: RegExp( - `${classMethodPrefix}${maybeAncestors}(${id})${callWithParams}$`, 'i') }, + `${classMethodPrefix}${maybeBacktick}${maybeAncestors}(${id})${callWithParams}${maybeBacktick}$`, 'i') }, { type: 'method', re: RegExp( - `^${maybeAncestors}(${id})${callWithParams}$`, 'i') }, + `^${maybeBacktick}${maybeAncestors}(${id})${callWithParams}${maybeBacktick}$`, 'i') }, { type: 'property', re: RegExp( - `^${maybeClassPropertyPrefix}${ancestors}(${id})${noCallOrProp}$`, 'i') }, + `^${maybeClassPropertyPrefix}${maybeBacktick}${ancestors}(${id})${maybeBacktick}${noCallOrProp}$`, 'i') }, ]; +/* eslint-enable max-len */ function newSection(header, file) { const text = textJoin(header.children, file);