Skip to content

Commit

Permalink
See #246. Improve beautifier docs with executable docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Glavin001 committed Mar 29, 2020
1 parent 60f9b09 commit 6ed657b
Show file tree
Hide file tree
Showing 6 changed files with 339 additions and 49 deletions.
1 change: 1 addition & 0 deletions docs/about.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
id: about
title: What is Unibeautify
description: "Unibeautify is a universal code beautifier which joins multiple code formatters into one unified experience
---
**Unibeautify is a universal code beautifier.**
Expand Down
327 changes: 318 additions & 9 deletions scripts/generate-docs/BeautifierDoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
} from "./utils";
import Doc from "./Doc";
import MarkdownBuilder from "./MarkdownBuilder";
import ExecutableDoc from "./ExecutableDoc";

export default class BeautifierDoc extends Doc {
private readonly optionsLookup: OptionsLookup;
Expand Down Expand Up @@ -47,8 +48,10 @@ export default class BeautifierDoc extends Doc {
this.appendAboutSection(builder);
this.appendInstallSection(builder);
this.appendUsageSection(builder);
builder.header("Options", 2);
this.appendOptionsTable(builder);
this.appendFaqSection(builder);
this.appendTroubleshootingSection(builder);
// this.appendExecutablesSection(builder);
return builder.build();
}
private appendAboutSection(builder: MarkdownBuilder): MarkdownBuilder {
Expand Down Expand Up @@ -127,14 +130,184 @@ export default class BeautifierDoc extends Doc {
return builder;
}
builder.header("Prerequisites", 2);
builder.append("Please install the following prerequisites:");
builder.append("Please install the following prerequisites.");

/*
const depLinks = dependencies.map((dep: ExecutableDependencyDefinition) =>
MarkdownBuilder.createDocLink(
dep.name,
`executable-${slugify(this.beautifierName)}-${slugify(dep.name)}`
)
);
builder.list(depLinks);
*/

this.appendExecutablesSection(builder);

return builder;
}

private appendExecutablesSection(builder: MarkdownBuilder): MarkdownBuilder {
/*
const dependencies = this.dependencies.filter(
dep => dep.type === DependencyType.Executable
);
if (dependencies.length === 0) {
return builder;
}
*/

// builder.header("Executables", 2);
// builder.append("Please install the following prerequisites:");
// dependencies.forEach(async (dep: ExecutableDependencyDefinition) => {

this.executables.forEach((dep: ExecutableDependencyDefinition) => {
/*
MarkdownBuilder.createDocLink(
dep.name,
`executable-${slugify(this.beautifierName)}-${slugify(dep.name)}`
)
*/

/*
builder.header(`${dep.name} Executable`, 2);
const contents = new ExecutableDoc(dep, this.beautifier, this.languages).body;
const indentedContents = contents.replace(new RegExp("^(#+ .+)$","gm"),"#$1")
builder.append(indentedContents);
*/

this.appendExecutableSection(dep, builder);
// "### Hello world".replace(new RegExp("^(#+ .+)$","gm"),"#$1")
});
return builder;
}

private get executables(): ExecutableDependencyDefinition[] {
return this.dependencies.filter(
dep => dep.type === DependencyType.Executable
) as any[];
}

private appendTroubleshootingSection(builder: MarkdownBuilder): MarkdownBuilder {
// const dependencies: ExecutableDependencyDefinition[] = this.dependencies.filter(
// dep => dep.type === DependencyType.Executable
// );
if (this.executables.length === 0) {
return builder;
}

new ExecutableDoc(this.executables[0], this.beautifier, this.languages).appendTroubleshootingSection(builder);

/*
// builder.header("Executables", 2);
// builder.append("Please install the following prerequisites:");
dependencies.forEach(async (dep: ExecutableDependencyDefinition) => {
MarkdownBuilder.createDocLink(
dep.name,
`executable-${slugify(this.beautifierName)}-${slugify(dep.name)}`
)
builder.header(`${dep.name} Executable`, 2);
const nestedBuilder = new MarkdownBuilder();
// const contents = new ExecutableDoc(dep, this.beautifier, this.languages).body;
new ExecutableDoc(dep, this.beautifier, this.languages).appendTroubleshootingSection(nestedBuilder);
builder.append(MarkdownBuilder.indent(nestedBuilder.build()));
new ExecutableDoc(dep, this.beautifier, this.languages).appendTroubleshootingSection(builder);
// this.appendExecutableSection(dep, builder);
// "### Hello world".replace(new RegExp("^(#+ .+)$","gm"),"#$1")
});
*/
return builder;
}

private appendExecutableSection(executable: ExecutableDependencyDefinition, builder: MarkdownBuilder): MarkdownBuilder {
const { installationUrl, bugsUrl } = executable;
const dependency = executable;
const beautifierName: string = this.beautifier.name;
const dependencyName: string = dependency.name;
builder.header(`${executable.name} executable`, 3);
builder.appendBadges(executable.badges || []);
const isConfusing =
beautifierName.toLowerCase() === dependencyName.toLowerCase();
if (isConfusing) {
builder.append(
`> **${dependencyName} executable** should not be confused with **${beautifierName} beautifier** with the same name. Executables are non-[Node.js](https://nodejs.org/) tools for code formatting while beautifiers are [Node.js](https://nodejs.org/) packages which wrap an executable to be used by Unibeautify.\n`
);
}
builder.append(
`${dependencyName} executable is a third-party program you must install manually and is required for beautification.`
);
if (executable.homepageUrl) {
builder.append(
`See ${MarkdownBuilder.createLink(
executable.homepageUrl,
executable.homepageUrl
)} for more information.`
);
}

if (installationUrl) {
// builder.header(`Install ${executable.name} executable`, 3);
builder.append(
`Install ${executable.name} (\`${
executable.program
}\`) by following ${MarkdownBuilder.createLink(
installationUrl,
installationUrl
)}.`
);
if (bugsUrl) {
builder.append(
`If you have questions or want to report a bug, go to ${MarkdownBuilder.createLink(
bugsUrl,
bugsUrl
)}.`
);
}
}

/*
const dep = executable;
const executableConfig = {
[dep.name]: {
path: fakePathForProgram(dep.program),
},
};
const beautifierOptions: any = {
...executableConfig,
};
builder.append(
`A \`.unibeautifyrc.json\` file would look like the following:`
);
builder.code(
JSON.stringify(
{
LANGUAGE_NAME: {
beautifiers: [beautifierName],
[beautifierName]: beautifierOptions,
},
},
null,
2
),
"json"
);
builder.note(
`The \`LANGUAGE_NAME\` should be replaced with your desired supported language name, such as ${this.languages
.slice(0, 3)
.map(lang => `\`${lang.name}\``)
.join(", ")}, etc.`
);
*/
// builder.append(
// `See ${MarkdownBuilder.createLink(
// "Install",
// "#install"
// )} section below for how to determine absolute path to the exectuable.`
// );

return builder;
}

Expand All @@ -151,6 +324,32 @@ export default class BeautifierDoc extends Doc {
builder.append(
`A \`.unibeautifyrc.json\` file would look like the following:`
);
const hasOnly1Language = this.languages.length === 1;
const languageKey = hasOnly1Language ? this.languages[0].name : "LANGUAGE_NAME";

builder.code(
JSON.stringify(
{
[languageKey]: {
beautifiers: [beautifierName],
},
},
null,
2
),
"json"
);

if (!hasOnly1Language) {
builder.note(
`The \`LANGUAGE_NAME\` should be replaced with your desired supported language name, such as ${this.languages
.slice(0, 3)
.map(lang => `\`${lang.name}\``)
.join(", ")}, etc.`
);
}

/*
if (this.languages.length === 1) {
const languageName = this.languages[0].name;
builder.code(
Expand Down Expand Up @@ -185,15 +384,60 @@ export default class BeautifierDoc extends Doc {
.join(", ")}, etc.`
);
}
if (this.beautifierOptionKeys.length > 0) {
*/

const hasBeautifierOptions = this.beautifierOptionKeys.length > 0;
const hasExecutables = this.executables.length > 0;
if (hasBeautifierOptions || hasExecutables) {
builder.header("Advanced", 3);
builder.append(`The following beautifier option(s) are supported:`);
builder.list(this.beautifierOptionKeys.map(key => `\`${key}\``));
builder.append(
`See ${MarkdownBuilder.createDocLink(
"beautifier options",
if (hasBeautifierOptions) {
builder.append(`The following beautifier option(s) are supported:`);
builder.list(this.beautifierOptionKeys.map(key => `\`${key}\``));
builder.append(
`See ${MarkdownBuilder.createDocLink(
"beautifier options",
"options-for-beautifiers"
)} docs for more information.`
)} docs for more information.\n`
);
}

builder.append('Example advanced configuration:');
// prefer_beautifier_config
// const beautifierOptions: any = {
// // ...executableConfig,
// };
const beautifierOptions: any = this.beautifierOptionKeys.reduce(
(options, key) => ({
...options,
[key]: true,
}),
{}
);

this.executables.forEach((dep: ExecutableDependencyDefinition) => {
const executableConfig = {
[dep.name]: {
path: fakePathForProgram(dep.program),
},
};
// const beautifierOptions: any = {
// ...executableConfig,
// };
Object.assign(beautifierOptions, executableConfig);
});

builder.code(
JSON.stringify(
{
[languageKey]: {
beautifiers: [beautifierName],
[beautifierName]: beautifierOptions,
},
},
null,
2
),
"json"
);
}

Expand All @@ -210,6 +454,7 @@ export default class BeautifierDoc extends Doc {
return !!this.beautifier.resolveConfig;
}
private appendOptionsTable(builder: MarkdownBuilder): MarkdownBuilder {
builder.header("Options", 2);
if (!this.hasOptions) {
builder.append("No configuration options are supported.");
builder.append(
Expand Down Expand Up @@ -271,6 +516,66 @@ export default class BeautifierDoc extends Doc {
private get allOptions(): OptionsRegistry {
return Unibeautify.loadedOptions;
}

private appendFaqSection(builder: MarkdownBuilder): MarkdownBuilder {
builder.header("FAQ", 2);

// builder.header(`Should I use ${this.beautifierName}?`, 3);
// builder.append(`${this.beautifierName} `);

builder.header(`How to use ${this.beautifierName} in Atom, VSCode, and other editors?`, 3);
builder.append(`See the ${MarkdownBuilder.createDocLink(
"editor integration",
"editors"
)} documentation for installation instructions for your editor of choice.`);

if (this.canResolveConfig) {
builder.header(`How to use ${this.beautifierName} configuration file?`, 3);
builder.append(`You can override Unibeautify configuration and use ${this.beautifierName}'s own configuration file instead with \`prefer_beautifier_config\` beautifier option.`);
builder.code(
JSON.stringify(
{
LANGUAGE_NAME: {
beautifiers: [this.beautifierName],
[this.beautifierName]: {
prefer_beautifier_config: `path/to/${this.beautifierName}/config/file`
},
},
},
null,
2
),
"json"
);
builder.append(
`See ${MarkdownBuilder.createDocLink(
"beautifier options",
"options-for-beautifiers"
)} docs for more information.\n`
);
}

builder.header(`How to enable ${this.beautifierName} to format on save?`, 3);
builder.append(`See the ${MarkdownBuilder.createDocLink(
"editor integration",
"editors"
)} documentation for format on save instructions for your editor of choice.`);

builder.header(`How to run ${this.beautifierName} on all files?`, 3);
builder.append(`You can run ${this.beautifierName} on all of your files for every commit with ${MarkdownBuilder.createLink(
'Unibeautify CI',
'https://github.com/apps/unibeautify-ci',
)}.`);

builder.header(`Is there a ${this.beautifierName} sandbox or playground?`, 3);
builder.append(`You can quickly try ${this.beautifierName} online with ${MarkdownBuilder.createLink(
'Unibeautify Playground',
'https://playground.unibeautify.com/'
)}.`);

return builder;
}

private get repoBadges(): Badge[] {
return badgesForRepository(this.repository);
}
Expand Down Expand Up @@ -308,3 +613,7 @@ export default class BeautifierDoc extends Doc {
interface OptionsLookup {
[languageName: string]: OptionsRegistry;
}

function fakePathForProgram(program: string): string {
return `/absolute/path/to/${program}`;
}
Loading

0 comments on commit 6ed657b

Please sign in to comment.