Skip to content

Commit

Permalink
Adjust --help print to accommodate different syntaxes. Closes #4673
Browse files Browse the repository at this point in the history
  • Loading branch information
Jwaegebaert authored and milanholemans committed May 30, 2023
1 parent f888180 commit 1009ea8
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 51 deletions.
2 changes: 1 addition & 1 deletion src/chili/chili.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function getPromptFromArgs(args: string[]): string {

if (showHelp) {
const commandsFolder = path.join(__dirname, '..', 'm365');
const pathChunks: string[] = [commandsFolder, '..', '..', 'docs', 'docs', 'user-guide', 'chili.md'];
const pathChunks: string[] = [commandsFolder, '..', '..', 'docs', 'docs', 'user-guide', 'chili.mdx'];
const helpFilePath = path.join(...pathChunks);

if (fs.existsSync(helpFilePath)) {
Expand Down
16 changes: 8 additions & 8 deletions src/cli/Cli.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,9 @@ describe('Cli', () => {
});

it('shows help for the specific command when help specified followed by a valid command name', (done) => {
sinon.stub(fs, 'existsSync').callsFake((path) => path.toString().endsWith('.md'));
sinon.stub(fs, 'existsSync').callsFake((path) => path.toString().endsWith('.mdx'));
const originalFsReadFileSync = fs.readFileSync;
sinon.stub(fs, 'readFileSync').callsFake(() => originalFsReadFileSync(path.join(rootFolder, '..', '..', 'docs', 'docs', 'cmd', 'cli', 'completion', 'completion-clink-update.md'), 'utf8'));
sinon.stub(fs, 'readFileSync').callsFake(() => originalFsReadFileSync(path.join(rootFolder, '..', '..', 'docs', 'docs', 'cmd', 'cli', 'completion', 'completion-clink-update.mdx'), 'utf8'));
cli
.execute(rootFolder, ['help', 'cli', 'mock'])
.then(_ => {
Expand All @@ -373,9 +373,9 @@ describe('Cli', () => {
});

it('shows help for the specific command when valid command name specified followed by --help', (done) => {
sinon.stub(fs, 'existsSync').callsFake((path) => path.toString().endsWith('.md'));
sinon.stub(fs, 'existsSync').callsFake((path) => path.toString().endsWith('.mdx'));
const originalFsReadFileSync = fs.readFileSync;
sinon.stub(fs, 'readFileSync').callsFake(() => originalFsReadFileSync(path.join(rootFolder, '..', '..', 'docs', 'docs', 'cmd', 'cli', 'completion', 'completion-clink-update.md'), 'utf8'));
sinon.stub(fs, 'readFileSync').callsFake(() => originalFsReadFileSync(path.join(rootFolder, '..', '..', 'docs', 'docs', 'cmd', 'cli', 'completion', 'completion-clink-update.mdx'), 'utf8'));
cli
.execute(rootFolder, ['cli', 'mock', '--help'])
.then(_ => {
Expand All @@ -390,9 +390,9 @@ describe('Cli', () => {
});

it('shows help for the specific command when valid command name specified followed by -h', (done) => {
sinon.stub(fs, 'existsSync').callsFake((path) => path.toString().endsWith('.md'));
sinon.stub(fs, 'existsSync').callsFake((path) => path.toString().endsWith('.mdx'));
const originalFsReadFileSync = fs.readFileSync;
sinon.stub(fs, 'readFileSync').callsFake(() => originalFsReadFileSync(path.join(rootFolder, '..', '..', 'docs', 'docs', 'cmd', 'cli', 'completion', 'completion-clink-update.md'), 'utf8'));
sinon.stub(fs, 'readFileSync').callsFake(() => originalFsReadFileSync(path.join(rootFolder, '..', '..', 'docs', 'docs', 'cmd', 'cli', 'completion', 'completion-clink-update.mdx'), 'utf8'));
cli
.execute(rootFolder, ['cli', 'mock', '-h'])
.then(_ => {
Expand Down Expand Up @@ -421,9 +421,9 @@ describe('Cli', () => {
});

it('shows help for the specific command when help specified followed by a valid command alias', (done) => {
sinon.stub(fs, 'existsSync').callsFake((path) => path.toString().endsWith('.md'));
sinon.stub(fs, 'existsSync').callsFake((path) => path.toString().endsWith('.mdx'));
const originalFsReadFileSync = fs.readFileSync;
sinon.stub(fs, 'readFileSync').callsFake(() => originalFsReadFileSync(path.join(rootFolder, '..', '..', 'docs', 'docs', 'cmd', 'cli', 'completion', 'completion-clink-update.md'), 'utf8'));
sinon.stub(fs, 'readFileSync').callsFake(() => originalFsReadFileSync(path.join(rootFolder, '..', '..', 'docs', 'docs', 'cmd', 'cli', 'completion', 'completion-clink-update.mdx'), 'utf8'));
cli
.execute(rootFolder, ['help', 'cli', 'mock', 'alt'])
.then(_ => {
Expand Down
6 changes: 3 additions & 3 deletions src/cli/Cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -680,14 +680,14 @@ export class Cli {
const pathChunks: string[] = [this.commandsFolder, '..', '..', 'docs', 'docs', 'cmd'];

if (commandNameWords.length === 1) {
pathChunks.push(`${commandNameWords[0]}.md`);
pathChunks.push(`${commandNameWords[0]}.mdx`);
}
else {
if (commandNameWords.length === 2) {
pathChunks.push(commandNameWords[0], `${commandNameWords.join('-')}.md`);
pathChunks.push(commandNameWords[0], `${commandNameWords.join('-')}.mdx`);
}
else {
pathChunks.push(commandNameWords[0], commandNameWords[1], commandNameWords.slice(1).join('-') + '.md');
pathChunks.push(commandNameWords[0], commandNameWords[1], commandNameWords.slice(1).join('-') + '.mdx');
}
}

Expand Down
43 changes: 24 additions & 19 deletions src/utils/md.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,14 @@ import { md } from './md';
describe('utils/md', () => {
let cliCompletionClinkUpdateHelp: string;
let cliCompletionClinkUpdateHelpPlain: string;
let mdMixedLineEndings: string;
let loginHelp: string;
let loginHelpPlain: string;
let plannerPlanAddHelp: string;
let plannerPlanAddHelpPlain: string;

before(() => {
cliCompletionClinkUpdateHelp = fs.readFileSync(path.join(__dirname, '..', '..', 'docs', 'docs', 'cmd', 'cli', 'completion', 'completion-clink-update.md'), 'utf8');
cliCompletionClinkUpdateHelp = fs.readFileSync(path.join(__dirname, '..', '..', 'docs', 'docs', 'cmd', 'cli', 'completion', 'completion-clink-update.mdx'), 'utf8');
cliCompletionClinkUpdateHelpPlain = md.md2plain(cliCompletionClinkUpdateHelp, path.join(__dirname, '..', '..', 'docs'));
mdMixedLineEndings = '\n```sh\nnix\n```\n\r\n```sh\r\nWindows\r\n```\r\n';
loginHelp = fs.readFileSync(path.join(__dirname, '..', '..', 'docs', 'docs', 'cmd', 'login.md'), 'utf8');
loginHelp = fs.readFileSync(path.join(__dirname, '..', '..', 'docs', 'docs', 'cmd', 'login.mdx'), 'utf8');
loginHelpPlain = md.md2plain(loginHelp, path.join(__dirname, '..', '..', 'docs'));
plannerPlanAddHelp = fs.readFileSync(path.join(__dirname, '..', '..', 'docs', 'docs', 'cmd', 'planner', 'plan', 'plan-add.md'), 'utf8');
plannerPlanAddHelpPlain = md.md2plain(plannerPlanAddHelp, path.join(__dirname, '..', '..', 'docs'));

});

it('converts title to uppercase', () => {
Expand Down Expand Up @@ -50,7 +43,7 @@ describe('utils/md', () => {

it('keeps only label when hyperlink URL is relative', () => {
assert(loginHelpPlain.includes('create a custom Azure AD application'));
assert(!loginHelpPlain.includes('(../user-guide/using-own-identity.md)'));
assert(!loginHelpPlain.includes('(../user-guide/using-own-identity.mdx)'));
});

it('appends URL between brackets for hyperlinks with absolute URLs', () => {
Expand All @@ -64,12 +57,6 @@ describe('utils/md', () => {
assert(!cliCompletionClinkUpdateHelpPlain.includes('```'));
});

it('converts code fences with mixed line endings', () => {
const plain = md.md2plain(mdMixedLineEndings, path.join(__dirname, '..', '..', 'docs'));
const expected = `\n nix\n${EOL}\r\n Windows\r\n${EOL}`;
assert.strictEqual(plain, expected);
});

it('converts inline markup', () => {
assert(cliCompletionClinkUpdateHelpPlain.includes('m365.lua'));
assert(!cliCompletionClinkUpdateHelpPlain.includes('`m365.lua`'));
Expand All @@ -84,9 +71,27 @@ describe('utils/md', () => {
});

it('converts content tabs with code blocks', () => {
assert(plannerPlanAddHelpPlain.includes(` JSON${EOL}${EOL} {`), `'Doesn't include upper-case JSON`);
assert(plannerPlanAddHelpPlain.includes(`=== "JSON"`), 'Includes the original tab definition');
assert(!plannerPlanAddHelpPlain.includes(`\` json`), 'Includes language escape code');
const tabsMd = '<Tabs>\n <TabItem value="tab1">\n This is tab 1 content.\n </TabItem>\n <TabItem value="tab2">\n This is tab 2 content.\n </TabItem>\n <TabItem value="tab3">\n This is tab 3 content.\n </TabItem>\n</Tabs>';
const expected = 'tab1\n This is tab 1 content.\n tab2\n This is tab 2 content.\n tab3\n This is tab 3 content.';

const plain = md.md2plain(tabsMd, path.join(__dirname, '..', '..', 'docs'));
assert.strictEqual(plain, expected);
});

it('removes frontmatter tags', () => {
const frontmatterMd = '---\ntitle: Demo\n---';
const expected = '';

const plain = md.md2plain(frontmatterMd, path.join(__dirname, '..', '..', 'docs'));
assert.strictEqual(plain, expected);
});

it('removes imports', () => {
const importsMd = 'import demo from \'../demo\';\nimport \'demo.css\';';
const expected = '';

const plain = md.md2plain(importsMd, path.join(__dirname, '..', '..', 'docs'));
assert.strictEqual(plain, expected);
});

it('escapes underscores in an md string', () => {
Expand Down
50 changes: 30 additions & 20 deletions src/utils/md.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,23 @@ function convertHeadings(md: string): string {
}

function convertAdmonitions(md: string): string {
const regex = new RegExp('^!!!\\s(.*)' + EOL + '\\s+', 'gm');
return md.replace(regex, (match, content: string) => {
return content.toLocaleUpperCase() + EOL + EOL;
});
const regex = new RegExp(/^:::(\w+)([\s\S]*?):::$/, 'gm');
return md.replace(regex, (_, label: string, content: string) => label.toLocaleUpperCase() + EOL + EOL + content.trim());
}

function includeContent(md: string, rootFolder: string): string {
return md.replace(/^--8<-- "([^"]+)"/gm, (match, filePath: string) => {
return fs.readFileSync(path.join(rootFolder, filePath), 'utf8');
const mdxImports = [
{ tag: "<Global />", location: "docs/cmd/_global.mdx" },
{ tag: "<CLISettings />", location: "docs/_clisettings.mdx" }
];

mdxImports.forEach(mdxImport => {
md = md.replace(mdxImport.tag, () => {
return fs.readFileSync(path.join(rootFolder, mdxImport.location), 'utf8');
}).replace(/(```\r\n)\r\n(```md defintion-list\r\n)/g, "$1$2");
});

return md;
}

function convertDd(md: string): string {
Expand Down Expand Up @@ -53,17 +60,11 @@ function convertHyperlinks(md: string): string {
}

function convertContentTabs(md: string): string {
const regex = new RegExp('^=== "(.+?)"(?:\r\n|\n){2}((?:^ (?:.*?(?:\r\n|\n))?)+)', 'gms');
return md.replace(regex, (match, title: string, content: string) => {
return ` ${title}${EOL}${EOL}${content.replace(/^ /gms, '')}`;
});
}

function convertMdOutput(md: string): string {
const regex = new RegExp('(?<=^ ```md)(.*)(?= ```)', 'gms');
return md.replace(regex, (match, content: string) => {
return content.replace(/^ /gms, '');
});
return md
.replace(/<TabItem value="([^"]+)">/gm, '$1')
.replace(/.*<\/?(Tabs|TabItem)>.*\n?/g, '')
.replace(/```(?:\w+)?\s*([\s\S]*?)\s*```/g, '$1')
.trim();
}

function convertCodeFences(md: string): string {
Expand All @@ -83,6 +84,14 @@ function removeTooManyEmptyLines(md: string): string {
return md.replace(regex, Array(4).join(EOL));
}

function removeFrontmatter(md: string): string {
return md.replace(/^---[\s\S]*?---/gm, '').trim();
}

function removeImports(md: string): string {
return md.replace(/^import .+;$/gms, '').trim();
}

function escapeMd(mdString: string | undefined): string | undefined {
if (!mdString) {
return mdString;
Expand All @@ -99,11 +108,12 @@ const convertFunctions = [
convertAdmonitions,
convertDd,
convertHyperlinks,
convertMdOutput,
convertContentTabs,
convertCodeFences,
convertContentTabs,
removeInlineMarkup,
removeTooManyEmptyLines
removeTooManyEmptyLines,
removeFrontmatter,
removeImports
];

export const md = {
Expand Down

0 comments on commit 1009ea8

Please sign in to comment.