diff --git a/antora/asam_macros/asam_macros.js b/antora/asam_macros/asam_macros.js index 4fff21c3ce2abd2ef3147a09ca6032a15e933ef1..4db08ddf704dbce757303cb82061b8d8192a8777 100644 --- a/antora/asam_macros/asam_macros.js +++ b/antora/asam_macros/asam_macros.js @@ -274,7 +274,6 @@ function replaceAutonavMacro( contentCatalog, pages, nav, component, version, fi * Traverses through the adoc files of a component-version-combination and replaces all found ASAM macros. * This covers the following macros: * autonav, reference, related, role_related, pages - * * @param {Object} contentCatalog - The complete content catalog provided by Antora. * @param {Array <Object>} pages - The array of pages for this component-version-combination. * @param {Array <Object>} navFiles - The navigation files for this component-version-combination. diff --git a/antora/consistent_numbering/lib/helper.js b/antora/consistent_numbering/lib/helper.js index c2ef1cde7a62f8f5729e6e1163dcb919e84f8add..981db8f07cc7dd3d90426846ea58a6eef072d669 100644 --- a/antora/consistent_numbering/lib/helper.js +++ b/antora/consistent_numbering/lib/helper.js @@ -160,6 +160,7 @@ function getIncludedPagesContentForExtensionFeatures( catalog, pagePartial, comp let numberOfImages = 0 let numberOfTables = 0 let numberOfExamples = 0 + let numberOfCodes = 0 let ignoreLine = false //------------- // Ignore everything between "ifndef::use-antora-rules[]" and the next "endif::[]" @@ -218,24 +219,26 @@ function getIncludedPagesContentForExtensionFeatures( catalog, pagePartial, comp let filteredPagesList = catalog.filter(file => file.src && file.src.path === targetPath) if (filteredPagesList.length > 0) { let includedPage = filteredPagesList[0] - let [numberOfLevelTwoSectionsIncluded, numberOfImagesIncluded, numberOfTablesIncluded, numberOfExamplesIncluded] = getIncludedPagesContentForExtensionFeatures(catalog, includedPage, componentAttributes, includeLeveloffset) + let [numberOfLevelTwoSectionsIncluded, numberOfImagesIncluded, numberOfTablesIncluded, numberOfCodesIncluded, numberOfExamplesIncluded] = getIncludedPagesContentForExtensionFeatures(catalog, includedPage, componentAttributes, includeLeveloffset) numberOfLevelTwoSections += numberOfLevelTwoSectionsIncluded numberOfImages += numberOfImagesIncluded numberOfTables += numberOfTablesIncluded numberOfExamples += numberOfExamplesIncluded + numberOfCodes += numberOfCodesIncluded } } } } //------------- - // Find all valid images (with "fig-" anchor) and tables (with "tab-" anchor) and examples (with "code-" anchor). + // Find all valid blocks (images, tables, examples, source/listing). //------------- const pageAnchorMap = ContentAnalyzer.getAnchorsFromPageOrPartial(catalog, pagePartial, componentAttributes) numberOfImages = [...pageAnchorMap].filter(([k,v]) => (k.startsWith("fig-") && ContentAnalyzer.getReferenceNameFromSource(componentAttributes, pageAnchorMap, catalog, v.source, k)!== "")).length - numberOfTables = [...pageAnchorMap].filter(([k,v]) => (k.startsWith("tab-")&& ContentAnalyzer.getReferenceNameFromSource(componentAttributes, pageAnchorMap, catalog, v.source, k)!== "")).length - numberOfExamples = [...pageAnchorMap].filter(([k,v]) => (k.startsWith("code-")&& ContentAnalyzer.getReferenceNameFromSource(componentAttributes, pageAnchorMap, catalog, v.source, k)!== "")).length + numberOfTables = [...pageAnchorMap].filter(([k,v]) => (k.startsWith("tab-") && ContentAnalyzer.getReferenceNameFromSource(componentAttributes, pageAnchorMap, catalog, v.source, k)!== "")).length + numberOfCodes = [...pageAnchorMap].filter(([k,v]) => (k.startsWith("code-") && ContentAnalyzer.getReferenceNameFromSource(componentAttributes, pageAnchorMap, catalog, v.source, k)!== "" && ContentAnalyzer.isListingBlock(v.source, k))).length + numberOfExamples = [...pageAnchorMap].filter(([k,v]) => (k.startsWith("code-") && ContentAnalyzer.getReferenceNameFromSource(componentAttributes, pageAnchorMap, catalog, v.source, k)!== "" && ContentAnalyzer.isExampleBlock(v.source, k))).length - return [numberOfLevelTwoSections, numberOfImages, numberOfTables, numberOfExamples] + return [numberOfLevelTwoSections, numberOfImages, numberOfTables, numberOfCodes, numberOfExamples] } module.exports = { diff --git a/antora/consistent_numbering/lib/images_tables.js b/antora/consistent_numbering/lib/images_tables.js index c73d165fd7367e5bd431ace9fe7c05015c6287c2..3f9e90af39641f8dda303e5756aa93b1e348637b 100644 --- a/antora/consistent_numbering/lib/images_tables.js +++ b/antora/consistent_numbering/lib/images_tables.js @@ -24,23 +24,25 @@ const ContentManipulator = require("../../../core/content_manipulator.js") * @param {Array <Object>} catalog - An array of pages and partials. * @param {Object} page - The current page. * @param {Object} componentAttributes - The list of inherited component attributes. - * @param {Integer} imageIndex - Optional: The image index that needs to be applied as offset. - * @param {Integer} tableIndex - Optional: The table index that needs to be applied as offset. - * @returns {Array <any>} [Updated image index, updated table index, number of level 2 sections ] + * @param {Object} indices - The current indices + * @returns {Array <any>} [Updated image index, updated table index, updated code index, updated examples index, number of level 2 sections ] */ -function updateImageAndTableIndex(catalog, page, componentAttributes, imageIndex=0, tableIndex=0, exampleIndex=0){ - let newImageIndex = imageIndex - let newTableIndex = tableIndex - let newExampleIndex = exampleIndex +function updateImageAndTableIndex(catalog, page, componentAttributes, indices){ + let newImageIndex = indices.imageIndex + let newTableIndex = indices.tableIndex + let newCodeIndex = indices.codeIndex + let newExampleIndex = indices.exampleIndex addImageOffsetAttributeToPage(page, newImageIndex) addTableOffsetAttributeToPage(page, newTableIndex) + addCodeOffsetAttributeToPage(page, newCodeIndex) addExampleOffsetAttributeToPage(page, newExampleIndex) - let [numberOfLevelTwoSections, numberOfImages, numberOfTables, numberOfExamples] = Helper.getIncludedPagesContentForExtensionFeatures(catalog, page, componentAttributes) + let [numberOfLevelTwoSections, numberOfImages, numberOfTables, numberOfCode, numberOfExamples] = Helper.getIncludedPagesContentForExtensionFeatures(catalog, page, componentAttributes) // if (page.src.stem === "entity") {console.log(numberOfImages, numberOfTables, numberOfLevelTwoSections); throw ""} newImageIndex += parseInt(numberOfImages) newTableIndex += parseInt(numberOfTables) + newCodeIndex += parseInt(numberOfCode) newExampleIndex += parseInt(numberOfExamples) - return ([newImageIndex,newTableIndex,newExampleIndex,numberOfLevelTwoSections]) + return ([newImageIndex,newTableIndex,newCodeIndex,newExampleIndex,numberOfLevelTwoSections]) } /** @@ -63,7 +65,22 @@ function addTableOffsetAttributeToPage( page, value ) { ContentManipulator.addAttributeWithValueToPage(page, newContent, indexOfTitle, "tableoffset", value) } -function addExampleOffsetAttributeToPage( page, value ) { +/** + * Adds an codeoffset attribute to a page with a given value. + * @param {Object} page - The page the value needs to be applied to. + * @param {Integer} value - The value that is to be applied as code offset. + */ +function addCodeOffsetAttributeToPage( page, value ) { + let [newContent, indexOfTitle, indexOfNavtitle, indexOfReftext] = ContentAnalyzer.getPageContentForExtensionFeatures(page) + ContentManipulator.addAttributeWithValueToPage(page, newContent, indexOfTitle, "codeoffset", value) +} + +/** + * Adds an exampleoffset attribute to a page with a given value. + * @param {Object} page - The page the value needs to be applied to. + * @param {Integer} value - The value that is to be applied as example offset. + */ + function addExampleOffsetAttributeToPage( page, value ) { let [newContent, indexOfTitle, indexOfNavtitle, indexOfReftext] = ContentAnalyzer.getPageContentForExtensionFeatures(page) ContentManipulator.addAttributeWithValueToPage(page, newContent, indexOfTitle, "exampleoffset", value) } diff --git a/antora/consistent_numbering/numbered_titles.js b/antora/consistent_numbering/numbered_titles.js index ad42cd2a0378f05beb3f9bdc72bb670a61579181..890712e39ca0b9a05578a3325119b7406b96ee0a 100644 --- a/antora/consistent_numbering/numbered_titles.js +++ b/antora/consistent_numbering/numbered_titles.js @@ -59,9 +59,7 @@ function generateConsistentNumbersBasedOnNavigation(catalog, pages, componentAtt let currentRole = "default" let generateNumbers = true let chapterIndex = Helper.setStartingChapterIndex(style,"0") - let imageIndex = 0, - tableIndex = 0, - exampleIndex = 0 + let indices = {chapterIndex: chapterIndex, imageIndex: 0, tableIndex: 0, exampleIndex: 0, codeIndex: 0} //------------- // Iterate over all (sorted) navigation files. //------------- @@ -82,7 +80,8 @@ function generateConsistentNumbersBasedOnNavigation(catalog, pages, componentAtt //--- //workaround!!! TODO: replace // - exampleIndex = 0 + indices.exampleIndex = 0 + indices.codeIndex = 0 //------------- // Check if the line contains a role or the sectnums attribute //------------- @@ -101,22 +100,22 @@ function generateConsistentNumbersBasedOnNavigation(catalog, pages, componentAtt currentRole = "default"; break; case "appendix": - [content, chapterIndex, imageIndex, tableIndex, exampleIndex, generateNumbers,currentRole] = handleAppendix(nav, catalog, pages, componentAttributes, content, line, generateNumbers, startLevel, chapterIndex, imageIndex, tableIndex, exampleIndex, style, appendixCaption, appendixOffset); + [content, generateNumbers,currentRole] = handleAppendix(nav, catalog, pages, componentAttributes, content, line, generateNumbers, startLevel, indices, style, appendixCaption, appendixOffset); break; case "glossary": currentRole = "default"; break; case "bibliography": - [currentRole, imageIndex, tableIndex, exampleIndex] = handleBibliography(nav, catalog, pages, componentAttributes, line, imageIndex, tableIndex, exampleIndex) + currentRole = handleBibliography(nav, catalog, pages, componentAttributes, line, indices) break; case "index": currentRole = "default"; break; case "preface": - [currentRole, imageIndex, tableIndex, exampleIndex] = handlePreface(nav, catalog, pages, componentAttributes, line, imageIndex, tableIndex, exampleIndex) + currentRole = handlePreface(nav, catalog, pages, componentAttributes, line, indices) break; case "default": - [content, chapterIndex, imageIndex, tableIndex, exampleIndex, generateNumbers,currentRole] = tryApplyingPageAndSectionNumberValuesToPage(nav, catalog, pages, componentAttributes, content, line, generateNumbers, startLevel, chapterIndex, imageIndex, tableIndex, exampleIndex, style) + [content, generateNumbers,currentRole] = tryApplyingPageAndSectionNumberValuesToPage(nav, catalog, pages, componentAttributes, content, line, generateNumbers, startLevel, indices, style) break; } } @@ -134,20 +133,23 @@ function generateConsistentNumbersBasedOnNavigation(catalog, pages, componentAtt * @param {Array <Object>} pages - An array of pages. * @param {Object} componentAttributes - The list of inherited component attributes. * @param {String} line - The next valid line after the role "preface" was declared. - * @param {Integer} imageIndex - The current image index used for the corresponding offset attribute. - * @param {Integer} tableIndex - The current table index used for the corresponding offset attribute. - * @returns {Array <any>} [new role, current image index, current table index] + * @param {Object} indices - The current indices. + * @returns {String} The new role "default" */ -function handlePreface( nav, catalog, pages, componentAttributes, line, imageIndex, tableIndex, exampleIndex ) { +function handlePreface( nav, catalog, pages, componentAttributes, line, indices ) { const indexOfXref = line.indexOf("xref:") let page = ContentAnalyzer.determinePageForXrefInLine(line, indexOfXref, pages, nav)[0] if (!page) { - return ["default", imageIndex, tableIndex, exampleIndex] + return "default" } Helper.unsetSectnumsAttributeInFile(page) - let [newImageIndex,newTableIndex,newExampleIndex] = ImgTab.updateImageAndTableIndex(catalog, page, componentAttributes, imageIndex, tableIndex, exampleIndex) + let [newImageIndex,newTableIndex,newCodeIndex,newExampleIndex,newLevelTwoSections] = ImgTab.updateImageAndTableIndex(catalog, page, componentAttributes, indices) + indices.imageIndex = newImageIndex + indices.tableIndex = newTableIndex + indices.codeIndex = newCodeIndex + indices.exampleIndex = newExampleIndex ContentManipulator.addSpecialSectionTypeToPage(page, "preface") - return ["default", newImageIndex, newTableIndex, newExampleIndex] + return "default" } /** @@ -160,17 +162,15 @@ function handlePreface( nav, catalog, pages, componentAttributes, line, imageInd * @param {String} line - The next valid line after the role "preface" was declared. * @param {Boolean} generateNumbers - Defines if sectnums are allowed. * @param {Integer} startLevel - The section level at which to start, depending on the level of the line in the bullet point list. - * @param {String} chapterIndex - The current chapter index. - * @param {Integer} imageIndex - The current image index used for the corresponding offset attribute. - * @param {Integer} tableIndex - The current table index used for the corresponding offset attribute. + * @param {Object} indices - The current indices (chapter, image, table, etc.). * @param {String} style - The selected style. If "iso", drop the trailing ".". * @param {String} appendixCaption - The caption for appendices. * @param {Integer} appendixOffset - An offset value for appendices, if an appendix needs to start with a different letter than "A". - * @returns {Array <any>} [new role, current image index, current table index] + * @returns {Array <any>} [new role, generateNumbers, new option] */ -function handleAppendix( nav, catalog, pages, componentAttributes, content, line, generateNumbers, startLevel, chapterIndex, imageIndex, tableIndex, exampleIndex, style, appendixCaption, appendixOffset ) { +function handleAppendix( nav, catalog, pages, componentAttributes, content, line, generateNumbers, startLevel, indices, style, appendixCaption, appendixOffset ) { const appendixStartLevel = isNaN(parseInt(startLevel)+parseInt(appendixOffset)) ? startLevel : (parseInt(startLevel)+parseInt(appendixOffset)).toString() - return tryApplyingPageAndSectionNumberValuesToPage(nav, catalog, pages, componentAttributes, content, line, generateNumbers, appendixStartLevel, chapterIndex, imageIndex, tableIndex, exampleIndex, style, "appendix", appendixCaption, true) + return tryApplyingPageAndSectionNumberValuesToPage(nav, catalog, pages, componentAttributes, content, line, generateNumbers, appendixStartLevel, indices, style, "appendix", appendixCaption, true) } /** @@ -180,21 +180,24 @@ function handleAppendix( nav, catalog, pages, componentAttributes, content, line * @param {Array <Object>} pages - An array of pages. * @param {Object} componentAttributes - The list of inherited component attributes. * @param {String} line - The next valid line after the role "preface" was declared. - * @param {Integer} imageIndex - The current image index used for the corresponding offset attribute. - * @param {Integer} tableIndex - The current table index used for the corresponding offset attribute. - * @returns {Array <any>} [new role, current image index, current table index] + * @param {Object} indices - The current indices. + * @returns {String} The new role "default" */ -function handleBibliography(nav, catalog, pages, componentAttributes, line, imageIndex, tableIndex, exampleIndex) { +function handleBibliography(nav, catalog, pages, componentAttributes, line, indices) { const indexOfXref = line.indexOf("xref:") let bibliographyPage = ContentAnalyzer.determinePageForXrefInLine(line, indexOfXref, pages, nav) let page = bibliographyPage[0] if (!page) { - return ["default", imageIndex, tableIndex] + return "default" } Helper.unsetSectnumsAttributeInFile(page) - let [newImageIndex,newTableIndex,newExampleIndex] = ImgTab.updateImageAndTableIndex(catalog, page, componentAttributes, imageIndex, tableIndex, exampleIndex) + let [newImageIndex,newTableIndex,newCodeIndex,newExampleIndex,newLevelTwoSections] = ImgTab.updateImageAndTableIndex(catalog, page, componentAttributes, indices) + indices.imageIndex = newImageIndex + indices.tableIndex = newTableIndex + indices.codeIndex = newCodeIndex + indices.exampleIndex = newExampleIndex ContentManipulator.addSpecialSectionTypeToPage(page, "bibliography") - return ["default", newImageIndex, newTableIndex, newExampleIndex] + return "default" } /** @@ -209,19 +212,19 @@ function handleBibliography(nav, catalog, pages, componentAttributes, line, imag * @param {String} line - The next valid line after the role "preface" was declared. * @param {Boolean} generateNumbers - Defines if sectnums are allowed. * @param {Integer} startLevel - The section level at which to start, depending on the level of the line in the bullet point list. - * @param {String} chapterIndex - The current chapter index. - * @param {Integer} imageIndex - The current image index used for the corresponding offset attribute. - * @param {Integer} tableIndex - The current table index used for the corresponding offset attribute. + * @param {Object} indices - The current indices. * @param {String} style - The selected style. If "iso", drop the trailing ".". * @param {String} option - Optional: If set to anything but "default", the option will be added as page role after the title (e.g. [appendix]). * @param {String} appendixCaption - Optional: The caption for appendices. Only relevant for appendix pages. * @param {Boolean} isAppendix - Optional: If true, activates the features reserved for appendices. - * @returns {Array <any>} [Changed content, new chapterIndex, new imageIndex, new tableIndex, generateNumbers = true, new option] + * @returns {Array <any>} [Changed content, generateNumbers = true, new option] */ -function tryApplyingPageAndSectionNumberValuesToPage( nav, catalog, pages, componentAttributes, content, line, generateNumbers, startLevel, chapterIndex, imageIndex, tableIndex, exampleIndex, style, option="default", appendixCaption="", isAppendix = false ) { - let newImageIndex = imageIndex - let newTableIndex = tableIndex - let newExampleIndex = exampleIndex +function tryApplyingPageAndSectionNumberValuesToPage( nav, catalog, pages, componentAttributes, content, line, generateNumbers, startLevel, indices, style, option="default", appendixCaption="", isAppendix = false ) { + let newImageIndex = indices.imageIndex + let newTableIndex = indices.tableIndex + let newCodeIndex = indices.codeIndex + let newExampleIndex = indices.exampleIndex + let chapterIndex = indices.chapterIndex let numberOfLevelTwoSections = 0 const indexOfXref = line.indexOf("xref:") //------------- @@ -236,13 +239,13 @@ function tryApplyingPageAndSectionNumberValuesToPage( nav, catalog, pages, compo //------------- if (indexOfXref <= 0) { if (!generateNumbers) { - return [content, chapterIndex, newImageIndex, newTableIndex, newExampleIndex, !generateNumbers,"default"] + + return [content, !generateNumbers,"default"] } chapterIndex = Helper.determineNextChapterIndex(targetLevel, chapterIndex, style) const changedLine = line.slice(0,level) + " " + chapterIndex + line.slice(level) content[content.indexOf(line)] = changedLine chapterIndex = style === "iso" ? chapterIndex +"."+ 0 : chapterIndex + 0 +"." - } //------------- // Execute if xref was found (i.e. the line contains a link to a file). @@ -257,19 +260,25 @@ function tryApplyingPageAndSectionNumberValuesToPage( nav, catalog, pages, compo let page = foundPage[0] if (!generateNumbers) { Helper.unsetSectnumsAttributeInFile(page) - let [a,b,c,d] = ImgTab.updateImageAndTableIndex(catalog, page, componentAttributes, imageIndex, tableIndex, exampleIndex) - return [content, chapterIndex, a, b, c, !generateNumbers, "default"] + let [updateImageIndex,updateTableIndex,updateCodeIndex,updateExampleIndex,newLevelTwoSections] = ImgTab.updateImageAndTableIndex(catalog, page, componentAttributes, indices) + indices.chapterIndex = chapterIndex + indices.imageIndex = updateImageIndex + indices.tableIndex = updateTableIndex + indices.codeIndex = updateCodeIndex + indices.exampleIndex = updateExampleIndex + return [content, !generateNumbers, "default"] } //------------- // If section number shall be applied, apply current values and determine the next ones. //------------- chapterIndex = Helper.determineNextChapterIndex(targetLevel, chapterIndex, style, appendixCaption, isAppendix) Helper.addTitleoffsetAttributeToPage( page, chapterIndex) - let [a,b,c,d] = ImgTab.updateImageAndTableIndex(catalog, page, componentAttributes, imageIndex, tableIndex, exampleIndex) - newImageIndex = a - newTableIndex = b - newExampleIndex = c - numberOfLevelTwoSections = d + let [updateImageIndex,updateTableIndex,updateCodeIndex,updateExampleIndex,newLevelTwoSections] = ImgTab.updateImageAndTableIndex(catalog, page, componentAttributes, indices) + newImageIndex = updateImageIndex + newTableIndex = updateTableIndex + newCodeIndex = updateCodeIndex + newExampleIndex = updateExampleIndex + numberOfLevelTwoSections = newLevelTwoSections let [newContent, indexOfTitle, indexOfNavtitle, indexOfReftext] = ContentAnalyzer.getPageContentForExtensionFeatures(page) const targetIndex = style === "iso" ? chapterIndex.split(".") : chapterIndex.split(".").slice(0,-1) if (isAppendix && targetLevel === 1) { @@ -302,7 +311,12 @@ function tryApplyingPageAndSectionNumberValuesToPage( nav, catalog, pages, compo } } } - return [content, chapterIndex, newImageIndex, newTableIndex, newExampleIndex, generateNumbers, option] + indices.chapterIndex = chapterIndex + indices.imageIndex = newImageIndex + indices.tableIndex = newTableIndex + indices.codeIndex = newCodeIndex + indices.exampleIndex = newExampleIndex + return [content, generateNumbers, option] } module.exports = { diff --git a/antora/crossref_replacement/crossref_replacement.js b/antora/crossref_replacement/crossref_replacement.js index e488b9ac13bb896dd3633c2892a0dc1313798937..c4f131958f2e786965103838e865b91f98fbcd01 100644 --- a/antora/crossref_replacement/crossref_replacement.js +++ b/antora/crossref_replacement/crossref_replacement.js @@ -33,7 +33,8 @@ function findAndReplaceLocalReferencesToGlobalAnchors( componentAttributes, anch } references.forEach(ref => { if (anchorMap.get(ref[1])) { - const referencePage = [...anchorMap.get(ref[1])][0] + const val = anchorMap.get(ref[1]) + const referencePage = [...val][0] if (page !== referencePage) { let autoAltText = ContentAnalyzer.getReferenceNameFromSource( componentAttributes, anchorMap, pages, referencePage, ref[1] ) const altText = ref[3] ? ref[3] : autoAltText diff --git a/antora/loft/loft.js b/antora/loft/loft.js index 716cf511d1490e9cea78b477694a21b9ffb4e353..5231b5c4f0deb5c89d9ccaca7af60817af67889c 100644 --- a/antora/loft/loft.js +++ b/antora/loft/loft.js @@ -40,20 +40,31 @@ function createLoft(componentAttributes, contentCatalog, anchorPageMap, navFiles const tableMap = new Map([...anchorPageMap].filter(([k,v]) => k.startsWith("tab-"))) const tableArray = createSortedArrayFromMap(tableMap, mergedNavContents) // let figuresPage = createListOfFiguresPage(componentAttributes, contentCatalog, catalog, figureMap, targetModule, component, version) - let figuresPage = createListOfFiguresPage(componentAttributes, contentCatalog, catalog, figureMap, figureArray, targetModule, component, version) + // let tablesPage = createListOfTablesPage(componentAttributes, contentCatalog, catalog, tableMap, targetModule, component, version) - let tablesPage = createListOfTablesPage(componentAttributes, contentCatalog, catalog, tableMap, tableArray, targetModule, component, version) - if (figuresPage) { - navFiles.at(-1).contents = Buffer.from(navFiles.at(-1).contents.toString().concat("\n",`* xref:${figuresPage.src.relative}[]\n`)) + if (figureArray && figureArray.length > 0){ + let figuresPage = createListOfFiguresPage(componentAttributes, contentCatalog, catalog, figureMap, figureArray, targetModule, component, version) + if (figuresPage) { + navFiles.at(-1).contents = Buffer.from(navFiles.at(-1).contents.toString().concat("\n",`* xref:${figuresPage.src.relative}[]\n`)) + } } - if (tablesPage) { - navFiles.at(-1).contents = Buffer.from(navFiles.at(-1).contents.toString().concat("\n",`* xref:${tablesPage.src.relative}[]\n`)) + if (tableArray && tableArray.length > 0){ + let tablesPage = createListOfTablesPage(componentAttributes, contentCatalog, catalog, tableMap, tableArray, targetModule, component, version) + if (tablesPage) { + navFiles.at(-1).contents = Buffer.from(navFiles.at(-1).contents.toString().concat("\n",`* xref:${tablesPage.src.relative}[]\n`)) + } } } +/** + * Analyzes an anchor map and converts it to a sorted array, where each anchor-page combination has its own entry. + * @param {Map <String, Object>} inputMap - The map that is to be converted. + * @param {String} mergedNavContents - The merged contents of all relevant navigation files. + * @returns {Array <Object>} {anchor, page, source, line} + */ function createSortedArrayFromMap(inputMap, mergedNavContents) { let newArray = [] for (let entry of inputMap.keys()) { @@ -71,6 +82,7 @@ function createSortedArrayFromMap(inputMap, mergedNavContents) { } } + newArray.sort((a,b) => { let indexA = mergedNavContents.indexOf(a.page.src.relative) let indexB = mergedNavContents.indexOf(b.page.src.relative) @@ -92,6 +104,7 @@ function createSortedArrayFromMap(inputMap, mergedNavContents) { * @param {Object} contentCatalog - The content catalog as provided by Antora. * @param {Array <Object>} catalog - An array of all pages and partials of this component-version combination. * @param {Map <String, Object>} figureMap - A map containing all figure anchors. + * @param {Array <Object>} figureArray - A sorted array created from the figureMap. * @param {String} targetModule - The determined target module for the new/updated file. * @param {String} component - The current component. * @param {String} version - The current version. @@ -136,6 +149,7 @@ function createSortedArrayFromMap(inputMap, mergedNavContents) { * @param {Object} contentCatalog - The content catalog as provided by Antora. * @param {Array <Object>} catalog - An array of all pages and partials of this component-version combination. * @param {Map <String, Object>} tableMap - A map containing all table anchors. + * @param {Array <Object>} tableArray - A sorted array created from the tableMap. * @param {String} targetModule - The determined target module for the new/updated file. * @param {String} component - The current component. * @param {String} version - The current version. diff --git a/asciidoctor/consistent_numbering/sectnumsoffset_antora.js b/asciidoctor/consistent_numbering/sectnumsoffset_antora.js index 8050ad6ccb28d8d2a6dcec8c16df30104e5becff..8e31fd9c36d27744cd903e5519cb12ff9aaa22fc 100644 --- a/asciidoctor/consistent_numbering/sectnumsoffset_antora.js +++ b/asciidoctor/consistent_numbering/sectnumsoffset_antora.js @@ -3,25 +3,28 @@ module.exports = function (registry) { const self = this let verbose = false self.process(function (doc) { - // if (doc.getTitle() && doc.getTitle().includes("Scenario abstraction")){verbose = true} + // if (doc.getTitle() && doc.getTitle().includes("Movement modifiers")){verbose = true} // Check if sectnums and sectnumoffset is found. Only act if true if (verbose){console.log("Title: ",doc.getTitle())} if (verbose){console.log("has imageoffset attribute: ",doc.hasAttribute("imageoffset"))} if (verbose){console.log("has tableoffset attribute: ",doc.hasAttribute("tableoffset"))} + if (verbose){console.log("has codeoffset attribute: ",doc.hasAttribute("codeoffset"))} if (verbose){console.log("has exampleoffset attribute: ",doc.hasAttribute("exampleoffset"))} - if (doc.hasAttribute("sectnums") && (doc.hasAttribute("sectnumoffset") || doc.hasAttribute("titleoffset") || doc.hasAttribute("imageoffset") || doc.hasAttribute("tableoffset") || doc.hasAttribute("exampleoffset"))) { + if (doc.hasAttribute("sectnums") && (doc.hasAttribute("sectnumoffset") || doc.hasAttribute("titleoffset") || doc.hasAttribute("imageoffset") || doc.hasAttribute("tableoffset") || doc.hasAttribute("codeoffset") || doc.hasAttribute("exampleoffset"))) { let offsetValue = Math.abs(doc.getAttribute("sectnumoffset",0)) let pageTitle = doc.getTitle() let titleOffset = doc.getAttribute("titleoffset",null) let titlePrefix = doc.getAttribute("titleprefix","") let imageOffset = Math.abs(doc.getAttribute("imageoffset",0)) let tableOffset = Math.abs(doc.getAttribute("tableoffset",0)) + let codeOffset = Math.abs(doc.getAttribute("codeoffset",0)) let exampleOffset = Math.abs(doc.getAttribute("exampleoffset",0)) if (verbose){console.log("titleoffset attribute: ",titleOffset)} if (verbose){console.log("titleprefix attribute: ",titlePrefix)} if (verbose){console.log("imageOffset attribute: ",imageOffset)} if (verbose){console.log("tableoffset attribute: ",tableOffset)} + if (verbose){console.log("codeoffset attribute: ",codeOffset)} if (verbose){console.log("exampleoffset attribute: ",exampleOffset)} // if (verbose){console.log("attributes: ", doc.getAttributes())} @@ -40,6 +43,7 @@ module.exports = function (registry) { } imageOffset = updateImageOffset(doc, imageOffset, verbose) tableOffset = updateTableOffset(doc, tableOffset, verbose) + codeOffset = updateCodeOffset(doc, codeOffset, verbose) exampleOffset = updateExampleOffset(doc, exampleOffset, verbose) } }) @@ -57,6 +61,7 @@ module.exports = function (registry) { function applyOffset (doc, offset, node_name, verbose = false) { let newOffset = offset // if (verbose && doc.node_name && doc.node_name === "table"){console.log("doc.node_name: ",doc.node_name); console.log("doc.getNodeName()", doc.getNodeName()); console.log("Array.isArray(doc)",Array.isArray(doc)); throw ""} + // if(verbose && node_name === "listing"){console.log(doc.getNodeName())} if (doc.getNodeName && doc.getNodeName() === node_name ) { if (verbose) {console.log("found",node_name)} newOffset = 1 + newOffset @@ -128,7 +133,25 @@ module.exports = function (registry) { return (applyOffset(doc, tableOffset,"table", verbose)) } - function updateExampleOffset( doc, exampleOffset, verbose=false) { + /** + * Updates and applies the code offset to each code block. + * @param {*} doc - The document. + * @param {Number} codeOffset - The code offset value. + * @param {Boolean} verbose - Optional: If true, will print verbose output in the console. + * @returns {Number} The updated tableOffset. + */ + function updateCodeOffset( doc, codeOffset, verbose=false) { + return (applyOffset(doc, codeOffset, "listing", verbose)) + } + + /** + * Updates and applies the example offset to each example block. + * @param {*} doc - The document. + * @param {Number} exampleOffset - The example offset value. + * @param {Boolean} verbose - Optional: If true, will print verbose output in the console. + * @returns {Number} The updated tableOffset. + */ + function updateExampleOffset( doc, exampleOffset, verbose=false) { return (applyOffset(doc, exampleOffset, "example", verbose)) } } diff --git a/core/content_analyzer.js b/core/content_analyzer.js index 3e393a02b7017f53698f141ca59a62cdb21f92f3..49c8a5d730116a074d077e41bbaa80788b827a3b 100644 --- a/core/content_analyzer.js +++ b/core/content_analyzer.js @@ -10,6 +10,8 @@ //------------- var nonStandardAnchors = [] +var anchorWarnings = [] +var count = 0 /** * Analyze a path of an include macro and identifies the linked file, if it exists. @@ -374,6 +376,8 @@ function getReferenceNameFromSource(componentAttributes, anchorPageMap, pages, p const regexAltAnchor = regexAnchor.slice(4) const reAnchor = new RegExp(`\\[\\[{1,2}${regexAnchor}(,([^\\]]*))?\\]\\]|\\[\#${regexAnchor}(,([^\\]]*))?\\]|anchor:${regexAnchor}(,([^\\]]*))?`, 'm') const reAltAnchor = new RegExp(`\\[\\[${regexAltAnchor}(,([^\\]]*))?\\]\\]|\\[\#${regexAltAnchor}(,([^\\]]*))?\\]|anchor:${regexAltAnchor}(,([^\\]]*))?`, 'm') + const reExampleBlock = /^(\[source([^\]]+)?\]\s*\n)?={4}$/m + const reSourceBlock = /^\[source([^\]]+)?\]\s*\n-{4}\s*$/m let inheritedAttributes = {} let content = page.contents.toString() const contentSplit = content.split("\n") @@ -402,6 +406,7 @@ function getReferenceNameFromSource(componentAttributes, anchorPageMap, pages, p const resultForNextHeading = content.slice(indexOfAnchor).match(reSectionEqualSigns) // const resultForPreviousHeading = content.slice(0,indexOfAnchor).match(reSectionEqualSigns) const resultNextCaption = content.slice(indexOfAnchor).match(reCaptionLabel) + const countLineBreaksHeading = resultForNextHeading ? content.slice(indexOfAnchor,indexOfAnchor+resultForNextHeading.index).split("\n").length : 0 const countLineBreaks = resultNextCaption ? content.slice(indexOfAnchor,indexOfAnchor+resultNextCaption.index).split("\n").length : 0 const lineBreakLimitBreached = countLineBreaks > 4 ? true : false // Use special anchor formats: sec, top, fig, tab, ... @@ -414,12 +419,63 @@ function getReferenceNameFromSource(componentAttributes, anchorPageMap, pages, p const appendixRefsig = componentAttributes['appendix-caption'] ? componentAttributes['appendix-caption'] : "Appendix" const figureCaption = inheritedAttributes['figure-caption'] ? inheritedAttributes['figure-caption'] : componentAttributes['figure-caption'] ? componentAttributes['figure-caption'] : "Figure" const tableCaption = inheritedAttributes['table-caption'] ? inheritedAttributes['table-caption'] : componentAttributes['table-caption'] ? componentAttributes['table-caption'] : "Table" - const codeCaption = inheritedAttributes['example-caption'] ? inheritedAttributes['example-caption'] : componentAttributes['example-caption'] ? componentAttributes['example-caption'] : "Example" + const exampleCaption = inheritedAttributes['example-caption'] ? inheritedAttributes['example-caption'] : componentAttributes['example-caption'] ? componentAttributes['example-caption'] : "Example" + const codeCaption = inheritedAttributes['listing-caption'] ? inheritedAttributes['listing-caption'] : componentAttributes['listing-caption'] ? componentAttributes['listing-caption'] : "" // let verbose = (anchor==="sec-lc-aggregate-types" && style === "full") //------------- // Only act on anchors that match one of the ASAM anchor types (matching reAnchorType). //------------- if (resultAnchorType) { + let anchorWarningEntry = {anchor:anchor,page:page, type:null} + switch (resultAnchorType[1]) { + case "fig": + break; + case "tab": + break; + case "code": + if (countLineBreaks > 2) { + anchorWarningEntry.type = "title"; + if(!anchorWarnings.find(x => (x.anchor === anchorWarningEntry.anchor && x.page === anchorWarningEntry.page && x.type === anchorWarningEntry.type))){console.warn(`ASAM rule violation: No title found in next line after ${anchor}!\nFile: ${page.src.abspath}`);anchorWarnings.push(anchorWarningEntry);} + break; + } + else { + let matchExample = content.slice(indexOfAnchor).match(reExampleBlock); + let matchSource = content.slice(indexOfAnchor).match(reSourceBlock); + if (!(matchExample && content.slice(indexOfAnchor,indexOfAnchor+matchExample.index).split("\n").length === 3) && !(matchSource && content.slice(indexOfAnchor,indexOfAnchor+matchSource.index).split("\n").length === 3) ){ + anchorWarningEntry.type = "block"; + if(!anchorWarnings.find(x => (x.anchor === anchorWarningEntry.anchor && x.page === anchorWarningEntry.page && x.type === anchorWarningEntry.type))){console.warn(`ASAM rule violation: Code anchor ${anchor} not immediately followed by block after title!\nFile: ${page.src.abspath}`);anchorWarnings.push(anchorWarningEntry);} + } + if (matchExample && content.slice(indexOfAnchor,indexOfAnchor+matchExample.index).split("\n").length === 3 ) { + anchorWarningEntry.type = "exAsCode"; + if(!anchorWarnings.find(x => (x.anchor === anchorWarningEntry.anchor && x.page === anchorWarningEntry.page && x.type === anchorWarningEntry.type))){console.warn(`INFO: Code anchor ${anchor} used with example block!\nFile: ${page.src.abspath}`);anchorWarnings.push(anchorWarningEntry);} + } + break; + } + case "top": + if (countLineBreaksHeading > 2) { + anchorWarningEntry.type = "title"; + if(!anchorWarnings.find(x => (x.anchor === anchorWarningEntry.anchor && x.page === anchorWarningEntry.page && x.type === anchorWarningEntry.type))){console.warn(`ASAM rule violation: Anchor ${anchor} not immediately followed by title!\nFile: ${page.src.abspath}`);anchorWarnings.push(anchorWarningEntry);} + } + else if (page.src.family === "partial") { + anchorWarningEntry.type = "partialTitle"; + if(!anchorWarnings.find(x => (x.anchor === anchorWarningEntry.anchor && x.page === anchorWarningEntry.page && x.type === anchorWarningEntry.type))){console.warn(`ASAM rule violation: Top anchor ${anchor} used in partil!\nFile: ${page.src.abspath}`);anchorWarnings.push(anchorWarningEntry);} + } + else if (!resultForNextHeading || resultForNextHeading[1].length !== 1) { + anchorWarningEntry.type = "section"; + if(!anchorWarnings.find(x => (x.anchor === anchorWarningEntry.anchor && x.page === anchorWarningEntry.page && x.type === anchorWarningEntry.type))){console.warn(`ASAM rule violation: Anchor ${anchor} used for section, not title!\nFile: ${page.src.abspath}`);anchorWarnings.push(anchorWarningEntry);} + } + break; + case "sec": + if (countLineBreaksHeading > 2) { + anchorWarningEntry.type = "title"; + if(!anchorWarnings.find(x => (x.anchor === anchorWarningEntry.anchor && x.page === anchorWarningEntry.page && x.type === anchorWarningEntry.type))){console.warn(`ASAM rule violation: Anchor ${anchor} not immediately followed by title!\nFile: ${page.src.abspath}`);anchorWarnings.push(anchorWarningEntry);} + } + else if (page.src.family === "page" && (!resultForNextHeading || resultForNextHeading[1].length === 1)) { + anchorWarningEntry.type = "section"; + if(!anchorWarnings.find(x => (x.anchor === anchorWarningEntry.anchor && x.page === anchorWarningEntry.page && x.type === anchorWarningEntry.type))){console.warn(`ASAM rule violation: Anchor ${anchor} used for title, not section!\nFile: ${page.src.abspath}`);anchorWarnings.push(anchorWarningEntry);} + } + break; + } switch (resultAnchorType[1]) { case "fig": result = lineBreakLimitBreached ? null : resultNextCaption; @@ -447,7 +503,7 @@ function getReferenceNameFromSource(componentAttributes, anchorPageMap, pages, p let codeIndex = Array.from(codeMap.keys()).indexOf(anchor) if (result) { title = result[1]; - prefix = codeCaption + ' ' + codeIndex; + prefix = codeCaption.length > 0 ? codeCaption + ' ' + codeIndex : null; returnValue = title; } break; @@ -671,7 +727,7 @@ function getKeywordPageMapForPages(useKeywords, pages = []) { * @param {Array <Object>} pages - An array of relevant pages * @returns {Map <String, Object>} A map of 'roles' and the pages where they were found in. */ -function getRolePageMapForPages(pages = []) { +function getRolePageMapForPages(pages) { var re = new RegExp("{role-([^}]*)}") var rolesMap = generateMapForRegEx(re, pages) return rolesMap @@ -916,6 +972,46 @@ function getSrcPathFromFileId(fileId) { return { version: version, component: component, module: antoraModule, type: type, relative: relative } } +/** + * Determines for an anchor found in a given file whether it is related to a listing block. + * @param {Object} file - The file where the anchor is located in. + * @param {String} anchor - The anchor in question + * @returns {Boolean} Whether the anchor is a listing block. + */ +function isListingBlock(file, anchor) { + const reSourceBlock = /^\[source([^\]]+)?\]\s*\n-{4}\s*$/m + const regexAnchor = anchor.replaceAll("-","\\-").replaceAll(".","\\.").replaceAll("(","\\(").replaceAll(")","\\)") + const reAnchor = new RegExp(`\\[\\[{1,2}${regexAnchor}(,([^\\]]*))?\\]\\]|\\[\#${regexAnchor}(,([^\\]]*))?\\]|anchor:${regexAnchor}(,([^\\]]*))?`, 'm') + const content = file.contents.toString() + const start = content.match(reAnchor) ? content.match(reAnchor).index : null + if (!start) {return false} + const match = content.slice(start).match(reSourceBlock) + if (!match) {return false} + const end = match.index + // console.log("is listing: ",content.slice(start,start+end).split("\n").length === 3); console.log(content.slice(start,start+end).split("\n"), content.slice(start,start+end).split("\n").length) + return (content.slice(start,start+end).split("\n").length === 3) +} + +/** + * Determines for an anchor found in a given file whether it is related to an example block. + * @param {Object} file - The file where the anchor is located in. + * @param {String} anchor - The anchor in question + * @returns {Boolean} Whether the anchor is an example block. + */ +function isExampleBlock(file, anchor) { + const reExampleBlock = /^(\[source([^\]]+)?\]\s*\n)?={4}$/m + const regexAnchor = anchor.replaceAll("-","\\-").replaceAll(".","\\.").replaceAll("(","\\(").replaceAll(")","\\)") + const reAnchor = new RegExp(`\\[\\[{1,2}${regexAnchor}(,([^\\]]*))?\\]\\]|\\[\#${regexAnchor}(,([^\\]]*))?\\]|anchor:${regexAnchor}(,([^\\]]*))?`, 'm') + const content = file.contents.toString() + const start = content.match(reAnchor) ? content.match(reAnchor).index : null + if (!start) {return false} + const match = content.slice(start).match(reExampleBlock) + if (!match) {return false} + const end = match.index + // console.log("is example: ",content.slice(start,start+end).split("\n").length === 3); console.log(content.slice(start,start+end).split("\n"), content.slice(start,start+end).split("\n").length) + return (content.slice(start,start+end).split("\n").length === 3) +} + module.exports = { determineTargetPageFromIncludeMacro, getAllKeywordsAsArray, @@ -933,5 +1029,7 @@ module.exports = { checkForIncludedFileFromLine, getAttributeFromFile, getSrcPathFromFileId, - getAttributeFromContent + getAttributeFromContent, + isExampleBlock, + isListingBlock } \ No newline at end of file