nuxt / content

The file-based CMS for your Nuxt application, powered by Markdown and Vue components.
https://content.nuxt.com
MIT License
3.13k stars 627 forks source link

Accessing Raw Content #2490

Open platform-kit opened 10 months ago

platform-kit commented 10 months ago

Is your feature request related to a problem? Please describe

One would expect that the ability to access the raw content of a markdown file (or any file for that matter), would be included, but I can't seem to find it documented anywhere. If this already exists, I apologize.

I am building a CMS that works with the markdown files, so I need to be able to access and parse the original, raw content, not just at build time but once the site is deployed.

Describe the solution you'd like

A simple function that can be invoked at query time like the following:

const blogPosts = await queryContent('blog').find().withRaw()

Describe alternatives you've considered

Transformers and hooks etc are not an intuitive way to do this.

ogios commented 6 months ago

same, i need raw text to process. and i can not overwrite transformer for .md, error:

[nitro 11:07:55 AM]  ERROR  RollupError: virtual:#content/virtual/transformers (2:7): Identifier "markdown_transform_ts_rr4xXXXpBA" has already been declared

1: import markdown_transform_ts_rr4xXXXpBA from "/home/ogios/work/temp/nuxt-content-test/markdown_transform.ts";
2: import markdown_transform_ts_rr4xXXXpBA from "/home/ogios/work/temp/nuxt-content-test/markdown_transform.ts";
          ^
3: export const transformers = [markdown_transform_ts_rr4xXXXpBA, markdown_transform_ts_rr4xXXXpBA]
4: export const getParser = (ext) => transformers.find(p => ext.match(new RegExp(p.extensions.join("|"),  "i")) && p.parse)
// filename: markdown_transform.ts
import { defineTransformer } from "@nuxt/content/transformers";
export default defineTransformer({
  name: "md-transformer",
  extensions: [".md"],
  parse(_id, rawContent) {
    return {
      _id,
      body: rawContent,
    };
  },
});

// filename: index.mjs
import { resolve } from "path";
import { defineNuxtModule } from "@nuxt/kit";
export default defineNuxtModule({
  setup(_options, nuxt) {
    nuxt.options.nitro.externals = nuxt.options.nitro.externals || {};
    nuxt.options.nitro.externals.inline =
      nuxt.options.nitro.externals.inline || [];
    nuxt.options.nitro.externals.inline.push(resolve("."));
    // @ts-ignore
    nuxt.hook("content:context", (contentContext) => {
      contentContext.transformers.push(resolve("./markdown_transform.ts"));
    });
  },
});
ogios commented 6 months ago

@platform-kit i manage to do it by overwrite nuxt content markdown transformer, the error before may be caused by cache, this is the minimal example repo: https://github.com/ogios/nuxt-content-raw-markdown-test

xarthurx commented 6 months ago

Same! When using Nuxt Content I always have issues when using the remark system. Sometimes the footnote doesn't work, sometimes the hightlight.

After spending days working on it, I decided to go back the markdown-it as it is more mature.

Then I realise that I cannot get the raw content with queryContent ?!

Nuxt Content works great for providing a default server/api setup to all markdown files, but it should allow users to access the raw content of the file for more customizations...

yamiOnEstrogen commented 5 months ago

Bumping this as this is really necessary

sorry

xarthurx commented 4 months ago

bump again.

ogios commented 4 months ago

it is a breaking change, may not be in recent update before a major version release i think?

can you make it work in the way of the example i demontrated? @xarthurx

xarthurx commented 4 months ago

it is a breaking change, may not be in recent update before a major version release i think?

can you make it work in the way of the example i demontrated? @xarthurx

Didn't try. I'm currently using markdown-it to do the job. But it is a bit tricky to correctly set it up.

xarthurx commented 4 months ago

it is a breaking change, may not be in recent update before a major version release i think?

can you make it work in the way of the example i demontrated? @xarthurx

I tested your approach, and it works. However, if I use the transformer, it will totally modify the way queryContent works and I need to re-write a lot of code of my current website.

Is there a way to just add a object body / rawBody to the original object parsed by queryContent? There isn't so much material online that I can learn from.

xarthurx commented 4 months ago

it is a breaking change, may not be in recent update before a major version release i think? can you make it work in the way of the example i demontrated? @xarthurx

I tested your approach, and it works. However, if I use the transformer, it will totally modify the way queryContent works and I need to re-write a lot of code of my current website.

Is there a way to just add a object body / rawBody to the original object parsed by queryContent? There isn't so much material online that I can learn from.

OK, I finally resolve this problem by doing this:

import { defineTransformer } from "@nuxt/content/transformers";
import markdownParser from "@nuxt/content/transformers/markdown";
import matter from "gray-matter";

export default defineTransformer({
    name: "md-transformer",
    extensions: [".md"],

    parse: async (_id: string, rawContent: string) => {

        const parsedContent = await markdownParser.parse(_id, rawContent);
        const { content, data } = matter(rawContent);

        return {
            ...parsedContent,
            rawContent: content,
        };
    },
});

It will attach a rawContent to the end of the parsed file, without overwriting it.

github-actions[bot] commented 2 months ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 30 days.

xarthurx commented 2 months ago

reactivate.

ManUtopiK commented 2 months ago

Hey ! An alternative is to expose the content files to the public, and access them by a simple fetch. Here is the process :

// Expose content to public
nuxt.hook('nitro:config', (nitroConfig) => {
      nitroConfig.publicAssets ||= []
      nitroConfig.publicAssets.push({
        dir: resolvePath('content'),
        baseURL: '/',
        maxAge: 60 * 60 * 24 * 365, // 1 year
      })
    })

Now you get a page as usual with https://example.com/my-file and can add .md extension to your url https://example.com/my-file.md to get the raw markdown. It also works for sub path and any kind of files : .yaml, .json ...

So you can fetch it in your component with $fetch() to access raw content.

codywakeford commented 2 months ago

I found adding a string to the headers works ok.

---
title: hello
description: world
raw: 'this is a sentence

# This is a header'
---

<-- Content here. -->

This allows you to access the raw content fine in the query. A bit scrappy but it works.

xarthurx commented 1 week ago

bump again.