This repository has been archived by the owner on Apr 21, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
1,121 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// tslint:disable no-implicit-dependencies | ||
|
||
import {Command} from '@anycli/command' | ||
import * as Config from '@anycli/config' | ||
import Help from '@anycli/plugin-help' | ||
import * as fs from 'fs-extra' | ||
import * as path from 'path' | ||
|
||
import {compact, sortBy, uniqBy} from '../util' | ||
|
||
const normalize = require('normalize-package-data') | ||
|
||
export default class Readme extends Command { | ||
static description = 'adds commands to readme' | ||
|
||
static aliases = ['c', 'd'] | ||
|
||
async run() { | ||
const config = Config.load({root: process.cwd()}) | ||
try { | ||
let p = require.resolve('@anycli/plugin-legacy') | ||
config.plugins.push(new Config.Plugin({root: p})) | ||
} catch {} | ||
await config.runHook('init', {id: 'readme', argv: this.argv}) | ||
let readme = await fs.readFile('README.md', 'utf8') | ||
// if (readme.includes('<!-- toc -->')) { | ||
// } else this.warn('<!-- toc --> not found in README') | ||
readme = this.commands(config, readme) | ||
|
||
console.log(readme) | ||
} | ||
|
||
commands(config: Config.IConfig, readme: string): string { | ||
const help = new Help(config, {stripAnsi: true, maxWidth: 120}) | ||
const build = (): string => { | ||
let commands = this.config.commands | ||
commands = commands.filter(c => !c.hidden) | ||
commands = uniqBy(commands, c => c.id) | ||
commands = sortBy(commands, c => c.id) | ||
const renderCommand = (level: number) => (c: Config.Command): string => { | ||
const header = () => '#'.repeat(level) + ` ${c.id}` | ||
const code = () => { | ||
let pluginName = c.pluginName | ||
if (!pluginName) return | ||
let plugin = config.plugins.concat([config]).find(p => p.name === c.pluginName) | ||
if (!plugin) return | ||
normalize(plugin.pjson) | ||
let repo = plugin.pjson.repository | ||
let commandsDir = plugin.pjson.anycli.commands | ||
if (!repo || !repo.url || !commandsDir) return | ||
commandsDir = commandsDir.replace(/\.\//, '') | ||
if (plugin.name === this.config.name) pluginName = path.join(__dirname, '../..') | ||
let commandPath = require.resolve(`${pluginName}/${commandsDir}/${c.id.replace(/:/g, '/')}`) | ||
commandPath = commandPath.replace(path.dirname(require.resolve(`${pluginName}/package.json`)) + '/', '') | ||
if (plugin.pjson.devDependencies.typescript) { | ||
commandPath = commandPath.replace(/^lib\//, 'src/') | ||
commandPath = commandPath.replace(/\.js$/, '.ts') | ||
} | ||
repo = repo.url.split('+')[1].replace(/\.git$/, '') | ||
return `_See code: [${plugin.name}](${repo}/blob/master/${commandPath})_` | ||
// return `_From plugin: [${plugin.name}](${plugin.pjson.homepage})_` | ||
} | ||
const subcommands = (): string | undefined => { | ||
return commands | ||
.filter(sc => sc.id.startsWith(c.id) && sc.id !== c.id) | ||
.map(renderCommand(level + 1)) | ||
.map(c => c.trim()) | ||
.join('\n\n') | ||
} | ||
return compact([ | ||
header(), | ||
'```\n' + help.command(c).trim() + '\n```', | ||
code(), | ||
subcommands(), | ||
]).join('\n\n') | ||
} | ||
let rootCommands = commands.filter(c => !c.id.includes(':')) | ||
|
||
return [ | ||
'<!-- commands -->', | ||
'# Commands\n', | ||
...commands.map(c => { | ||
return `* [${c.id}](#${c.id.replace(/:/g, '')})` | ||
}), | ||
...rootCommands.map(renderCommand(2)).map(s => s.trim() + '\n'), | ||
'<!-- commandsstop -->', | ||
].join('\n').trim() | ||
} | ||
if (readme.includes('<!-- commands -->')) { | ||
if (readme.includes('<!-- commandsstop -->')) { | ||
// clear out current commands | ||
readme = readme.replace(/<!-- commands -->(.|\n)*<!-- commandsstop -->/m, '<!-- commands -->') | ||
} | ||
readme = readme.replace(/<!-- commands -->/, build()) | ||
} else { | ||
// add commands to end | ||
readme += `\n${build()}` | ||
} | ||
return readme | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import Template = require('lodash.template') | ||
|
||
export function castArray<T>(input?: T | T[]): T[] { | ||
if (input === undefined) return [] | ||
return Array.isArray(input) ? input : [input] | ||
} | ||
|
||
export function uniqBy<T>(arr: T[], fn: (cur: T) => any): T[] { | ||
return arr.filter((a, i) => { | ||
let aVal = fn(a) | ||
return !arr.find((b, j) => j !== i && fn(b) === aVal) | ||
}) | ||
} | ||
|
||
export function compact<T>(a: (T | undefined)[]): T[] { | ||
return a.filter((a): a is T => !!a) | ||
} | ||
|
||
export function sortBy<T>(arr: T[], fn: (i: T) => sort.Types | sort.Types[]): T[] { | ||
function compare(a: sort.Types | sort.Types[], b: sort.Types | sort.Types[]): number { | ||
a = a === undefined ? 0 : a | ||
b = b === undefined ? 0 : b | ||
|
||
if (Array.isArray(a) && Array.isArray(b)) { | ||
if (a.length === 0 && b.length === 0) return 0 | ||
let diff = compare(a[0], b[0]) | ||
if (diff !== 0) return diff | ||
return compare(a.slice(1), b.slice(1)) | ||
} | ||
|
||
if (a < b) return -1 | ||
if (a > b) return 1 | ||
return 0 | ||
} | ||
|
||
return arr.sort((a, b) => compare(fn(a), fn(b))) | ||
} | ||
|
||
export namespace sort { | ||
export type Types = string | number | undefined | boolean | ||
} | ||
|
||
export const template = (context: any) => (t: string | undefined): string => Template(t || '')(context) |
Oops, something went wrong.