diff --git a/interface/src/scripting/SelectionScriptingInterface.h b/interface/src/scripting/SelectionScriptingInterface.h index 8b5c12e3dc..83aec63ee2 100644 --- a/interface/src/scripting/SelectionScriptingInterface.h +++ b/interface/src/scripting/SelectionScriptingInterface.h @@ -182,7 +182,7 @@ public: /**jsdoc * Get the list of avatars, entities, and overlays stored in a selection list. - * @function Selection.getList + * @function Selection.getSelectedItemsList * @param {string} listName - The name of the selection list. * @returns {Selection.SelectedItemsList} The content of a selection list. If the list name doesn't exist, the function * returns an empty object with no properties. @@ -257,7 +257,7 @@ public: void onSelectedItemsListChanged(const QString& listName); signals: - /**jsoc + /**jsdoc * Triggered when a list's content changes. * @function Selection.selectedItemsListChanged * @param {string} listName - The name of the selection list that changed. diff --git a/tools/jsdoc/.gitignore b/tools/jsdoc/.gitignore index c585e19389..148363ca03 100644 --- a/tools/jsdoc/.gitignore +++ b/tools/jsdoc/.gitignore @@ -1 +1,2 @@ -out \ No newline at end of file +out + diff --git a/tools/jsdoc/CMakeLists.txt b/tools/jsdoc/CMakeLists.txt index 4a6c18f243..1c4333983f 100644 --- a/tools/jsdoc/CMakeLists.txt +++ b/tools/jsdoc/CMakeLists.txt @@ -8,7 +8,7 @@ set(JSDOC_WORKING_DIR ${CMAKE_SOURCE_DIR}/tools/jsdoc) file(TO_NATIVE_PATH ${JSDOC_WORKING_DIR}/node_modules/.bin/jsdoc JSDOC_PATH) file(TO_NATIVE_PATH ${JSDOC_WORKING_DIR}/config.json JSDOC_CONFIG_PATH) file(TO_NATIVE_PATH ${JSDOC_WORKING_DIR}/out OUTPUT_DIR) -file(TO_NATIVE_PATH ${JSDOC_WORKING_DIR} NATIVE_JSDOC_WORKING_DIR) +file(TO_NATIVE_PATH ${JSDOC_WORKING_DIR}/root.js NATIVE_JSDOC_WORKING_DIR) add_custom_command(TARGET ${TARGET_NAME} COMMAND ${NPM_EXECUTABLE} --no-progress install && ${JSDOC_PATH} ${NATIVE_JSDOC_WORKING_DIR} -c ${JSDOC_CONFIG_PATH} -d ${OUTPUT_DIR} diff --git a/tools/jsdoc/README.md b/tools/jsdoc/README.md index 5cce6bb2a6..5cdb1ea44e 100644 --- a/tools/jsdoc/README.md +++ b/tools/jsdoc/README.md @@ -2,12 +2,27 @@ ##Prerequisites -* Install node.js +* Install node.js. * Install jsdoc via npm. `npm install jsdoc -g` +If you would like the extra functionality for gravPrep: +* Run npm install + To generate html documentation for the High Fidelity JavaScript API: * `cd tools/jsdoc` * `jsdoc . -c config.json` The out folder should contain index.html. + +To generate the grav automation files, run node gravPrep.js after you have made a JSdoc output folder. + +This will create files that are needed for hifi-grav and hifi-grav-content repos + +The md files for hifi-grav-content are located in out/grav/06.api-reference. + +The template twig html files for hifi-grav are located out/grav/templates. + +if you would like to copy these to a local version of the docs on your system you can run with the follows args: + +* node grav true "path/to/grav/" "path/to/grav/content" \ No newline at end of file diff --git a/tools/jsdoc/gravPrep.js b/tools/jsdoc/gravPrep.js new file mode 100644 index 0000000000..849837bae0 --- /dev/null +++ b/tools/jsdoc/gravPrep.js @@ -0,0 +1,671 @@ +// Dependencies +const htmlclean = require('htmlclean'); +const fs = require('fs'); +const path = require('path'); +const pretty = require('pretty'); +const cheerio = require('cheerio'); +const rimraf = require('rimraf'); +const dedent = require('dedent-js'); + +// Arg Vars +const copyLocal = process.argv[2]; +console.log("copyLocal:", copyLocal); +let targetTemplateDirectory = ''; +let targetMDDirectory = ''; +if (copyLocal) { + targetTemplateDirectory = process.argv[3]; + targetMDDirectory = process.argv[4];; +} + +// Required directories +let dir_out = path.join(__dirname, 'out'); + +let dir_grav = path.join(dir_out, 'grav'); +let dir_css = path.join(dir_grav, 'css'); +let dir_js = path.join(dir_grav, 'js'); +let dir_template = path.join(dir_grav, 'templates'); + +let dir_md = path.join(dir_grav, '06.api-reference'); +let dir_md_objects = path.join(dir_md, '02.Objects'); +let dir_md_namespaces = path.join(dir_md, '01.Namespaces'); +let dir_md_globals = path.join(dir_md, '03.Globals'); + +// Array to itterate over and create if doesn't exist +let dirArray = [dir_grav, dir_css, dir_js, dir_template, dir_md, dir_md_objects, dir_md_namespaces, dir_md_globals]; + +// Base Grouping Directories for MD files +let baseMDDirectories = ["API-Reference", "Globals", "Namespaces", "Objects"]; + +// Maps for directory names +let map_dir_md = { + "API-Reference": dir_md, + "Globals": dir_md_globals, + "Objects": dir_md_objects, + "Namespaces": dir_md_namespaces, + "Class": dir_md_objects, + "Namespace": dir_md_namespaces, + "Global": dir_md_globals +} + +// Map for Links +let map_links = { + "Global": "globals", + "Namespace": "namespaces", + "Class": "objects" +} + +// Mapping for GroupNames and Members +let groupNameMemberMap = { + "Objects": [], + "Namespaces": [], + "Globals": [] +} + +// Html variables to be handle regex replacements +const html_reg_static = /\(static\)<\/span>/g +const html_reg_title = /\.+?\<\/h1\>/g; +const html_reg_htmlExt = /\.html/g; +const html_reg_objectHeader = /
[\s\S]+?<\/header>/; +const html_reg_objectSpanNew = /
<\/h5>/; +const html_reg_propertiesHeaderEdit = '

Properties:

'; +const html_reg_propertiesHeaderEdit_Replace = '

Properties

'; +const html_reg_typeEdit = /(
Returns[\s\S]*?Type)(<\/dt[\s\S]*?type">)(.*?)(<\/span><\/dd>[\s\S]*?<\/dl>)/g; +const html_reg_typeEdit_replace = '$1: $3' +const html_reg_methodSize = /()/g; +const html_reg_methodSize_replace = ''; +const html_reg_findByName = '
` +const html_reg_signalTitle = `

Signals

`; +const html_reg_typeDefinitonsTitle = /

Type Definitions<\/h3>/; +const html_reg_typeDefinitonsTitle_replace = `

Type Definitions

` +const html_reg_classDefinitonsTitle = /

Classes<\/h3>/; +const html_reg_classDefinitonsTitle_replace = `

Classes

` +const html_reg_firstDivClose = ``; +const html_reg_allNonHTTPLinks = /()/g; +const html_reg_allHTTPLinks = /()/g; +const html_reg_pretty = /(
)([\s\S]*?)(<\/pre>)/g;
+const html_reg_pretty_replace = "
$2<\/pre>";
+const html_reg_availableIn = /([\s\S]+?Available in:[\s\S]+?<\/table>)/g;
+const html_reg_findControllerCuratedList = /
Functions<\/h5>[\s\S]*?

Input Recordings[\s\S]*?<\/ul>/g +const html_reg_findEntityMethods = /

Entity Methods:[\s\S]+?<\/ul>/g; +const html_reg_EntityMethodsHeader = '
Entity Methods:
'; +const html_reg_EntityMethodsHeader_replace = '
Entity Methods
'; +const html_reg_dlClassDetails = /
<\/dl>/g +const html_reg_typeDefType = /(
)(Type:)(<\/h5>[\s\S]*?)([\s\S]*?<\/ul>)/g; +const html_reg_typeDefType_replace = `
$2 $4
`; +const html_reg_returnSize = /
Returns:<\/h5>/g; +const html_reg_returnSize_replace = '
Returns:<\/h6>'; +const html_reg_depreciated = /(
[\s\S]+?)(
)([\s\S]+?)([\s\S]+?)(<\/ul>[\s\S]+?)(<\/dd>)/g; +const html_reg_depreciated_replace = '$1
$4
' + +// Procedural functions + +//remove .html from non http links +function removeHTML(match, p1, p2, p3) { + p2 = p2.replace(".html", ""); + return [p1, p2, p3].join(""); +} + +// Turn links to lower case that aren't part of IDs +function allLinksToLowerCase(match, p1, p2, p3) { + // split on id # and make sure only the preceding is lower case + if (p2.indexOf("#") > -1) { + p2 = p2.split("#"); + p2 = [p2[0].toLowerCase(), "#", p2[1]].join(""); + } else { + p2 = p2.toLowerCase(); + } + return [p1, p2, p3].join(""); +} + +// Helper for fixing formatting of page links +function fixLinkGrouping(match, p1, p2, p3) { + // Handle if referencing ID + let count = (p2.match(/\./g) || []).length; + if (p2.indexOf("#") > -1) { + let split = p2.split("#"); + if (count >= 2) { + // console.log("MULTI DOTS!"); + split = p2.split("."); + // This is a case where we are in an object page and there are multiple levels referenced (only doing 2 levels at the moment) + // console.log("split", split) + return [p1, "/api-reference/", returnRightGroup(split[1].slice(0, -1)), "/", split[1], ".", split[2], p3].join(""); + } + if (split[0] === "global") { + return [p1, "/api-reference/", "globals", "#", split[1], p3].join(""); + } + return [p1, "/api-reference/", returnRightGroup(split[0]), "/", p2, p3].join(""); + } else { + // Handle if there are member references + // console.log("count", count) + let split; + if (count === 1) { + split = p2.split("."); + return [p1, "/api-reference/", returnRightGroup(split[1]), "/", split[1], p3].join(""); + } + return [p1, "/api-reference/", returnRightGroup(p2), "/", p2, p3].join(""); + } +} + +// Return the right group for where the method or type came from +function returnRightGroup(methodToCheck) { + for (var key in groupNameMemberMap) { + for (i = 0; i < groupNameMemberMap[key].length; i++) { + if (methodToCheck.toLowerCase() === groupNameMemberMap[key][i].toLowerCase()) { + return key.toLowerCase(); + } else { + // console.log("Couldn't find group: ", methodToCheck); + } + } + } +} + +// Create the actual MD file +function createMD(title, directory, needsDir, isGlobal) { + let mdSource = makeMdSource(title); + + if (needsDir) { + if (!fs.existsSync(directory)) { + fs.mkdirSync(directory); + } + } + + let destinationMDFile = path.join(directory, `API_${title}.md`); + fs.writeFileSync(destinationMDFile, mdSource); +} + +// Create the actual Template file +function createTemplate(title, content) { + let twigBasePartial = makeTwigFile(content); + let destinationFile = path.join(dir_template, `API_${title}.html.twig`); + fs.writeFileSync(destinationFile, twigBasePartial); +} + +// Copy file from source to target - used for recurssive call +function copyFileSync(source, target) { + let targetFile = target; + + // If target is a directory a new file with the same name will be created + if (fs.existsSync(target)) { + if (fs.lstatSync(target).isDirectory()) { + targetFile = path.join(target, path.basename(source)); + } + } + + fs.writeFileSync(targetFile, fs.readFileSync(source)); +} + +// Copy file from source to target +function copyFolderRecursiveSync(source, target) { + var files = []; + + // Check if folder needs to be created or integrated + var targetFolder = path.join(target, path.basename(source)); + if (!fs.existsSync(targetFolder)) { + fs.mkdirSync(targetFolder); + } + + // Copy + if (fs.lstatSync(source).isDirectory()) { + files = fs.readdirSync(source); + files.forEach(function(file) { + var curSource = path.join(source, file); + if (fs.lstatSync(curSource).isDirectory()) { + copyFolderRecursiveSync(curSource, targetFolder); + } else { + copyFileSync(curSource, targetFolder); + } + }); + } +} + +// Clean up the Html +function prepareHtml(source) { + let htmlBefore = fs.readFileSync(source, { encoding: 'utf8' }); + let htmlAfter = htmlclean(htmlBefore); + let htmlAfterPretty = pretty(htmlAfter); + return cheerio.load(htmlAfterPretty); +} + +// Base file for MD's +function makeMdSource(title) { + return dedent( + ` + --- + title: ${title} + taxonomy: + category: + - docs + visible: true + highlight: + enabled: false + --- + ` + ) +} + +// Base file for Templates +function makeTwigFile(contentHtml) { + return dedent( + ` + {% extends 'partials/base_noGit.html.twig' %} + {% set tags = page.taxonomy.tag %} + {% if tags %} + {% set progress = page.collection({'items':{'@taxonomy':{'category': 'docs', 'tag': tags}},'order': {'by': 'default', 'dir': 'asc'}}) %} + {% else %} + {% set progress = page.collection({'items':{'@taxonomy':{'category': 'docs'}},'order': {'by': 'default', 'dir': 'asc'}}) %} + {% endif %} + + {% block navigation %} + + {% endblock %} + + {% block content %} +
+
+

{{ page.title }}

+ ${contentHtml} +
+
+ {% endblock %} + ` + ) +} + +// Handle NameSpace Group +function handleNamespace(title, content) { + let destinationDirectory = path.join(map_dir_md["Namespace"], title); + createMD(title, destinationDirectory, true); + createTemplate(title, content); +} + +// Handle Class Group +function handleClass(title, content) { + let destinationDirectory = path.join(map_dir_md["Class"], title); + createMD(title, destinationDirectory, true) + + let formatedHtml = content + .replace(html_reg_objectSpanNew, "") + createTemplate(title, formatedHtml); +} + +// Handle Global Group +function handleGlobal(title, content) { + createMD("Globals", map_dir_md["Global"], false, true); + createTemplate("Globals", content); +} + +// Handle Group TOCs +function makeGroupTOC(group) { + let mappedGroup; + if (!Array.isArray(group)) { + mappedGroup = groupNameMemberMap[group]; + } else { + mappedGroup = group; + } + let htmlGroup = mappedGroup.map(item => { + return dedent( + ` +
+ ${item} +
+ ` + ) + }) + return htmlGroup.join("\n"); + } + +// Handle Class TOCS +function makeClassTOC(group){ + let linkArray = [] + group.forEach( item => { + linkArray.push(`
${item.type}
`) + item.array.forEach( link => { + if ( link.indexOf('.') > -1 ){ + linkArray.push(``); + } else { + linkArray.push(``); + + } + }) + linkArray.push("
"); + }) + return linkArray.join("\n"); +} + +// Extract IDS for TOC +function extractIDs(groupToExtract){ + let firstLine = ""; + let id = ""; + let extractedIDs = []; + groupToExtract.forEach((item)=>{ + firstLine = item.split("\n")[0]; + try { + id = firstLine.split('id="')[1].split(`"`)[0]; + } catch (e){ + id = ""; + } + if (id){ + extractedIDs.push(id) + } + }) + return extractedIDs; +} + +// Helper for splitting up html +// Takes: Content to split, SearchTerm to Split by, and term to End Splitting By +// Returns: [newContent after Split, Array of extracted ] +function splitBy(content, searchTerm, endSplitTerm, title){ + let foundArray = []; + let curIndex = -1; + let afterCurSearchIndex = -1 + let nextIndex = 0; + let findbyNameLength = searchTerm.length; + let curEndSplitTermIndex = -1; + let classHeader; + do { + // Find the index of where to stop searching + curEndSplitTermIndex = content.indexOf(endSplitTerm); + // console.log("curEndSplitTermIndex", curEndSplitTermIndex) + // Find the index of the the next Search term + curIndex = content.indexOf(searchTerm); + // console.log("curIndex", curIndex) + + // The index of where the next search will start + afterCurSearchIndex = curIndex+findbyNameLength; + // Find the content of the next Index + nextIndex = content.indexOf(searchTerm,afterCurSearchIndex); + // If the next index isn't found, then next index === index of the end term + if (nextIndex === -1){ + nextIndex = curEndSplitTermIndex; + } + if (curIndex > curEndSplitTermIndex){ + break; + } + // Push from the cur index to the next found || the end term + let contentSlice = content.slice(curIndex, nextIndex); + if (contentSlice.indexOf(`id="${title}"`) === -1){ + foundArray.push(contentSlice); + } else { + classHeader = contentSlice; + } + + // Remove that content + content = content.replace(contentSlice, ""); + + curEndSplitTermIndex = content.indexOf(endSplitTerm); + nextIndex = content.indexOf(searchTerm,afterCurSearchIndex); + // Handle if nextIndex goes beyond endSplitTerm + if (nextIndex > curEndSplitTermIndex) { + curIndex = content.indexOf(searchTerm); + contentSlice = content.slice(curIndex, curEndSplitTermIndex); + if (contentSlice.indexOf(`id="${title}"`) === -1){ + foundArray.push(contentSlice); + } + content = content.replace(contentSlice, ""); + break; + } + } while (curIndex > -1) + if (classHeader){ + content = append(content, html_reg_findByArticleClose, classHeader, true); + } + return [content, foundArray]; +} + +// Split the signals and methods [Might make this more generic] +function splitMethodsSignals(allItemToSplit){ + let methodArray = []; + let signalArray = []; + + allItemToSplit.forEach( (content, index) => { + firstLine = content.split("\n")[0]; + if (firstLine.indexOf("{Signal}") > -1){ + signalArray.push(content); + } else if (firstLine.indexOf("span") > -1) { + methodArray.push(content); + } else { + } + }) + return [methodArray, signalArray]; +} + +// Helper to append +// Takes content, the search term to appendTo, the content to append, +// and bool if the append is before the found area +function append(content, searchTermToAppendto, contentToAppend, appendBefore){ + let contentArray = content.split("\n"); + let foundIndex = findArrayTrim(contentArray, searchTermToAppendto) + foundIndex = appendBefore ? foundIndex : foundIndex +1 + + contentArray.splice(foundIndex,0,contentToAppend) + return contentArray.join("\n") +} + +// Helper function for append +function findArrayTrim(array, searchTerm){ + var index = -1; + for (var i = 0; i < array.length; i++){ + index = array[i].trim().indexOf(searchTerm.trim()); + if (index > -1){ + return i + } + } + return index; +} + +// Remove grav directory if exists to make sure old files aren't kept +if (fs.existsSync(dir_grav)){ + console.log("dir_grav exists"); + rimraf.sync(dir_grav); +} + +// Create Grav directories in JSDOC output +dirArray.forEach(function(dir){ + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir); + } +}) + +// Create baseMD files +baseMDDirectories.forEach( md => { + createMD(md, map_dir_md[md]); +}) + +// Read jsdoc output folder and process html files +let files = fs.readdirSync(dir_out); + +// Create initial Group name member map to handle individual link +files.forEach(function (file){ + let curSource = path.join(dir_out, file); + if (path.extname(curSource) == ".html" && path.basename(curSource, '.html') !== "index") { + let loadedHtml = prepareHtml(curSource); + let splitTitle = loadedHtml("title").text().split(": "); + let groupName = splitTitle[1]; + let htmlTitle = splitTitle.pop(); + switch(groupName){ + case "Namespace": + groupNameMemberMap["Namespaces"].push(htmlTitle); + break; + case "Class": + groupNameMemberMap["Objects"].push(htmlTitle); + break; + default: + console.log(`Case not handled for ${groupName}`); + } + } +}) +files.forEach(function (file, index){ + // For testing individual files + // if (index !== 59) return; + let curSource = path.join(dir_out, file); + if (path.extname(curSource) == ".html" && path.basename(curSource, '.html') !== "index") { + // Clean up the html source + let loadedHtml = prepareHtml(curSource); + + // Extract the title, group name, and the main div + let splitTitle = loadedHtml("title").text().split(": "); + let groupName = splitTitle[1]; + let htmlTitle = splitTitle.pop(); + console.log("html title", htmlTitle) + let mainDiv = loadedHtml("#main") + + let methodIDs = []; + let signalIDs = []; + let typeDefIDs = []; + // Basic Regex HTML edits + let currentContent = mainDiv.html() + .replace(html_reg_findByMethod, "") //Remove Method title to be remade later + .replace(html_reg_static,"") // Remove static from the file names + .replace(html_reg_title,"") // Remove title + .replace(html_reg_objectHeader,"") // Remove extra Object Header + .replace(html_reg_dlClassDetails, "") // Remove unneccsary dlClassDetails Tag + .replace(html_reg_allNonHTTPLinks, removeHTML) // Remove the .html extension from all links + .replace(html_reg_allNonHTTPLinks, allLinksToLowerCase) // Turn all links into lowercase before ID tags + .replace(html_reg_allNonHTTPLinks, fixLinkGrouping) // Make sure links refer to correct grouping + .replace(html_reg_propertiesHeaderEdit, html_reg_propertiesHeaderEdit_Replace) // Remove : from Properties + .replace(html_reg_typeEdit, html_reg_typeEdit_replace) // Put type on the same line + .replace(html_reg_returnSize, html_reg_returnSize_replace) // Make return size h6 instead of h5 + .replace(html_reg_methodSize, html_reg_methodSize_replace) // Make method size into h5 + .replace(html_reg_pretty, html_reg_pretty_replace) // remove the references to pretty + .replace(html_reg_classDefinitonsTitle, html_reg_classDefinitonsTitle_replace) // Change the class def titles + .replace(html_reg_depreciated, html_reg_depreciated_replace); // format depreciated better + + // Further HTML Manipulation + // Make end term either Type Definitions or by the article + let endTerm; + let foundTypeDefinitions; + let foundSignalsAndMethods; + if (currentContent.indexOf("Type Definitions") > -1){ + // console.log("Found Type Definitions"); + endTerm = `

Type Definitions

`; + // Split HTML by Each named entry + let contentSplitArray = splitBy(currentContent, html_reg_findByName, endTerm, htmlTitle); + foundSignalsAndMethods = contentSplitArray[1]; + // console.log("foundSignalsAndMethods", foundSignalsAndMethods) + // Create a reference to the current content after split and the split functions + currentContent = contentSplitArray[0] + .replace(html_reg_typeDefType, html_reg_typeDefType_replace) // Edit how the typedef type looks + .replace(html_reg_typeDefinitonsTitle, ""); // Remove Type Definitions Title to be remade later; + endTerm = html_reg_findByArticleClose; + // Grab split Type Definitions + let contentSplitArrayForTypeDefs = splitBy(currentContent, html_reg_findByName, endTerm, htmlTitle); + currentContent = contentSplitArrayForTypeDefs[0]; + foundTypeDefinitions = contentSplitArrayForTypeDefs[1]; + // console.log("foundTypeDefinitions", foundTypeDefinitions) + + } else { + endTerm = html_reg_findByArticleClose; + let contentSplitArray = splitBy(currentContent, html_reg_findByName, endTerm, htmlTitle); + foundSignalsAndMethods = contentSplitArray[1]; + currentContent = contentSplitArray[0]; + } + + // Create references to the split methods and signals + let processedMethodsSignalsAndTypeDefs = splitMethodsSignals(foundSignalsAndMethods); + let splitMethods = processedMethodsSignalsAndTypeDefs[0]; + let splitSignals = processedMethodsSignalsAndTypeDefs[1]; + let splitTypeDefinitionIDS; + let splitMethodIDS = extractIDs(splitMethods); + let splitSignalIDS = extractIDs(splitSignals); + if (foundTypeDefinitions){ + splitTypeDefinitionIDS = extractIDs(foundTypeDefinitions); + } + let arrayToPassToClassToc = []; + + if (splitMethods.length > 0) { + arrayToPassToClassToc.push({type: "Methods", array: splitMethodIDS}); + // Add the Methods header to the Methods HTML + splitMethods.unshift(html_reg_findByMethod_replace) + currentContent = append(currentContent, html_reg_findByArticleClose, splitMethods.join('\n'), true); + } + if (splitSignals.length > 0) { + arrayToPassToClassToc.push({type: "Signals", array: splitSignalIDS}); + // Add the Signals header to the Signals HTML + splitSignals.unshift(html_reg_signalTitle) + currentContent = append(currentContent, html_reg_findByArticleClose, splitSignals.join('\n'),true); + } + if (foundTypeDefinitions && foundTypeDefinitions.length > 0) { + arrayToPassToClassToc.push({type: "Type Definitions", array: splitTypeDefinitionIDS}); + // Add the Type Defs header to the Type Defs HTML + foundTypeDefinitions.unshift(html_reg_typeDefinitonsTitle_replace) + currentContent = append(currentContent, html_reg_findByArticleClose, foundTypeDefinitions.join('\n'), true); + } + + let classTOC = makeClassTOC(arrayToPassToClassToc); + if (groupName === "Global"){ + currentContent = append(currentContent, html_reg_findByTitle, classTOC); + } else if (htmlTitle === "Controller") { + let curatedList = currentContent.match(html_reg_findControllerCuratedList); + currentContent = currentContent.replace(html_reg_findControllerCuratedList, ""); + let entityMethods = currentContent.match(html_reg_findEntityMethods); + currentContent = currentContent.replace(html_reg_findEntityMethods, ""); + currentContent = append(currentContent, html_reg_firstDivClose, [classTOC, curatedList, entityMethods].join("\n")); + currentContent = currentContent.replace(html_reg_EntityMethodsHeader, html_reg_EntityMethodsHeader_replace); + } else { + currentContent = append(currentContent, html_reg_firstDivClose, classTOC); + } + + // Final Pretty Content + currentContent = htmlclean(currentContent); + currentContent = pretty(currentContent); + + // Handle Unique Categories + switch(groupName){ + case "Namespace": + handleNamespace(htmlTitle, currentContent); + break; + case "Class": + handleClass(htmlTitle, currentContent); + break; + case "Global": + handleGlobal(htmlTitle, currentContent); + break; + default: + console.log(`Case not handled for ${groupName}`); + } + } +}) + +// Create the base Templates after processing individual files +createTemplate("API-Reference", makeGroupTOC(["Namespaces", "Objects", "Globals"])); +createTemplate("Namespaces", makeGroupTOC("Namespaces")); +createTemplate("Objects", makeGroupTOC("Objects")); + +// Copy the files to the target Directories if Local +if (copyLocal){ + // Copy files to the Twig Directory + let templateFiles = fs.readdirSync(path.resolve(targetTemplateDirectory)); + // Remove Existing API files + templateFiles.forEach(function(file){ + let curSource = path.join(targetTemplateDirectory, file); + + if(path.basename(file, '.html').indexOf("API") > -1){ + fs.unlink(curSource); + } + + }) + copyFolderRecursiveSync(dir_template, targetTemplateDirectory); + + // Copy files to the Md Directory + let baseMdRefDir = path.join(targetMDDirectory,"06.api-reference"); + // Remove existing MD directory + if (fs.existsSync(baseMdRefDir)){ + rimraf.sync(baseMdRefDir); + } + copyFolderRecursiveSync(dir_md, targetMDDirectory); +} \ No newline at end of file diff --git a/tools/jsdoc/package.json b/tools/jsdoc/package.json index 215ceec177..4bbb2ad4f2 100644 --- a/tools/jsdoc/package.json +++ b/tools/jsdoc/package.json @@ -1,7 +1,14 @@ { "name": "hifiJSDoc", "dependencies": { - "jsdoc": "^3.5.5" + "axios": "^0.18.0", + "cheerio": "^1.0.0-rc.2", + "dedent-js": "^1.0.1", + "htmlclean": "^3.0.8", + "jsdoc": "^3.5.5", + "pretty": "^2.0.0", + "request": "^2.85.0", + "rimraf": "^2.6.2" }, "private": true } diff --git a/tools/jsdoc/plugins/hifi.js b/tools/jsdoc/plugins/hifi.js index 049d32cceb..76f33e2c73 100644 --- a/tools/jsdoc/plugins/hifi.js +++ b/tools/jsdoc/plugins/hifi.js @@ -153,4 +153,4 @@ exports.defineTags = function (dictionary) { doclet.hifiServerEntity = true; } }); -}; +}; \ No newline at end of file