Skip to content
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

docs: add script to fetch design system pages for storybook #558

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ locales/
# storybook
storybook/storybook-static

# pages fetched from design system for storybook
docs/design-system

# Intermediate icons build directory. Our build tooling
# currently only supports building from code in ./src
# So we generate the react components in the src
Expand Down
89 changes: 89 additions & 0 deletions docs/fetch-design-system-pages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
const fs = require('fs').promises
const path = require('path')
const { URL } = require('url')
const { startCase } = require('lodash')
const fetch = require('node-fetch')

/**
* This regex matches relative links in markdown, like '![link](../images/image.png)'
*
* This will be used to transform relative links (and images) in the design system
* pages into external links to the github repo so these pages don't need to serve
* images and to enable linking to other design system pages.
*
* There is a negative lookahead assertion to exclude external links that include 'http'
* or same-page links that start with '#'
*
* It also checks if the link is for an image or not, because they need different handling
* The capture groups for the above link would be 1. '!' 2. 'link' and 3. '../images/image.png'
*
* Check it out here: https://regex101.com/r/y5o9Tf/6
*
*/
const mdRelativeLinkRegex = /(!)?\[(.*?)\]\((?!http|#)(.*?)\)/g
const rawGithubUrl =
'https://raw.githubusercontent.com/dhis2/design-system/master/principles/'
const regularGithubUrl =
'https://github.com/dhis2/design-system/tree/master/principles/'

// eslint-disable-next-line max-params
const linkReplacer = (_, imageBang, text, linkPath) => {
// Different links for images or markdown pages
const githubUrl = imageBang ? rawGithubUrl : regularGithubUrl
const prefix = imageBang || '' // '!' or ''
const url = new URL(linkPath, githubUrl).href
return `${prefix}[${text}](${url})`
}

const replaceRelativeLinksWithGithubLinks = text =>
text.replace(mdRelativeLinkRegex, linkReplacer)

// Template for creating .stories.mdx file for storybook that imports from regular markdown file
const mdxTemplate = basename => `import { Meta, Description } from '@storybook/addon-docs/blocks'
import ${startCase(basename).replace(/ /g, '')} from './${basename}.md'

<Meta title="Design System Principles/${startCase(basename)}" />

<Description>{${startCase(basename).replace(/ /g, '')}}</Description>
`

const outputDir = path.join('docs', 'design-system')

const downloadAndProcessFiles = async filteredFiles => {
// Create output dir if one doesn't exist yet
await fs.mkdir(outputDir, { recursive: true })
return Promise.all(
filteredFiles.map(async ({ name, download_url }) => {
// Get file contents
const text = await fetch(download_url).then(res => res.text())
// Transform relative links (see comments above)
const processedText = replaceRelativeLinksWithGithubLinks(text)
// Make a regular markdown file from contents
await fs.writeFile(path.join(outputDir, name), processedText)
// Make an MDX stories file that imports regular markdown
const basename = path.basename(name, '.md')
await fs.writeFile(
path.join(outputDir, `${basename}.stories.mdx`),
mdxTemplate(basename)
)
})
)
}

// Fetch design system 'principles' directory info from github
fetch(
'https://api.github.com/repos/dhis2/design-system/contents/principles?ref=master'
)
.then(res => res.json())
// Filter out non-markdown files
.then(fileInfo =>
fileInfo.filter(
({ name, type }) => type === 'file' && name.endsWith('.md')
)
)
// Fetch files and create local ones for storybook
.then(downloadAndProcessFiles)
.then(() =>
console.log('Design system files downloaded & processed for storybook')
)
.catch(console.error)
Copy link
Contributor

Choose a reason for hiding this comment

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

Catching the error and logging it to the console implies we only want to notify about this failure. I think for something like this, that does probably make sense: we can still showcase our components without including the design system files. However, this does imply that the storybook demo is still functional with these and I have not verified this.

Also, I think we should probably include some additional information about the context before printing this error to the console, i.e.:

The following error occurred while downloading and processing design system files. The design system will not be included in the demo storybook.
(and then the error)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a good point -- if there's something that could go wrong that would interfere with the rest of the storybook, it would be partially-made story files that could cause run-time errors. In that case, if there's an error, maybe the directory the design system files get copied into should get wiped to delete any malformed files

6 changes: 6 additions & 0 deletions docs/for-readers.stories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ In the **Using UI** section in the menu on the left, there are a few pages descr

These pages are the same as you would find on the previous doc site.

## Design System Principles

These are guiding principles from the [DHIS2 Design System](https://github.com/dhis2/design-system) about how to design an app that is visually consistent with the DHIS2 appearance and functionally effective. You should understand these principles and refer back to these pages and the Design System homepage as you build an app.

These pages are from the 'Principles' section of the Design System. For more design guidance and detailed guidelines for individual interface components, see the [Design System homepage](https://github.com/dhis2/design-system)

## Components

The other sections in the menu on the left describe the components available for use in the UI library.
Expand Down
1 change: 1 addition & 0 deletions storybook/config/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const parameters = {
'Useful Constants',
'Recipes',
],
'Design System Principles',
],
// Then sort the rest alphabetically
method: 'alphabetical',
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13043,6 +13043,11 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==

lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==

log-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
Expand Down