contentlayerdev / contentlayer

Contentlayer turns your content into data - making it super easy to import MD(X) and CMS content in your app
https://www.contentlayer.dev
MIT License
3.14k stars 199 forks source link

Support SvelteKit #170

Open seancdavis opened 2 years ago

seancdavis commented 2 years ago

Add your vote for SvelteKit support by clicking the 👍 emoji below.

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

nisarhassan12 commented 11 months ago

Thanks to all the contributors for their great work on this project. I was wondering how many more votes is it gonna need before it gets worked on?

arnvgh commented 10 months ago

Sveltekit support will be much appreciated 😄 !!

seancdavis commented 10 months ago

Tight integration with SvelteKit is not currently planned. However, you can still use Contentlayer with SvelteKit.

I've done this with other frameworks that aren't officially supported. It usually looks like this:

  1. Use a tool like concurrently to run contentlayer dev and the dev server in parallel.
  2. Run contentlayer build prior to running the framework's build command.
git-no commented 10 months ago

I could create a working demo of a Sveltekit - Contentlayer - MDX integration with simple and little code.

For those interested here is the git repositiory: sveltekit-contentlayer-example

I hope this supports the Contentlayer project and helps to enlarge the Svelte / Contentlayer community.

Ahidada commented 9 months ago

I could create a working demo of a Sveltekit - Contentlayer - MDX integration with simple and little code.

For those interested here is the git repositiory: sveltekit-contentlayer-example

I hope this supports the Contentlayer project and helps to enlarge the Svelte / Contentlayer community.

Can parse md, but SvelteKit doesn't have enough support for mdx

git-no commented 7 months ago

@Ahidada

Can parse md, but SvelteKit doesn't have enough support for mdx

Quite an allegation. Maybe you can elaborate what support you are missing.

johan8834 commented 3 months ago

yes please

ap0nia commented 2 months ago

I could create a working demo of a Sveltekit - Contentlayer - MDX integration with simple and little code.

For those interested here is the git repositiory: sveltekit-contentlayer-example

I hope this supports the Contentlayer project and helps to enlarge the Svelte / Contentlayer community.

Given a repository that's prepared to import/render the contentlayer content, would a Vite plugin work? All it does is invoke contentlayer build and contentlayer dev during the Vite lifecycle.

// vite.config.js
// @ts-check

import * as core from '@contentlayer/core'
import { fs, errorToString } from '@contentlayer/utils'
import { E, OT, pipe, S, T } from '@contentlayer/utils/effect'
import { sveltekit } from '@sveltejs/kit/vite'
import { defineConfig } from 'vite'

export default defineConfig({
  plugins: [
    sveltekit(),
    contentlayer(),
  ],
})

/**
 * @typedef {{
 * clearCache?: boolean
 * configPath?: string | undefined
 * verbose?: boolean
 * isDev?: boolean
 * contentDirPath?: string
 * generatedDirPath?: string
 * }} ContentlayerOptions
 */

/**
 * Contentlayer Vite plugin.
 * @param {ContentlayerOptions?} options
 * @returns {import('vite').Plugin}
 */
function contentlayer(options = null) {
  const resolvedOptions = {
    generatedDirPath: '.contentlayer',
    contentDirPath: 'content',
    clearCache: false,
    configPath: undefined,
    verbose: false,
    isDev: true,
    ...options,
  }

  /**
   * @type {ReturnType<typeof startContentlayerDevelopmentWatch>}
   */
  let contentLayerWatcher

  /**
   * @see https://github.com/contentlayerdev/contentlayer/blob/main/packages/%40contentlayer/cli/src/commands/DevCommand.ts
   */
  const startContentlayerDevelopmentWatch = async () => {
    /**
     * Promise that runs in the background while the server is running.
     * TODO: terminate gracefully when the server is stopped.
     */
    pipe(
      pipe(
        S.fromEffect(
          T.gen(function*($) {
            if (resolvedOptions.clearCache) {
              const cwd = yield* $(core.getCwd)
              const artifactsDir = core.ArtifactsDir.getDirPath({ cwd })
              yield* $(fs.rm(artifactsDir, { recursive: true, force: true }))
              yield* $(T.log('Cache cleared successfully'))
            }
          }),
        ),
        S.chain(() => core.getConfigWatch({ configPath: resolvedOptions.configPath })),
        S.tapSkipFirstRight(() =>
          T.log(`Contentlayer config change detected. Updating type definitions and data...`),
        ),
        S.tapRight((config) =>
          config.source.options.disableImportAliasWarning ? T.unit : T.fork(core.validateTsconfig),
        ),
        S.chainSwitchMapEitherRight((config) =>
          core.generateDotpkgStream({
            config,
            verbose: resolvedOptions.verbose,
            isDev: resolvedOptions.isDev,
          }),
        ),
        S.tap(E.fold((error) => T.log(errorToString(error)), core.logGenerateInfo)),
        OT.withStreamSpan('@contentlayer/cli/commands/DevCommand:stream'),
        S.runDrain,
        OT.withSpan('@contentlayer/cli/commands/DevCommand:executeSafe'),
      ),
      core.runMain({
        tracingServiceName: 'contentlayer-cli',
        verbose: resolvedOptions.verbose || process.env['CL_DEBUG'] !== undefined,
      }),
    )
  }

  /**
   * @see https://github.com/contentlayerdev/contentlayer/blob/main/packages/%40contentlayer/cli/src/commands/BuildCommand.ts
   */
  const buildContentlayer = async () => {
    return pipe(
      pipe(
        T.gen(function*($) {
          if (resolvedOptions.clearCache) {
            const cwd = yield* $(core.getCwd)
            const artifactsDir = core.ArtifactsDir.getDirPath({ cwd })
            yield* $(fs.rm(artifactsDir, { recursive: true, force: true }))
            yield* $(T.log('Cache cleared successfully'))
          }
        }),
        T.chain(() => core.getConfig({ configPath: resolvedOptions.configPath })),
        T.tap((config) =>
          config.source.options.disableImportAliasWarning ? T.unit : T.fork(core.validateTsconfig),
        ),
        T.chain((config) => core.generateDotpkg({ config, verbose: resolvedOptions.verbose })),
        T.tap(core.logGenerateInfo),
        OT.withSpan('@contentlayer/cli/commands/BuildCommand:executeSafe'),
      ),
      core.runMain({
        tracingServiceName: 'contentlayer-cli',
        verbose: resolvedOptions.verbose || process.env['CL_DEBUG'] !== undefined,
      }),
    )
  }

  return {
    name: 'vite-plugin-contentlayer',

    /**
     * Add additional directories to the Vite server's file serving list.
     */
    async config() {
      return {
        server: {
          fs: {
            allow: [resolvedOptions.contentDirPath, resolvedOptions.generatedDirPath],
          },
        },
      }
    },

    /**
     * When development server starts, start contentlayer development watch.
     */
    async configureServer() {
      contentLayerWatcher = startContentlayerDevelopmentWatch()
    },

    /**
     * When build starts, build contentlayer.
     */
    async buildStart() {
      await buildContentlayer()
    },

    /**
     * TODO: When build ends, stop the contentlayer development watch.
     */
    async buildEnd() {
      if (contentLayerWatcher !== undefined) {
        contentLayerWatcher
      }
    },
  }
}