Skip to content

Commit

Permalink
fix(dev): remove dependency on resolve order for linking in markdown … (
Browse files Browse the repository at this point in the history
#599)

Co-authored-by: Guillaume Chau <[email protected]>
  • Loading branch information
Kane-R-G and Akryum authored Nov 13, 2023
1 parent 510999f commit 4f2664e
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 12 deletions.
1 change: 1 addition & 0 deletions packages/histoire-shared/src/types/story.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export interface ServerMarkdownFile {
isRelatedToStory: boolean
frontmatter?: any
html?: string
content?: string
storyFile?: ServerStoryFile
}

Expand Down
59 changes: 59 additions & 0 deletions packages/histoire/src/node/__tests__/markdown.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { createWriteStream, unlinkSync } from 'node:fs'
import path from 'node:path'
import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest'
import { createMarkdownFilesWatcher } from '../markdown.js'
import { watchStories } from '../stories.js'
import { Context, createContext } from '../context.js'

describe('markdown', async () => {
vi.spyOn(process, 'cwd').mockReturnValue(path.resolve(__dirname, './markdown'))

let ctx: Context
let storyWatcher: Awaited<ReturnType<typeof watchStories>>

beforeEach(async () => {
ctx = await createContext({
mode: 'dev',
})

// create watch stories to set context root etc.
storyWatcher = await watchStories(ctx)
})

afterEach(() => {
storyWatcher.close()
})

test('should not throw error or depend on - resolve order for linking', async () => {
// FileWatcher should pickup the test markdown files (test1 and test2)
// test1 links to test2 (issue previously as test1 resolved first)
// test 2 links to test1
const { stop } = await createMarkdownFilesWatcher(ctx)
expect(ctx.markdownFiles.length).toEqual(2)
stop()
})

test('should render html from md', async () => {
const { stop } = await createMarkdownFilesWatcher(ctx)
expect(ctx.markdownFiles[0].html).toContain('<p>')
stop()
})

test('should throw error on missing [md] story file.', async () => {
const testFile3 = '/markdown/test3.story.md'
const writer = createWriteStream(__dirname.concat(testFile3))
// link to missing file.
writer.write(
'<!-- File should link to test1 file. -->\n' +
'# Test3\n\n' +
'Link to test 4\n' +
'[TEST](./test4.story.md)\n')
writer.end()
await new Promise(resolve => writer.on('finish', resolve))

// create markdownWatcher and check for error
await expect(async () => createMarkdownFilesWatcher(ctx)).rejects.toThrowError()
// delete test file, so failures are removed as well.
unlinkSync(__dirname.concat(testFile3))
})
})
7 changes: 7 additions & 0 deletions packages/histoire/src/node/__tests__/markdown/test1.story.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!-- File should link to test2 file. -->
<!-- File should return test2 successfully, even though test1 loads before test2. -->

# Test1

Link to test 2
[Test2](./test2.story.md)
5 changes: 5 additions & 0 deletions packages/histoire/src/node/__tests__/markdown/test2.story.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- File should link to test1 file. -->
# Test2

Link to test 1
[Test1](./test1.story.md)
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { describe, test, expect } from 'vitest'
import { makeTree } from './tree'
import { getDefaultConfig } from './config'
import type { StoryFile } from './types'
import type { ServerStoryFile } from '@histoire/shared'
import { makeTree } from '../tree.js'
import { getDefaultConfig } from '../config.js'

let id = 0

interface StoryFileFactoryOptions {
treePath: string[]
}

function storyFileFactory (options: StoryFileFactoryOptions): StoryFile {
function storyFileFactory (options: StoryFileFactoryOptions): ServerStoryFile {
return {
id: `id_${id++}`,
path: options.treePath.join('/'),
treePath: options.treePath,
fileName: 'fileName',
moduleId: 'moduleId',
relativePath: options.treePath.join('/'),
supportPluginId: 'supportPluginId',
}
}

Expand Down
43 changes: 35 additions & 8 deletions packages/histoire/src/node/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,23 +140,37 @@ export async function createMarkdownFilesWatcher (ctx: Context) {
ignored: ctx.config.storyIgnored,
})

async function addFile (relativePath: string) {
/**
* Initial scan is complete.
*/
let watcherIsReady = false

function addFile (relativePath: string) {
const absolutePath = path.resolve(ctx.root, relativePath)
const dirFiles = await fs.readdir(path.dirname(absolutePath))
const dirFiles = fs.readdirSync(path.dirname(absolutePath))
const truncatedName = path.basename(absolutePath, '.md')
const isRelatedToStory = dirFiles.some((file) => !file.endsWith('.md') && file.startsWith(truncatedName))

const { data: frontmatter, content } = matter(await fs.readFile(absolutePath, 'utf8'))
const html = md.render(content, {
file: absolutePath,
})
const { data: frontmatter, content } = matter(fs.readFileSync(absolutePath, 'utf8'))

let html: string | undefined

// We don't immediately render markdown during initial scanning in case
// markdown references other files in links (otherwise they might not
// be scanned yet and will throw 'not found' errors).
if (watcherIsReady) {
html = md.render(content, {
file: absolutePath,
})
}

const file: ServerMarkdownFile = {
id: paramCase(relativePath.toLowerCase()),
relativePath,
absolutePath,
isRelatedToStory,
frontmatter,
content,
html,
}
ctx.markdownFiles.push(file)
Expand Down Expand Up @@ -219,8 +233,21 @@ export async function createMarkdownFilesWatcher (ctx: Context) {
watcher.once('ready', resolve)
})

return {
stop,
try {
// Render markdown after initial scan is complete.
for (const mdFile of ctx.markdownFiles) {
mdFile.html = md.render(mdFile.content, {
file: mdFile.absolutePath,
})
}
watcherIsReady = true

return {
stop,
}
} catch (e) {
stop()
throw e
}
}

Expand Down

0 comments on commit 4f2664e

Please sign in to comment.