Skip to content

Commit

Permalink
add sort option to createSource
Browse files Browse the repository at this point in the history
  • Loading branch information
souporserious committed Apr 29, 2024
1 parent 7c5df2f commit 7726268
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 12 deletions.
13 changes: 13 additions & 0 deletions .changeset/poor-coins-cross.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'mdxts': minor
---

Adds a new `sort` option to `createSource`:

```tsx
import { createSource } from 'mdxts'

const allPosts = createSource<{ frontMatter: { date: Date } }>('**/*.mdx', {
sort: (a, b) => a.frontMatter.date - b.frontMatter.date,
})
```
7 changes: 7 additions & 0 deletions packages/mdxts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ export function createSource<Type extends { frontMatter: Record<string, any> }>(
* when the source is located in a different workspace than the project rendering it.
*/
outputDirectory?: string | string[]

/**
* A function to sort data items by.
*/
sort?: (a: ModuleData<Type>, b: ModuleData<Type>) => number
} = {}
) {
let allModules = arguments[2] as AllModules
Expand All @@ -126,6 +131,7 @@ export function createSource<Type extends { frontMatter: Record<string, any> }>(
basePathname = '',
sourceDirectory,
outputDirectory,
sort,
} = options || {}
const allData = getAllData<Type>({
allModules,
Expand All @@ -135,6 +141,7 @@ export function createSource<Type extends { frontMatter: Record<string, any> }>(
basePathname,
sourceDirectory,
outputDirectory,
sort,
})
const filteredDataKeys = Object.keys(allData).filter((pathname) => {
const moduleData = allData[pathname]
Expand Down
66 changes: 54 additions & 12 deletions packages/mdxts/src/utils/get-all-data.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Project, InMemoryFileSystemHost } from 'ts-morph'
import { getAllData } from './get-all-data'

const workingDirectory = '/Users/username/Code/mdxts'
const mockModule = () => Promise.resolve({ default: () => {} })

jest.mock('./get-git-metadata', () => ({
getGitMetadata: jest.fn().mockReturnValue({
Expand Down Expand Up @@ -78,14 +79,10 @@ describe('getAllData', () => {
const allData = getAllData({
project,
allModules: {
'/package/components/Button.tsx': () =>
Promise.resolve({ default: () => {} }),
'/package/components/Card.tsx': () =>
Promise.resolve({ default: () => {} }),
'/package/hooks/usePressable.ts': () =>
Promise.resolve({ default: () => {} }),
'/package/hooks/useFocus.ts': () =>
Promise.resolve({ default: () => {} }),
'/package/components/Button.tsx': mockModule,
'/package/components/Card.tsx': mockModule,
'/package/hooks/usePressable.ts': mockModule,
'/package/hooks/useFocus.ts': mockModule,
},
globPattern: 'package/**/*.(ts|tsx)',
baseDirectory: 'package',
Expand Down Expand Up @@ -198,8 +195,8 @@ describe('getAllData', () => {
const allData = getAllData({
project,
allModules: {
[`${workingDirectory}/src/components/Button.examples.tsx`]: () =>
Promise.resolve({ default: () => {} }),
[`${workingDirectory}/src/components/Button.examples.tsx`]:
mockModule,
},
globPattern: `${workingDirectory}/src/**/*.{ts,tsx}`,
baseDirectory: 'src',
Expand Down Expand Up @@ -239,8 +236,7 @@ describe('getAllData', () => {
const allData = getAllData({
project,
allModules: {
[`${workingDirectory}/src/components/Button.examples.tsx`]: () =>
Promise.resolve({ default: () => {} }),
[`${workingDirectory}/src/components/Button.examples.tsx`]: mockModule,
},
globPattern: '*.tsx',
baseDirectory: 'src',
Expand Down Expand Up @@ -283,6 +279,52 @@ describe('getAllData', () => {
exportedTypes.find((type) => type.name === 'PrivateComponent')
).toBeUndefined()
})

it('uses custom sort function if provided', () => {
const fileSystem = new InMemoryFileSystemHost()
const files = [
{
path: 'blog/codemods.mdx',
content: `---\ndate: 2021-10-31\n---\n\n# Codemods`,
},
{
path: 'blog/design-systems.mdx',
content: `---\ndate: 2019-01-01\n---\n\n# Design Systems`,
},
{
path: 'blog/hello-world.mdx',
content: `---\ndate: 2021-04-20\n---\n\n# Hello World`,
},
]

files.forEach((file) => {
fileSystem.writeFileSync(
`${workingDirectory}/src/${file.path}`,
file.content
)
})

const allData = getAllData<{
frontMatter: { date: Date }
}>({
project: new Project({ fileSystem }),
allModules: {
[`${workingDirectory}/src/blog/codemods.mdx`]: mockModule,
[`${workingDirectory}/src/blog/design-systems.mdx`]: mockModule,
[`${workingDirectory}/src/blog/hello-world.mdx`]: mockModule,
},
globPattern: `${workingDirectory}/src/blog/*.mdx`,
baseDirectory: `src`,
sort: (a, b) => {
return a.frontMatter.date.getTime() - b.frontMatter.date.getTime()
},
})
const dataPaths = Object.values(allData).map((data) => data.pathname)

expect(dataPaths[0]).toBe('/blog/design-systems')
expect(dataPaths[1]).toBe('/blog/hello-world')
expect(dataPaths[2]).toBe('/blog/codemods')
})
})

function getDocsData() {
Expand Down
9 changes: 9 additions & 0 deletions packages/mdxts/src/utils/get-all-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export function getAllData<Type extends { frontMatter: Record<string, any> }>({
basePathname = '',
sourceDirectory = 'src',
outputDirectory = 'dist',
sort,
}: {
/** A map of all MDX modules keyed by their pathname. */
allModules: AllModules
Expand All @@ -82,6 +83,9 @@ export function getAllData<Type extends { frontMatter: Record<string, any> }>({

/** The output directory or directories for built files used to calculate package export paths. */
outputDirectory?: string | string[]

/** A custom sort function to use when sorting the modules. */
sort?: (a: ModuleData<Type>, b: ModuleData<Type>) => number
}) {
const typeScriptSourceFiles = /ts(x)?/.test(globPattern)
? project.addSourceFilesAtPaths(globPattern)
Expand Down Expand Up @@ -336,6 +340,11 @@ export function getAllData<Type extends { frontMatter: Record<string, any> }>({
return a[0].localeCompare(b[0])
})

// Sort the data if a custom sort function is provided
if (sort) {
sortedAndFilteredData.sort((a, b) => sort(a[1], b[1]))
}

// Add previous/next data to each module now that they're sorted
sortedAndFilteredData.forEach(([, data], index) => {
const previousData = sortedAndFilteredData[index - 1]
Expand Down

0 comments on commit 7726268

Please sign in to comment.