Skip to content

Extract docs #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 36 commits into from
May 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
1da1cac
deps
tmlayton Mar 24, 2021
4ed814a
Add script to generate READMEs
iainmcampbell Apr 28, 2021
ba24ed7
improve docs and add examples
tmlayton Apr 6, 2021
98447d3
render js and react examples
tmlayton Apr 7, 2021
b5247a9
proper code formatting
tmlayton Apr 8, 2021
3cfaf56
fix void type
tmlayton Apr 8, 2021
9945818
support params
tmlayton Apr 8, 2021
874cdf6
more types
tmlayton Apr 8, 2021
041d7fc
updates for content and getting started
tmlayton Apr 12, 2021
b030433
yamlFrontMatter function
iainmcampbell Apr 14, 2021
0da5844
Replace hardcoded paths in components()
iainmcampbell Apr 14, 2021
2e7ae4e
Genericize renderExamples
iainmcampbell Apr 14, 2021
3b86bf2
genericize getAdditionalContentFor, renaming
iainmcampbell Apr 14, 2021
722baba
typescript
iainmcampbell Apr 14, 2021
4e95c86
Parse and output tsdoc tags in PropertySignature nodes
iainmcampbell Apr 15, 2021
532bd57
fix table formatting
tmlayton Apr 16, 2021
2ac9d4f
fix up doc content output
tmlayton Apr 16, 2021
2a8bb48
update taxonomy and more clean-up
tmlayton Apr 17, 2021
56eab05
Wrap example code in `{% raw %}` so liquid doesn't barf
iainmcampbell Apr 21, 2021
9a95609
Render additionalPropsTables with <h3>
iainmcampbell Apr 21, 2021
972a21a
Sort components alphabetically
iainmcampbell Apr 21, 2021
650370b
Add yarn run docs command
iainmcampbell Apr 22, 2021
5555812
Handle Responsive type
iainmcampbell Apr 23, 2021
73336a0
Cool that fixed View too
iainmcampbell Apr 23, 2021
df01ecb
fix linting
tmlayton Apr 24, 2021
f0099b9
Add argo-admin generate-docs script entry
iainmcampbell Apr 29, 2021
cdadaf2
Add support for interface extends
iainmcampbell Apr 29, 2021
71d782b
Move shopify dev renderer into own folder, begin to componentize
iainmcampbell Apr 29, 2021
45194bb
add skipLibCheck to base tsconfig
iainmcampbell May 3, 2021
c76b383
Scripts get its own tsconfig
iainmcampbell May 4, 2021
0202003
fix rendering bugs, output proper yaml frontmatter description
iainmcampbell May 4, 2021
7a84f77
double quotes around yaml frontmatter description
iainmcampbell May 4, 2021
8af05c7
move to repo tsconfig
iainmcampbell May 4, 2021
3563335
fix resolve bug
iainmcampbell May 4, 2021
fe402ce
Remove scripts tsconfig
iainmcampbell May 5, 2021
82eaf78
Replace showdown with markdown-table
iainmcampbell May 5, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug current file",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/babel-node",
"runtimeArgs": ["--extensions", ".ts,.tsx,.mjs,.js,.json", "${file}"],
"sourceMaps": true,
"env": {
"BABEL_ENV": "debug"
}
}
]
}
18 changes: 15 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@
"build-consumer": "yarnpkg build && ./scripts/build-consumer.sh",
"restore-consumer": "./scripts/restore-consumer.sh",
"clean": "git clean -xdf ./packages; rm -rf ./build",
"clear-cache": "rm -rf .sewing-kit"
"clear-cache": "rm -rf .sewing-kit",
"run:ts": "babel-node --extensions .ts,.tsx,.mjs,.js,.json",
"run:ts:watch": "nodemon --ext .ts,.tsx,.mjs,.json,.graphql node_modules/.bin/babel-node --extensions .ts,.tsx,.mjs,.js,.json",
"docs:checkout": "babel-node --extensions .ts,.tsx,.mjs,.js,.json scripts/generate-docs-checkout.ts",
"docs:admin": "babel-node --extensions .ts,.tsx,.mjs,.js,.json scripts/generate-docs-admin.ts"
},
"devDependencies": {
"@babel/node": "^7.8.7",
"@microsoft/tsdoc": "^0.12.20",
"@sewing-kit/cli": "^0.2.0",
"@sewing-kit/config": "^0.1.0",
"@sewing-kit/eslint-plugin": "^0.0.14",
Expand All @@ -30,13 +36,19 @@
"@sewing-kit/plugin-react": "^0.1.0",
"@sewing-kit/plugin-typescript": "^0.1.0",
"@types/execa": "^0.9.0",
"@types/resolve": "^1.17.1",
"@types/uuid": "^8.3.0",
"lerna": "^3.22.1",
"markdown-table": "^2.0.0",
"nodemon": "^2.0.4",
"react": ">=17.0.0 <18.0.0",
"lerna": "^3.22.1"
"resolve": "^1.17.0",
"uuid": "^8.3.2"
},
"resolutions": {
"@typescript-eslint/eslint-plugin": "^4.0.0",
"@typescript-eslint/experimental-utils": "^4.0.0",
"@typescript-eslint/parser": "^4.0.0",
"typescript": "^4.1.0"
}
}
}
12 changes: 12 additions & 0 deletions scripts/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"presets": [
["@babel/preset-env", {"targets": {"node": true}}],
"@babel/preset-typescript"
],
"env": {
"debug": {
"sourceMaps": "inline",
"retainLines": true
}
}
}
14 changes: 14 additions & 0 deletions scripts/generate-docs-admin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {components, extensionPoints} from './typedoc/shopify-dev-renderer';

const paths = {
inputRoot: './packages/argo-admin',
packages: {
JavaScript: './packages/argo-admin',
React: './packages/argo-admin-react',
},
outputRoot: '../shopify-dev/content/tools/argo-admin',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we not put these docs in the same place as Checkout like docs/admin-extensions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably yes, haven't finalized this yet. not concerned about this right now.

shopifyDevUrl: '/tools/argo-admin',
};

components(paths);
extensionPoints(paths);
13 changes: 13 additions & 0 deletions scripts/generate-docs-checkout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {renderForShopifyDev} from './typedoc';

const paths = {
inputRoot: '../checkout-web/packages/argo-checkout',
packages: {
JS: '../checkout-web/packages/argo-checkout',
React: '../checkout-web/packages/argo-checkout-react',
},
outputRoot: '../shopify-dev/content/docs/checkout-extensions',
shopifyDevUrl: '/docs/checkout-extensions',
};

renderForShopifyDev(paths);
1 change: 1 addition & 0 deletions scripts/typedoc/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {renderForShopifyDev} from './shopify-dev-renderer';
196 changes: 196 additions & 0 deletions scripts/typedoc/shopify-dev-renderer/components.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
import {resolve, extname} from 'path';
import * as fs from 'fs';

import type {
Paths,
Packages,
} from '../types';

import {createDependencyGraph} from '../utilities/dependency-graph';

import {renderYamlFrontMatter, findUuid, dedupe, propsTable, strip, firstSentence} from './shared';
import type {Node} from './shared';

const additionalPropsTables: string[] = [];

export async function components(paths: Paths) {
const componentIndex = resolve(`${paths.inputRoot}/src/components/index.ts`);
const {nodes, components} = await buildComponentGraph(componentIndex);

const outputRoot = resolve(`${paths.outputRoot}`);
const componentDocsPath = resolve(`${paths.outputRoot}/components`);

if (!fs.existsSync(outputRoot)) {
fs.mkdirSync(outputRoot);
}

if (!fs.existsSync(componentDocsPath)) {
fs.mkdirSync(componentDocsPath);
}

const indexFile = resolve(`${paths.outputRoot}/components/index.md`);
let index = renderYamlFrontMatter({
gid: findUuid(indexFile),
url: `${paths.shopifyDevUrl}/components/index`,
title: 'Components for checkout extensions',
description: 'A list of components for checkout extensions.',
hidden: true,
});

index += `Argo provides many powerful UI components that a
[rendering extension](${paths.shopifyDevUrl}/extension-points#rendering) can
use to build an interface. This UI is rendered natively by Shopify, so you
can depend on it to be performant, accessible, and work in all of Checkout’s
supported browsers. \n\nThe following components are available as part of Argo
for Checkout, but make sure that you check the documentation for your
[extension point](${paths.shopifyDevUrl}/extension-points#extension-points)
to ensure the component is available in the extension points you are
targeting.\n\n`;

index += '<ul style="column-count: auto;column-width: 12rem;">';

components.forEach(({value: {name, docs, props}}: any) => {
const outputFile = `${componentDocsPath}/${name.toLowerCase()}.md`;

const docsContent = docs ? strip(docs.content).trim() : '';

const componentUrl = `${
paths.shopifyDevUrl
}/components/${name.toLowerCase()}`;

let markdown = renderYamlFrontMatter({
gid: findUuid(outputFile),
url: componentUrl,
title: `${name}`,
description: `"${firstSentence(docsContent)}"`,
hidden: true,
});
markdown += docsContent ? `${docsContent}\n\n` : '';

const examples = renderComponentExamplesFor(name, paths.packages);
if (examples.length > 0) {
markdown += examples;
}

const face = nodes.find(({value}: any) => value.name === props.name);
if (
face &&
face.value.kind === 'InterfaceType' &&
face.value.properties.length > 0
) {
markdown += '## Props\noptional = ?\n';
markdown += propsTable(
name,
docs,
face.value.properties,
nodes,
componentIndex,
additionalPropsTables,
false,
undefined,
);
}

markdown += dedupe(additionalPropsTables).reverse().join('');

const contentFolder = resolve(
`${paths.inputRoot}/src/components/${name}/content`,
);
markdown += getAdditionalContentFor(contentFolder);

fs.writeFile(outputFile, markdown, function (err) {
if (err) throw err;
});

additionalPropsTables.length = 0;
index += `<li><a href="${componentUrl}">${name}</a></li>`;
});

index += '</ul>';

// Write the component table of contents
fs.writeFile(indexFile, index, function (err) {
if (err) throw err;
});
}

async function buildComponentGraph(componentIndex: string) {
const graph = await createDependencyGraph(componentIndex);

const nodes: Node[] = [];

graph.forEach((value) => {
value.locals.forEach((value: any, key) => {
if (value.kind !== 'Imported') {
if (value.name == null) {
value.name = key;
}
nodes.push({value, module: undefined});
}
});
});

const components = [
...new Set(nodes.filter(({value}: any) => value.kind === 'Component')),
];

// console.log(JSON.stringify(nodes))

// Sort alphabetically (tsdoc seems to get this confused)
components.sort((aa: any, bb: any) => {
if (aa.value.name > bb.value.name) {
return 1;
} else if (aa.value.name < bb.value.name) {
return -1;
} else {
return 0;
}
});

return {nodes, components};
}

function renderComponentExamplesFor(name: string, packages: Packages): string {
const examples: any = {};

Object.keys(packages).forEach((packageName) => {
const packagePath = packages[packageName];
const folder = resolve(`${packagePath}/src/components/${name}/examples`);

if (fs.existsSync(folder)) {
fs.readdirSync(folder).forEach((file) => {
const extension = extname(file).split('.').pop();
examples[packageName] = `{% highlight ${extension} %}{% raw %}\n`;
examples[packageName] += fs.readFileSync(`${folder}/${file}`, 'utf8');
examples[packageName] += '\n{% endraw %}{% endhighlight %}\n\n';
});
}
});

let markdown = '';

const exampleCount = Object.keys(examples).length;

if (exampleCount > 1) {
const sections = Object.keys(examples).join(', ');
markdown += `{% sections "${sections}" %}\n\n`;
markdown += Object.values(examples).join('\n\n----\n\n');
markdown += '{% endsections %}\n\n';
} else if (exampleCount > 0) {
markdown += Object.values(examples).join('\n\n----\n\n');
}

return markdown;
}

function getAdditionalContentFor(contentFolder: string) {
let markdown = '';

if (fs.existsSync(contentFolder)) {
fs.readdirSync(contentFolder).forEach((file) => {
markdown += fs.readFileSync(`${contentFolder}/${file}`, 'utf8');
});
}

return markdown;
}
90 changes: 90 additions & 0 deletions scripts/typedoc/shopify-dev-renderer/extension-points.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import {resolve} from 'path';
import * as fs from 'fs';

import type {
Paths,
InterfaceType,
} from '../types';

import {createDependencyGraph} from '../utilities/dependency-graph';
import {renderYamlFrontMatter, findUuid, dedupe, propsTable} from './shared';
import type {Node} from './shared';

const additionalPropsTables: string[] = [];

export async function extensionPoints(paths: Paths) {
const extensionsIndex = resolve(`${paths.inputRoot}/src/index.ts`);

const graph = await createDependencyGraph(extensionsIndex);

const allInterfaces: InterfaceType[] = [];

for (const value of graph.values()) {
const localValues = [...value.locals.values()];
allInterfaces.push(
...(localValues.filter(
({kind}) => kind === 'InterfaceType',
) as InterfaceType[]),
);
}

const nodes: Node[] = [];

graph.forEach((value) => {
value.locals.forEach((value: any, key) => {
if (value.kind !== 'Imported') {
if (value.name == null) {
value.name = key;
}
nodes.push({value, module: undefined});
}
});
});

const interfaceEntryPoints = ['ExtensionPoints'];

const interfaces = allInterfaces.filter(({name}) =>
interfaceEntryPoints.includes(name),
);

const rootFolder = resolve(paths.outputRoot)
if (!fs.existsSync(rootFolder)) {
fs.mkdirSync(rootFolder);
}

const folder = resolve(`${paths.outputRoot}/extension-points`);
if (!fs.existsSync(folder)) {
fs.mkdirSync(folder);
}

const apiFile = resolve(`${paths.outputRoot}/extension-points/api.md`);

let markdown = renderYamlFrontMatter({
gid: findUuid(apiFile),
url: `${paths.shopifyDevUrl}/extension-points/api`,
title: 'Extension points API',
hidden: true,
});

interfaces.forEach(({name, docs, properties}) => {
markdown += propsTable(
name,
docs,
properties,
nodes,
extensionsIndex,
additionalPropsTables,
undefined,
undefined,
);
});

markdown += dedupe(additionalPropsTables).reverse().join('');

fs.writeFile(apiFile, markdown, function (err) {
if (err) throw err;
});

additionalPropsTables.length = 0;
}

Loading