Skip to content

Commit

Permalink
fix race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
souporserious committed Nov 21, 2023
1 parent e62bde6 commit 9606ccd
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 39 deletions.
1 change: 1 addition & 0 deletions mdxts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"@mdx-js/loader": "^2.3.0",
"@mdx-js/mdx": "^2.3.0",
"@next/mdx": "13.4.19",
"@preact/signals-core": "^1.5.0",
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.94",
"@types/hast": "^3.0.0",
Expand Down
12 changes: 10 additions & 2 deletions mdxts/src/components/Code.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { SourceFile } from 'ts-morph'
import { getHighlighter, type Theme } from './highlighter'
import { project } from './project'
import { CodeView } from './CodeView'
import { registerCodeComponent, unregisterCodeComponent } from './state'

export type BaseCodeProps = {
/** Name of the file. */
Expand Down Expand Up @@ -82,6 +83,11 @@ export async function Code({
isNestedInEditor,
...props
}: CodeProps) {
const id =
'source' in props ? props.source : filenameProp ?? `${filenameId++}`

registerCodeComponent(id)

let finalValue
let finalLanguage = languageMap[language] ?? language
let isJsxOnly = false
Expand All @@ -105,8 +111,7 @@ export async function Code({
const filename =
'source' in props
? props.source
: filenameProp ?? `${filenameId++}.mdxts.${finalLanguage}`
const highlighter = await getHighlighter({ theme })
: filenameProp ?? `${id}.mdxts.${finalLanguage}`
let sourceFile: SourceFile

if (['js', 'jsx', 'ts', 'tsx'].includes(finalLanguage)) {
Expand All @@ -128,6 +133,9 @@ export async function Code({
sourceFile.formatText({ indentSize: 2 })
}

unregisterCodeComponent(id)

const highlighter = await getHighlighter({ theme })
const tokens = highlighter(finalValue, finalLanguage, sourceFile, isJsxOnly)

return (
Expand Down
3 changes: 3 additions & 0 deletions mdxts/src/components/Preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import React from 'react'
import { bundle } from '../utils/bundle'
import { ClientComponent } from './ClientComponent'
import { project } from './project'
import { waitUntilAllCodesProcessed } from './state'

export async function Preview({ source }: { source: string }) {
await waitUntilAllCodesProcessed()

const code = await bundle(project, source)

if (!code) {
Expand Down
17 changes: 7 additions & 10 deletions mdxts/src/components/RegisterSourceFile.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
'use client'
import { useLayoutEffect } from 'react'
import { project } from './project'

/** Registers code block source files on the client. */
Expand All @@ -10,17 +9,15 @@ export function RegisterSourceFile({
filename: string
source: string
}) {
useLayoutEffect(() => {
if (!source) {
return
}
if (!source) {
return
}

const sourceFile = project.getSourceFile(filename)
const sourceFile = project.getSourceFile(filename)

if (!sourceFile) {
project.createSourceFile(filename, source)
}
}, [])
if (!sourceFile) {
project.createSourceFile(filename, source)
}

return null
}
2 changes: 0 additions & 2 deletions mdxts/src/components/client/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import React, {
useState,
} from 'react'
import type { Diagnostic, SourceFile } from 'ts-morph'
import { useMdxtsContext } from '../../context'
import { getDiagnosticMessageText } from '../diagnostics'
import type { Highlighter, Theme, Tokens } from '../highlighter'
import { getHighlighter } from '../highlighter'
Expand Down Expand Up @@ -65,7 +64,6 @@ export function Editor({
className,
children,
}: EditorProps & { children?: React.ReactNode }) {
const mdxtsContext = useMdxtsContext()
const filenameId = useId()
const filename = filenameProp || `index-${filenameId.slice(1, -1)}.tsx`
const language = languageMap[languageProp] || languageProp
Expand Down
1 change: 1 addition & 0 deletions mdxts/src/components/project.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Project, ts } from 'ts-morph'
import { readFile } from 'node:fs/promises'

export const project = new Project({
compilerOptions: {
Expand Down
41 changes: 41 additions & 0 deletions mdxts/src/components/state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { signal, effect } from '@preact/signals-core'

const activeCodeComponents = signal<Set<any> | null>(null)

const areAllCodesProcessed = signal(false)

export function registerCodeComponent(id) {
if (activeCodeComponents.value === null) {
activeCodeComponents.value = new Set([id])
} else {
activeCodeComponents.value.add(id)
}
}

export function unregisterCodeComponent(id) {
activeCodeComponents.value.delete(id)
if (activeCodeComponents.value.size === 0) {
areAllCodesProcessed.value = true
}
}

effect(() => {
if (activeCodeComponents.value?.size === 0) {
areAllCodesProcessed.value = true
}
})

export function waitUntilAllCodesProcessed() {
return new Promise((resolve) => {
if (areAllCodesProcessed.value) {
resolve(null)
} else {
const stop = effect(() => {
if (areAllCodesProcessed.value) {
stop()
resolve(null)
}
})
}
})
}
15 changes: 0 additions & 15 deletions mdxts/src/context.tsx

This file was deleted.

9 changes: 0 additions & 9 deletions mdxts/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import React from 'react'
import title from 'title'
import type { ComponentType } from 'react'
import type { CodeBlocks, Headings } from './remark'
import { MdxtsProvider } from './context'

export * from './context'

export type Module = {
Component: ComponentType
Expand All @@ -30,11 +26,6 @@ function parseModule(module, filename: string) {
const slug = pathname.split('/').pop()

return {
// Component: (props) => (
// <MdxtsProvider value={{ codeBlocks }}>
// <Component {...props} />
// </MdxtsProvider>
// ),
Component,
title: module.metadata?.title || module.headings?.[0]?.text || title(slug),
pathname,
Expand Down
13 changes: 12 additions & 1 deletion mdxts/src/utils/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,27 @@ export async function bundle(
...external,
]
const inMemoryFiles = {}
let entryFilePresent = false

project.getSourceFiles().forEach((sourceFile) => {
if (sourceFile.isInNodeModules()) {
return
}
const filePath = sourceFile.getFilePath()
const fileContents = sourceFile.getFullText()

inMemoryFiles[filePath] = fileContents

if (filePath === ensureLeadingSlash(entryPoint)) {
entryFilePresent = true
}
})

if (!entryFilePresent) {
console.error(`mdxts esbuild: Entry point not found for ${entryPoint}`)
return null
}

if (Object.keys(inMemoryFiles).length === 0) {
return null
}
Expand Down Expand Up @@ -103,7 +114,7 @@ export async function bundle(
}

return {
errors: [{ text: `File not found: ${path}` }],
errors: [{ text: `mdxts esbuild: File not found: ${path}` }],
}
})
},
Expand Down
7 changes: 7 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 comment on commit 9606ccd

@vercel
Copy link

@vercel vercel bot commented on 9606ccd Nov 21, 2023

Choose a reason for hiding this comment

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

Please sign in to comment.