Skip to content
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
367 changes: 259 additions & 108 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,8 @@
},
"browserslist": [
"extends @instructure/browserslist-config-instui"
]
],
"dependencies": {
"clipboardy": "^4.0.0"
Copy link
Contributor

Choose a reason for hiding this comment

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

cant this be a dev dep?

Copy link
Contributor

Choose a reason for hiding this comment

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

or is this even needed?

}
}
30 changes: 19 additions & 11 deletions packages/__docs__/buildScripts/build-docs.mts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const pathsToProcess = [
'**/src/*/*.{js,ts,tsx}', // component src files
'**/src/*/*/*.{js,ts,tsx}', // child component src files
'CODE_OF_CONDUCT.md',
'LICENSE.md'
'LICENSE.md',
]

const pathsToIgnore = [
Expand Down Expand Up @@ -117,7 +117,7 @@ if (import.meta.url === pathToFileURL(process.argv[1]).href) {
buildDocs()
}

function buildDocs() {
async function buildDocs() {
// eslint-disable-next-line no-console
console.log('Start building application data')

Expand All @@ -127,17 +127,20 @@ function buildDocs() {
// globby needs the posix format
const files = pathsToProcess.map((file) => path.posix.join(packagesDir, file))
const ignore = pathsToIgnore.map((file) => path.posix.join(packagesDir, file))

globby(files, { ignore })
.then((matches) => {
.then(async (matches) => {

fs.mkdirSync(buildDir + 'docs/', { recursive: true })
// eslint-disable-next-line no-console
console.log(
'Parsing markdown and source files... (' + matches.length + ' files)'
)
const docs = matches.map((relativePath) => {
const docs = await Promise.all(matches.map(async (relativePath) => {
// loop trough every source and Readme file
return processSingleFile(path.resolve(relativePath))
})
return await processSingleFile(path.resolve(relativePath))
}))

const themes = parseThemes()
const clientProps = getClientProps(docs, library)
const props: MainDocsData = {
Expand All @@ -146,6 +149,7 @@ function buildDocs() {
library
}
const markdownsAndSources = JSON.stringify(props)

fs.writeFileSync(
buildDir + 'markdown-and-sources-data.json',
markdownsAndSources
Expand Down Expand Up @@ -182,12 +186,13 @@ function buildDocs() {
// This function is also called by Webpack if a file changes
// TODO this parses some files twice, its needed for the Webpack watcher but not
// for the full build.
function processSingleFile(fullPath: string) {
async function processSingleFile(fullPath: string) {

let docObject
const dirName = path.dirname(fullPath)
const fileName = path.parse(fullPath).name
if (fileName === 'index') {
docObject = processFile(fullPath, projectRoot, library)
docObject = await processFile(fullPath, projectRoot, library)
// Some Components (e.g. Alert) store their descriptions in README.md files.
// Add this to the final JSON if it's edited
const readmeDesc = tryParseReadme(dirName)
Expand All @@ -203,20 +208,23 @@ function processSingleFile(fullPath: string) {
componentIndexFile = path.join(dirName, 'index.ts')
}
if (componentIndexFile) {
docObject = processFile(componentIndexFile, projectRoot, library)
docObject = await processFile(componentIndexFile, projectRoot, library)
const readmeDesc = tryParseReadme(dirName)
docObject.description = readmeDesc ? readmeDesc : docObject.description
} else {
// just a README.md, has no index file
docObject = processFile(fullPath, projectRoot, library)
docObject = await processFile(fullPath, projectRoot, library)
}
} else {
// documentation .md files, utils ts and tsx files
docObject = processFile(fullPath, projectRoot, library)
docObject = await processFile(fullPath, projectRoot, library)
}

const docJSON = JSON.stringify(docObject!)
fs.writeFileSync(buildDir + 'docs/' + docObject!.id + '.json', docJSON)

return docObject!

}

function tryParseReadme(dirName: string) {
Expand Down
6 changes: 3 additions & 3 deletions packages/__docs__/buildScripts/processFile.mts
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ import { parseDoc } from './utils/parseDoc.mjs'
import { getPathInfo } from './utils/getPathInfo.mjs'
import type { LibraryOptions, ProcessedFile } from './DataTypes.mjs'

export function processFile(
export async function processFile(
fullPath: string,
projectRoot: string,
library: LibraryOptions
): ProcessedFile {
): Promise<ProcessedFile> {
// eslint-disable-next-line no-console
console.info(`Processing ${fullPath}`)
const source = fs.readFileSync(fullPath)
const dirName = path.dirname(fullPath) || process.cwd()
const pathInfo = getPathInfo(fullPath, projectRoot, library)

const doc = parseDoc(fullPath, source, (err: Error) => {
const doc = await parseDoc(fullPath, source, (err: Error) => {
console.warn('Error when parsing ', fullPath, ":\n", err.stack)
})
const docData: ProcessedFile = { ...doc, ...pathInfo } as ProcessedFile
Expand Down
23 changes: 12 additions & 11 deletions packages/__docs__/buildScripts/utils/getJSDoc.mts
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,26 @@
import jsdoc from 'jsdoc-api'
import type { JsDocResult } from '../DataTypes.mjs'

export function getJSDoc(source: Buffer, error: (err: Error) => void) {
export async function getJSDoc(source: Buffer, error: (err: Error) => void) {
// note: JSDoc seems to be abandoned, we should use TypeScript:
// https://stackoverflow.com/questions/47429792/is-it-possible-to-get-comments-as-nodes-in-the-ast-using-the-typescript-compiler
let doc: Partial<JsDocResult> = {}
try {
// JSDoc only creates these sections if the file has a @module or @namespace annotation
let sections: JsDocResult[] = jsdoc
.explainSync({
let sections: JsDocResult[] = await jsdoc
.explain({
// note: Do not use cache:true here, its buggy
configure: './jsdoc.config.json',
source
})
sections = sections.filter((section) => {
return (
section.undocumented !== true &&
section.access !== 'private' &&
section.kind !== 'package'
)
source: source.toString()
})

sections = sections.filter((section) => {
return (
section.undocumented !== true &&
section.access !== 'private' &&
section.kind !== 'package'
)
})
const module =
sections.filter((section) => section.kind === 'module')[0] ||
sections[0] ||
Expand Down
2 changes: 2 additions & 0 deletions packages/__docs__/buildScripts/utils/getReactDoc.mts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export function getReactDoc(
error: (err: Error) => void
) {
let doc: Documentation | undefined = undefined

try {
const parsed = parse(
source,
Expand All @@ -42,6 +43,7 @@ export function getReactDoc(
importer: makeFsImporter()
}
)

if (parsed.length > 1) {
// If a file has multiple exports this will choose the one that has the
// same name in its path.
Expand Down
13 changes: 8 additions & 5 deletions packages/__docs__/buildScripts/utils/parseDoc.mts
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,28 @@ import path from 'path'
import type { JsDocResult, YamlMetaInfo } from '../DataTypes.mjs'
import type { Documentation } from 'react-docgen'

export function parseDoc(
export async function parseDoc(
resourcePath: string,
source: Buffer,
errorHandler: (err: Error) => void
): Documentation & YamlMetaInfo & Partial<JsDocResult> {
): Promise<Documentation & YamlMetaInfo & Partial<JsDocResult>> {
const extension = path.extname(resourcePath)
const allowedExtensions = ['.js', '.ts', '.tsx']
let doc: Documentation | undefined

if (extension === '.md') {
doc = { description: source as unknown as string}
doc = { description: source as unknown as string }
} else if (allowedExtensions.includes(extension)) {

doc = getReactDoc(source, resourcePath, errorHandler)

if (!doc || !doc.props) {
doc = getJSDoc(source, errorHandler)
doc = await getJSDoc(source, errorHandler)
}

} else {
errorHandler(new Error('not allowed extension ' + extension))
doc = { description: source as unknown as string}
doc = { description: source as unknown as string }
}
// the YAML description in a JSDoc comment at the top of some files
let frontMatter: YamlMetaInfo
Expand Down
2 changes: 1 addition & 1 deletion packages/__docs__/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
"globby": "^14.0.2",
"gray-matter": "^4.0.3",
"html-webpack-plugin": "^5.6.3",
"jsdoc-api": "^8.1.1",
"jsdoc-api": "^9.3.4",
"mkdirp": "^3.0.1",
"raw-loader": "^4.0.2",
"react-docgen": "^7.1.1",
Expand Down
6 changes: 3 additions & 3 deletions packages/__docs__/webpack.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ const config = merge(baseConfig, {
directory: outputPath,
},
host: '0.0.0.0',
onListening: function () {
onListening: async function () {
// devServer is watching source files by default and hot reloading the docs page if they are changed
// however markdown files (i.e. README.md) need to be recompiled hence the need for chokidar
const paths = globbySync(['packages/**/*.md', 'docs/**/*.md'], { cwd: '../../' }).map(p => '../../' + p)
chokidar
.watch(paths)
.on('change', (evt) => {
.on('change', async (evt) => {
const fullPath = resolvePath(import.meta.dirname, evt)
processSingleFile(fullPath)
await processSingleFile(fullPath)
Comment on lines +62 to +70
Copy link
Collaborator

Choose a reason for hiding this comment

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

Both the Webpack onListening https://webpack.js.org/configuration/dev-server/#devserveronlistening
and Chokidar's on https://github.com/paulmillr/chokidar are not async.

I think this should work fine for 99% of use cases (unless you somehow modify the same file in very quick succession?) but please put a comment to both functions, that these do not wait for the promise to return.

})
},
client: {
Expand Down
Loading