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

fix(dev): remove dependency on resolve order for linking in markdown … #599

Merged
merged 6 commits into from
Nov 13, 2023
Merged
Changes from 1 commit
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
Next Next commit
fix(dev): remove dependency on resolve order for linking in markdown …
…files

This fixes the error when linking a markdown file to another markdown file that is higher than the resolve order of the parent.

#562
Kane-R-G committed Sep 25, 2023
commit c808e00562429a0c57c6b9bdc6585b09df783861
28 changes: 22 additions & 6 deletions packages/histoire/src/node/markdown.ts
Original file line number Diff line number Diff line change
@@ -133,6 +133,7 @@ export async function createMarkdownPlugins (ctx: Context) {
}

export async function createMarkdownFilesWatcher (ctx: Context) {
let watcherError
const md = await createMarkdownRendererWithPlugins(ctx)

const watcher = chokidar.watch(['**/*.story.md'], {
@@ -147,17 +148,17 @@ export async function createMarkdownFilesWatcher (ctx: Context) {
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 html = md.render(content, {
// file: absolutePath,
// })

const file: ServerMarkdownFile = {
id: paramCase(relativePath.toLowerCase()),
relativePath,
absolutePath,
isRelatedToStory,
frontmatter,
html,
content,
}
ctx.markdownFiles.push(file)

@@ -214,14 +215,29 @@ export async function createMarkdownFilesWatcher (ctx: Context) {
.on('unlink', (relativePath) => {
removeFile(relativePath)
})
.on('ready', async () => {
// get ctx and md renderer to create HTML.
for (const mdFile of ctx.markdownFiles) {
try {
mdFile.html = md.render(mdFile.content, {
file: mdFile.absolutePath,
})
} catch (e: any) {
watcherError = e
}
}
})

await new Promise(resolve => {
watcher.once('ready', resolve)
})

return {
stop,
if (watcherError === null || watcherError === undefined) {
return {
stop,
}
}
return Promise.reject(watcherError)
}

export type MarkdownFilesWatcher = ReturnType<typeof createMarkdownFilesWatcher>
44 changes: 44 additions & 0 deletions packages/histoire/src/tests/markdown.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { describe, test, expect } from 'vitest'
import { createMarkdownFilesWatcher } from '../node/markdown'
import { watchStories } from '../node/stories'
import { createContext } from '../node/context.js'
import { createWriteStream, unlinkSync } from 'fs'

describe('markdown', async () => {
const ctx = await createContext({
mode: 'dev',
})
// create watch stories to set context root etc.
await watchStories(ctx)

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
await createMarkdownFilesWatcher(ctx)
expect(ctx.markdownFiles.length).toEqual(2)
})

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

test('should throw error on missing [md] story file.', async () => {
const testFile3 = '/resources/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/tests/resources/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/tests/resources/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 { makeTree } from '../node/tree'
import { getDefaultConfig } from '../node/config'
import type { ServerStoryFile } from '@histoire/shared'

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',
}
}