quackage 1.0.45 → 1.0.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -203,9 +203,9 @@
203
203
  "Description": "A template set for fableservice ...",
204
204
  "Files": [
205
205
  {
206
- "Hash": "FableServicejs",
207
- "Path": "Fable-Service.js",
208
- "Content": "const FableServiceProviderBase = require('fable-serviceproviderbase');\n\nconst _DefaultOptions = (\n\t{\n\t});\n\nclass FableService extends FableServiceProviderBase\n{\n\t/**\n\t * @param {import('fable')} pFable - The fable instance.\n\t * @param {Object<String, any>} [pOptions] - The options for the client.\n\t * @param {String} [pServiceHash] - A service hash for the fable service.\n\t */\n\tconstructor(pFable, pOptions, pServiceHash)\n\t{\n\t\tlet tmpOptions = Object.assign({}, _DefaultOptions, pOptions);\n\t\tsuper(pFable, tmpOptions, pServiceHash);\n\t}\n\n\tdoSomething()\n\t{\n\t\treturn true;\n\t}\n}\n\nmodule.exports = FableService;\n\nmodule.exports.default_configuration = _DefaultOptions;\n"
206
+ "Hash": "FableServiceQUACKAGESCOPEjs",
207
+ "Path": "Fable-Service-QUACKAGESCOPE.js",
208
+ "Content": "const libFableServiceProviderBase = require('fable-serviceproviderbase');\n\nconst _DefaultOptions = (\n\t{\n\t});\n\nclass FableService{~PascalCaseIdentifier:Record.Scope~} extends libFableServiceProviderBase\n{\n\t/**\n\t * @param {import('fable')} pFable - The fable instance.\n\t * @param {Object<String, any>} [pOptions] - The options for the client.\n\t * @param {String} [pServiceHash] - A service hash for the fable service.\n\t */\n\tconstructor(pFable, pOptions, pServiceHash)\n\t{\n\t\tconst tmpOptions = Object.assign({}, _DefaultOptions, pOptions);\n\t\tsuper(pFable, tmpOptions, pServiceHash);\n\t}\n\n\tdoSomething()\n\t{\n\t\treturn true;\n\t}\n}\n\nmodule.exports = FableService{~PascalCaseIdentifier:Record.Scope~};\nmodule.exports.default_configuration = _DefaultOptions;\n"
209
209
  }
210
210
  ]
211
211
  },
package/README.md CHANGED
@@ -9,6 +9,12 @@ This standardizes:
9
9
  1. Building an app for a browser
10
10
  2. Transpiling an app for ... older browsers
11
11
  3. Running unit tests
12
+ 4. Copying files around
13
+ 5. Managing package.json files in a standad way
14
+ 6. Assembling folders of JSON views into v7iew classes
15
+ 7. Boilerplate files and file structures
16
+ 8. Pulling documentation from codebases
17
+ 9. Compiling data description language files into their downstream parts (manifests, sql generation, documentation, etc.)
12
18
 
13
19
  ## Usage
14
20
 
package/debug/Harness.js CHANGED
@@ -5,4 +5,4 @@ let libQuackage = require('../source/Quackage-CLIProgram.js');
5
5
  //libQuackage.run(['node', 'Harness.js', 'bp', 'pictunittest']);
6
6
  //libQuackage.run(['node', 'Harness.js', 'lint']);
7
7
 
8
- libQuackage.run(['node', 'Harness.js', 'dgen', 'output_docs', '--source', '/Users/stevenvelozo/Code/retold/modules/pict/pict/source/']);
8
+ libQuackage.run(['node', 'Harness.js', 'dgen', 'output_docs', '--source', `${__dirname}/../source/`]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quackage",
3
- "version": "1.0.45",
3
+ "version": "1.0.47",
4
4
  "description": "Building. Testing. Quacking. Reloading.",
5
5
  "main": "source/Quackage-CLIProgram.js",
6
6
  "scripts": {
@@ -55,17 +55,18 @@
55
55
  "browserify": "^17.0.0",
56
56
  "chai": "4.3.10",
57
57
  "copy-files-from-to": "^3.11.0",
58
- "docsify-cli": "^4.4.4",
59
58
  "gulp": "^4.0.2",
60
59
  "gulp-babel": "^8.0.0",
61
60
  "gulp-env": "^0.4.0",
62
61
  "gulp-sourcemaps": "^3.0.0",
63
62
  "gulp-terser": "^2.1.0",
63
+ "indoctrinate": "^1.0.4",
64
64
  "jsdoc": "^4.0.5",
65
65
  "mocha": "10.4.0",
66
66
  "npm-check-updates": "^18.0.1",
67
67
  "nyc": "^15.1.0",
68
- "pict-service-commandlineutility": "^1.0.16",
68
+ "pict-docuserve": "^0.0.4",
69
+ "pict-service-commandlineutility": "^1.0.17",
69
70
  "vinyl-buffer": "^1.0.1",
70
71
  "vinyl-source-stream": "^2.0.0"
71
72
  },
@@ -59,7 +59,10 @@
59
59
 
60
60
  "coverage": "npx nyc --reporter=lcov --reporter=text-lcov npx mocha -- -u tdd -R spec",
61
61
 
62
- "build": "npx quack build"
62
+ "build": "npx quack build",
63
+
64
+ "docs": "npx quack prepare-docs ./docs -d ./modules",
65
+ "docs-serve": "npx quack docs-serve ./docs"
63
66
  },
64
67
  "LuxuryPackageScripts":
65
68
  {
@@ -37,7 +37,18 @@ let _Pict = new libCLIProgram(
37
37
  // Boilerplate file management
38
38
  require('./commands/Quackage-Command-Boilerplate.js'),
39
39
  require('./commands/Quackage-Command-ListTemplates.js'),
40
- require('./commands/Quackage-Command-BuildTemplates.js')
40
+ require('./commands/Quackage-Command-BuildTemplates.js'),
41
+
42
+ // Stricture
43
+ require('./commands/stricture//Quackage-Command-Stricture-Compile.js'),
44
+ require('./commands/stricture/Quackage-Command-StrictureLegacy.js'),
45
+
46
+ // Documentation preparation (indoctrinate + pict-docuserve)
47
+ require('./commands/Quackage-Command-Indoctrinate.js'),
48
+ require('./commands/Quackage-Command-IndoctrinateIndex.js'),
49
+ require('./commands/Quackage-Command-DocuserveInject.js'),
50
+ require('./commands/Quackage-Command-PrepareDocs.js'),
51
+ require('./commands/Quackage-Command-DocuserveServe.js')
41
52
  ]);
42
53
 
43
54
  // Instantiate the file persistence service
@@ -10,7 +10,6 @@ class QuackageCommandBuild extends libCommandLineCommand
10
10
  this.options.CommandKeyword = 'build';
11
11
  this.options.Description = 'Build your npm module into a dist folder';
12
12
 
13
- // Auto add the command on initialization
14
13
  this.addCommand();
15
14
  }
16
15
 
@@ -17,7 +17,6 @@ class QuackageCommandBuildTemplates extends libCommandLineCommand
17
17
 
18
18
  this.templateSets = {};
19
19
 
20
- // Auto add the command on initialization
21
20
  this.addCommand();
22
21
  }
23
22
 
@@ -11,6 +11,7 @@ class QuackageCommandCopyFilesFromTo extends libCommandLineCommand
11
11
  this.options.Description = 'Copy files to a stage location.';
12
12
 
13
13
  this.options.Aliases.push('copy');
14
+ this.options.Aliases.push('cp');
14
15
 
15
16
  // Auto add the command on initialization
16
17
  this.addCommand();
@@ -0,0 +1,90 @@
1
+ const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
2
+ const libFS = require('fs');
3
+ const libPath = require('path');
4
+
5
+ class QuackageCommandDocuserveInject extends libCommandLineCommand
6
+ {
7
+ constructor(pFable, pManifest, pServiceHash)
8
+ {
9
+ super(pFable, pManifest, pServiceHash);
10
+
11
+ this.options.CommandKeyword = 'docuserve-inject';
12
+ this.options.Description = 'Inject pict-docuserve application assets into a documentation folder for static hosting.';
13
+
14
+ this.options.CommandArguments.push({ Name: '<docs_folder>', Description: 'Target documentation folder to inject docuserve assets into.' });
15
+
16
+ this.options.Aliases.push('docuserve');
17
+ this.options.Aliases.push('inject-docs');
18
+
19
+ this.addCommand();
20
+ }
21
+
22
+ onRunAsync(fCallback)
23
+ {
24
+ let tmpDocsFolder = libPath.resolve(this.ArgumentString || '.');
25
+
26
+ this.log.info(`Injecting pict-docuserve assets into documentation folder...`);
27
+ this.log.info(` Target: ${tmpDocsFolder}`);
28
+
29
+ // Ensure the output folder exists
30
+ if (!libFS.existsSync(tmpDocsFolder))
31
+ {
32
+ this.log.info(`Creating documentation folder [${tmpDocsFolder}]...`);
33
+ libFS.mkdirSync(tmpDocsFolder, { recursive: true });
34
+ }
35
+
36
+ // Find the pict-docuserve binary
37
+ let tmpDocuserveLocation = this.resolveExecutable('pict-docuserve');
38
+ if (!tmpDocuserveLocation)
39
+ {
40
+ return fCallback(new Error(`Could not find pict-docuserve. Make sure it is installed (npm install pict-docuserve).`));
41
+ }
42
+
43
+ this.log.info(`Found pict-docuserve at [${tmpDocuserveLocation}]`);
44
+
45
+ this.fable.QuackageProcess.execute(
46
+ tmpDocuserveLocation,
47
+ [
48
+ 'inject',
49
+ tmpDocsFolder
50
+ ],
51
+ { cwd: this.fable.AppData.CWD },
52
+ (pError) =>
53
+ {
54
+ if (pError)
55
+ {
56
+ return fCallback(pError);
57
+ }
58
+
59
+ // Ensure .nojekyll exists for GitHub Pages compatibility
60
+ let tmpNoJekyllPath = libPath.join(tmpDocsFolder, '.nojekyll');
61
+ libFS.writeFileSync(tmpNoJekyllPath, '');
62
+ this.log.info(`Wrote .nojekyll to [${tmpNoJekyllPath}]`);
63
+
64
+ return fCallback();
65
+ }
66
+ );
67
+ }
68
+
69
+ resolveExecutable(pName)
70
+ {
71
+ let tmpLocations =
72
+ [
73
+ `${this.fable.AppData.CWD}/node_modules/.bin/${pName}`,
74
+ `${__dirname}/../../../.bin/${pName}`,
75
+ `${__dirname}/../../node_modules/.bin/${pName}`
76
+ ];
77
+
78
+ for (let i = 0; i < tmpLocations.length; i++)
79
+ {
80
+ if (libFS.existsSync(tmpLocations[i]))
81
+ {
82
+ return tmpLocations[i];
83
+ }
84
+ }
85
+
86
+ return false;
87
+ }
88
+ }
89
+
90
+ module.exports = QuackageCommandDocuserveInject;
@@ -0,0 +1,79 @@
1
+ const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
2
+ const libFS = require('fs');
3
+ const libPath = require('path');
4
+
5
+ class QuackageCommandDocuserveServe extends libCommandLineCommand
6
+ {
7
+ constructor(pFable, pManifest, pServiceHash)
8
+ {
9
+ super(pFable, pManifest, pServiceHash);
10
+
11
+ this.options.CommandKeyword = 'docs-serve';
12
+ this.options.Description = 'Serve a documentation folder locally using pict-docuserve.';
13
+
14
+ this.options.CommandArguments.push({ Name: '<docs_folder>', Description: 'The documentation folder to serve.' });
15
+
16
+ this.options.CommandOptions.push({ Name: '-p, --port [port]', Description: 'Port to serve on.', Default: '3333' });
17
+
18
+ this.options.Aliases.push('serve-docs');
19
+
20
+ this.addCommand();
21
+ }
22
+
23
+ onRunAsync(fCallback)
24
+ {
25
+ let tmpDocsFolder = libPath.resolve(this.ArgumentString || '.');
26
+ let tmpPort = this.CommandOptions.port || '3333';
27
+
28
+ this.log.info(`Serving documentation with pict-docuserve...`);
29
+ this.log.info(` Docs folder: ${tmpDocsFolder}`);
30
+ this.log.info(` Port: ${tmpPort}`);
31
+
32
+ if (!libFS.existsSync(tmpDocsFolder))
33
+ {
34
+ return fCallback(new Error(`Documentation folder not found at [${tmpDocsFolder}].`));
35
+ }
36
+
37
+ // Find the pict-docuserve binary
38
+ let tmpDocuserveLocation = this.resolveExecutable('pict-docuserve');
39
+ if (!tmpDocuserveLocation)
40
+ {
41
+ return fCallback(new Error(`Could not find pict-docuserve. Make sure it is installed (npm install pict-docuserve).`));
42
+ }
43
+
44
+ this.log.info(`Found pict-docuserve at [${tmpDocuserveLocation}]`);
45
+
46
+ this.fable.QuackageProcess.execute(
47
+ tmpDocuserveLocation,
48
+ [
49
+ 'serve',
50
+ tmpDocsFolder,
51
+ '--port', tmpPort
52
+ ],
53
+ { cwd: this.fable.AppData.CWD },
54
+ fCallback
55
+ );
56
+ }
57
+
58
+ resolveExecutable(pName)
59
+ {
60
+ let tmpLocations =
61
+ [
62
+ `${this.fable.AppData.CWD}/node_modules/.bin/${pName}`,
63
+ `${__dirname}/../../../.bin/${pName}`,
64
+ `${__dirname}/../../node_modules/.bin/${pName}`
65
+ ];
66
+
67
+ for (let i = 0; i < tmpLocations.length; i++)
68
+ {
69
+ if (libFS.existsSync(tmpLocations[i]))
70
+ {
71
+ return tmpLocations[i];
72
+ }
73
+ }
74
+
75
+ return false;
76
+ }
77
+ }
78
+
79
+ module.exports = QuackageCommandDocuserveServe;
@@ -4,7 +4,9 @@ const libOS = require('os');
4
4
  const libFS = require('fs');
5
5
  const libPath = require('path');
6
6
 
7
- const libJSDocWrapper = require('./Quackage-JSDoc-Wrapper.js');
7
+ const { spawn } = require('node:child_process');
8
+ const { createWriteStream } = require('node:fs');
9
+ const { once } = require('node:events');
8
10
 
9
11
  class QuackageCommandGenerateDocumentation extends libCommandLineCommand
10
12
  {
@@ -28,6 +30,138 @@ class QuackageCommandGenerateDocumentation extends libCommandLineCommand
28
30
  this.addCommand();
29
31
  }
30
32
 
33
+ /**
34
+ * Run the real JSDoc CLI with -X and return parsed JSON (like `jsdoc -X`).
35
+ *
36
+ * @param {string[]|string} pFilesArray Files/dirs/globs to parse. (e.g., ['src'] or 'src')
37
+ * @param {string|null} pJSDocConfig Path to jsdoc config file (e.g., 'jsdoc.conf.json') or null.
38
+ * @param {boolean} pSuppressOutput Suppress non-essential CLI output (defaults true).
39
+ * @param {string} pProcessCWD Working directory (defaults process.cwd()).
40
+ * @param {number} pTimoutMs Kill the process after N ms (0 = no timeout).
41
+ * @param {string[]} pCLIExtraArguments Extra CLI args (e.g., ['--recurse']).
42
+ * @param {string|null} pOutputFile If set, also write raw JSON to this file.
43
+ * @returns {Promise<any>} Parsed JSON doclets.
44
+ */
45
+ runJSDocCLI(pFilesArray, pJSDocConfig, pSuppressOutput, pProcessCWD, pTimoutMs, pCLIExtraArguments, pOutputFile, fCallback)
46
+ {
47
+ if (!pFilesArray || (Array.isArray(pFilesArray) && pFilesArray.length === 0)) pFilesArray = ['.'];
48
+ if (typeof pFilesArray === 'string') pFilesArray = [pFilesArray];
49
+ if (typeof pJSDocConfig === 'undefined') pJSDocConfig = null;
50
+ if (typeof pSuppressOutput === 'undefined') pSuppressOutput = true;
51
+ if (!pProcessCWD) pProcessCWD = process.cwd();
52
+ if (!pTimoutMs) pTimoutMs = 0;
53
+ if (!Array.isArray(pCLIExtraArguments)) pCLIExtraArguments = [];
54
+ if (typeof pOutputFile === 'undefined') pOutputFile = null;
55
+
56
+ return new Promise((resolve, reject) =>
57
+ {
58
+ // Resolve local CLI in the node_modules folder and try that; fallback to `npx jsdoc` if this fails
59
+ let tmpCommandPath, tmpCommandArguments;
60
+ let tmpExecuteUsingNode = true;
61
+ try
62
+ {
63
+ const jsdocBin = require.resolve('jsdoc/jsdoc.js', { paths: [pProcessCWD] });
64
+ tmpCommandPath = process.execPath;
65
+ tmpCommandArguments = [
66
+ jsdocBin,
67
+ '-X',
68
+ ...(pSuppressOutput ? ['--quiet'] : []),
69
+ ...(pJSDocConfig ? ['-c', pJSDocConfig] : []),
70
+ ...pCLIExtraArguments,
71
+ ...pFilesArray,
72
+ ];
73
+ }
74
+ catch
75
+ {
76
+ tmpExecuteUsingNode = false;
77
+ tmpCommandPath = process.platform === 'win32' ? 'npx.cmd' : 'npx';
78
+ tmpCommandArguments = [
79
+ '-y',
80
+ 'jsdoc',
81
+ '-X',
82
+ ...(pSuppressOutput ? ['--quiet'] : []),
83
+ ...(pJSDocConfig ? ['-c', pJSDocConfig] : []),
84
+ ...pCLIExtraArguments,
85
+ ...pFilesArray,
86
+ ];
87
+ }
88
+
89
+ const tmpChild = spawn(tmpCommandPath, tmpCommandArguments, { cwd: pProcessCWD, stdio: ['ignore', 'pipe', 'pipe'] });
90
+
91
+ let tmpStdOut = '';
92
+ let tmpStdErr = '';
93
+
94
+ const tmpTimeoutSignal = pTimoutMs > 0 ? setTimeout(() => tmpChild.kill('SIGKILL'), pTimoutMs) : null;
95
+
96
+ let tmpOutputStream = null;
97
+ if (pOutputFile)
98
+ {
99
+ tmpOutputStream = createWriteStream(pOutputFile, { encoding: 'utf8' });
100
+ }
101
+
102
+ tmpChild.stdout.setEncoding('utf8');
103
+ tmpChild.stderr.setEncoding('utf8');
104
+
105
+ tmpChild.stdout.on('data',
106
+ (pChunk) =>
107
+ {
108
+ tmpStdOut += pChunk;
109
+ if (tmpOutputStream) tmpOutputStream.write(pChunk);
110
+ });
111
+ tmpChild.stderr.on('data',
112
+ (pChunk) =>
113
+ {
114
+ tmpStdErr += pChunk;
115
+ });
116
+
117
+ const finalize = async (pProcessReturnCode) =>
118
+ {
119
+ if (tmpTimeoutSignal)
120
+ {
121
+ clearTimeout(tmpTimeoutSignal);
122
+ }
123
+
124
+ if (tmpOutputStream)
125
+ {
126
+ await new Promise(
127
+ (pResult) =>
128
+ {
129
+ tmpOutputStream.end(pResult)
130
+ });
131
+ }
132
+ if (pProcessReturnCode !== 0)
133
+ {
134
+ const tmpExecutionMethod = tmpExecuteUsingNode ? 'node jsdoc/jsdoc.js' : 'npx jsdoc';
135
+ const tmpError = new Error(`JSDoc exited with code ${pProcessReturnCode} (${tmpExecutionMethod}).\n${tmpStdErr || ''}`);
136
+ tmpError.code = pProcessReturnCode;
137
+ tmpError.stderr = tmpStdErr;
138
+ tmpError.stdout = tmpStdOut;
139
+ reject(tmpError);
140
+ return fCallback(tmpError);
141
+ }
142
+ try
143
+ {
144
+ resolve(JSON.parse(tmpStdOut));
145
+ }
146
+ catch (pError)
147
+ {
148
+ const tmpStdOutHead = tmpStdOut.slice(0, 3000);
149
+ const tmpError = new Error(
150
+ `Failed to parse JSDoc JSON. Ensure --quiet and plugins don't write to stdout.\n` +
151
+ `Parse error: ${pError.message}\n--- stdout (head) ---\n${tmpStdOutHead}`
152
+ );
153
+ tmpError.stderr = tmpStdErr;
154
+ tmpError.stdout = tmpStdOut;
155
+ reject(tmpError);
156
+ }
157
+ return fCallback();
158
+ };
159
+
160
+ tmpChild.on('close', finalize);
161
+ tmpChild.on('error', reject);
162
+ });
163
+ }
164
+
31
165
  onRunAsync(fCallback)
32
166
  {
33
167
  const libFilePersistence = this.services.FilePersistence;
@@ -89,7 +223,7 @@ class QuackageCommandGenerateDocumentation extends libCommandLineCommand
89
223
  function (fNext)
90
224
  {
91
225
  this.log.info(`Documentation Phase 1: Gathering documentation metadata...`);
92
- libJSDocWrapper(tmpOperationState.SourceCodeFolderJSDocParameter, null, false, './', 60000, [], tmpOperationState.JSDocOutputPath, fNext);
226
+ this.runJSDocCLI(tmpOperationState.SourceCodeFolderJSDocParameter, null, false, './', 60000, [], tmpOperationState.JSDocOutputPath, fNext);
93
227
  }.bind(this));
94
228
 
95
229
  tmpAnticipate.anticipate(
@@ -0,0 +1,88 @@
1
+ const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
2
+ const libFS = require('fs');
3
+ const libPath = require('path');
4
+
5
+ class QuackageCommandIndoctrinate extends libCommandLineCommand
6
+ {
7
+ constructor(pFable, pManifest, pServiceHash)
8
+ {
9
+ super(pFable, pManifest, pServiceHash);
10
+
11
+ this.options.CommandKeyword = 'indoctrinate';
12
+ this.options.Description = 'Generate a documentation catalog from module documentation folders using indoctrinate.';
13
+
14
+ this.options.CommandArguments.push({ Name: '<docs_folder>', Description: 'The documentation output folder for the generated catalog.' });
15
+
16
+ this.options.CommandOptions.push({ Name: '-d, --directory_root [directory_root]', Description: 'Root directory to scan for modules (defaults to CWD).', Default: '' });
17
+ this.options.CommandOptions.push({ Name: '-b, --branch [branch]', Description: 'Git branch for GitHub raw URLs (defaults to master).', Default: 'master' });
18
+ this.options.CommandOptions.push({ Name: '-g, --github_org [github_org]', Description: 'GitHub organization for raw URLs (defaults to stevenvelozo).', Default: 'stevenvelozo' });
19
+
20
+ this.options.Aliases.push('indoc');
21
+
22
+ this.addCommand();
23
+ }
24
+
25
+ onRunAsync(fCallback)
26
+ {
27
+ let tmpDocsFolder = libPath.resolve(this.ArgumentString || '.');
28
+ let tmpDirectoryRoot = this.CommandOptions.directory_root || this.fable.AppData.CWD;
29
+ let tmpBranch = this.CommandOptions.branch || 'master';
30
+ let tmpGitHubOrg = this.CommandOptions.github_org || 'stevenvelozo';
31
+ let tmpOutputFile = libPath.join(tmpDocsFolder, 'retold-catalog.json');
32
+
33
+ this.log.info(`Generating documentation catalog with indoctrinate...`);
34
+ this.log.info(` Module root: ${tmpDirectoryRoot}`);
35
+ this.log.info(` Output: ${tmpOutputFile}`);
36
+
37
+ // Ensure the output folder exists
38
+ if (!libFS.existsSync(tmpDocsFolder))
39
+ {
40
+ this.log.info(`Creating documentation folder [${tmpDocsFolder}]...`);
41
+ libFS.mkdirSync(tmpDocsFolder, { recursive: true });
42
+ }
43
+
44
+ // Find the indoctrinate binary
45
+ let tmpIndoctrinateLocation = this.resolveExecutable('indoctrinate');
46
+ if (!tmpIndoctrinateLocation)
47
+ {
48
+ return fCallback(new Error(`Could not find indoctrinate. Make sure it is installed (npm install indoctrinate).`));
49
+ }
50
+
51
+ this.log.info(`Found indoctrinate at [${tmpIndoctrinateLocation}]`);
52
+
53
+ this.fable.QuackageProcess.execute(
54
+ tmpIndoctrinateLocation,
55
+ [
56
+ 'generate_catalog',
57
+ '-d', tmpDirectoryRoot,
58
+ '-o', tmpOutputFile,
59
+ '-b', tmpBranch,
60
+ '-g', tmpGitHubOrg
61
+ ],
62
+ { cwd: this.fable.AppData.CWD },
63
+ fCallback
64
+ );
65
+ }
66
+
67
+ resolveExecutable(pName)
68
+ {
69
+ let tmpLocations =
70
+ [
71
+ `${this.fable.AppData.CWD}/node_modules/.bin/${pName}`,
72
+ `${__dirname}/../../../.bin/${pName}`,
73
+ `${__dirname}/../../node_modules/.bin/${pName}`
74
+ ];
75
+
76
+ for (let i = 0; i < tmpLocations.length; i++)
77
+ {
78
+ if (libFS.existsSync(tmpLocations[i]))
79
+ {
80
+ return tmpLocations[i];
81
+ }
82
+ }
83
+
84
+ return false;
85
+ }
86
+ }
87
+
88
+ module.exports = QuackageCommandIndoctrinate;
@@ -0,0 +1,83 @@
1
+ const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
2
+ const libFS = require('fs');
3
+ const libPath = require('path');
4
+
5
+ class QuackageCommandIndoctrinateIndex extends libCommandLineCommand
6
+ {
7
+ constructor(pFable, pManifest, pServiceHash)
8
+ {
9
+ super(pFable, pManifest, pServiceHash);
10
+
11
+ this.options.CommandKeyword = 'indoctrinate-index';
12
+ this.options.Description = 'Generate a lunr keyword search index from module documentation using indoctrinate.';
13
+
14
+ this.options.CommandArguments.push({ Name: '<docs_folder>', Description: 'The documentation output folder for the generated keyword index.' });
15
+
16
+ this.options.CommandOptions.push({ Name: '-d, --directory_root [directory_root]', Description: 'Root directory to scan for modules (defaults to CWD).', Default: '' });
17
+
18
+ this.options.Aliases.push('indoc-index');
19
+ this.options.Aliases.push('keyword-index');
20
+
21
+ this.addCommand();
22
+ }
23
+
24
+ onRunAsync(fCallback)
25
+ {
26
+ let tmpDocsFolder = libPath.resolve(this.ArgumentString || '.');
27
+ let tmpDirectoryRoot = this.CommandOptions.directory_root || this.fable.AppData.CWD;
28
+ let tmpOutputFile = libPath.join(tmpDocsFolder, 'retold-keyword-index.json');
29
+
30
+ this.log.info(`Generating keyword search index with indoctrinate...`);
31
+ this.log.info(` Module root: ${tmpDirectoryRoot}`);
32
+ this.log.info(` Output: ${tmpOutputFile}`);
33
+
34
+ // Ensure the output folder exists
35
+ if (!libFS.existsSync(tmpDocsFolder))
36
+ {
37
+ this.log.info(`Creating documentation folder [${tmpDocsFolder}]...`);
38
+ libFS.mkdirSync(tmpDocsFolder, { recursive: true });
39
+ }
40
+
41
+ // Find the indoctrinate binary
42
+ let tmpIndoctrinateLocation = this.resolveExecutable('indoctrinate');
43
+ if (!tmpIndoctrinateLocation)
44
+ {
45
+ return fCallback(new Error(`Could not find indoctrinate. Make sure it is installed (npm install indoctrinate).`));
46
+ }
47
+
48
+ this.log.info(`Found indoctrinate at [${tmpIndoctrinateLocation}]`);
49
+
50
+ this.fable.QuackageProcess.execute(
51
+ tmpIndoctrinateLocation,
52
+ [
53
+ 'generate_keyword_index',
54
+ '-d', tmpDirectoryRoot,
55
+ '-o', tmpOutputFile
56
+ ],
57
+ { cwd: this.fable.AppData.CWD },
58
+ fCallback
59
+ );
60
+ }
61
+
62
+ resolveExecutable(pName)
63
+ {
64
+ let tmpLocations =
65
+ [
66
+ `${this.fable.AppData.CWD}/node_modules/.bin/${pName}`,
67
+ `${__dirname}/../../../.bin/${pName}`,
68
+ `${__dirname}/../../node_modules/.bin/${pName}`
69
+ ];
70
+
71
+ for (let i = 0; i < tmpLocations.length; i++)
72
+ {
73
+ if (libFS.existsSync(tmpLocations[i]))
74
+ {
75
+ return tmpLocations[i];
76
+ }
77
+ }
78
+
79
+ return false;
80
+ }
81
+ }
82
+
83
+ module.exports = QuackageCommandIndoctrinateIndex;
@@ -12,6 +12,7 @@ class QuackageCommandBoilerplate extends libCommandLineCommand
12
12
  this.options.Description = 'List the available boilerplate template filesets in your user, local and the built-in .quackage-templates.json file(s).';
13
13
 
14
14
  this.options.Aliases.push('list');
15
+ this.options.Aliases.push('ls');
15
16
  this.options.Aliases.push('lt');
16
17
 
17
18
  this.fable.TemplateProvider.addTemplate('PrototypePackage', JSON.stringify(this.pict.ProgramConfiguration, null, 4));