How to import markdown(.md) file in typescript
Asked Answered
P

8

35

I am trying to import readme files in typescript but getting "error module not found"

My TS code

import * as readme from "./README.md"; // here i am getting error module not found

I also tried: typings.d.ts

declare module "*.md" {
    const value: any;
    export default value;
}

I found that in typescript 2.0 https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#typescript-20 they have introduced "Wildcard character in module names" using that we can include any extension file.

I just followed example https://hackernoon.com/import-json-into-typescript-8d465beded79 which is for json files I followed same for markdown files but no success.

I am not using webpack and any loader, so I just wanted it only from typescript

Photodynamics answered 21/6, 2017 at 14:0 Comment(3)
markdown is not json, you should probably load it using an actual http request.Spume
I know markdown is not json. I just referred that solution and implemented for markdown filesPhotodynamics
@LokeshDaiya did you found any solution on this already?Stewardson
O
37

For those using React with Typescript:

Create a globals.d.ts file in your root directory (e.g. src/) with the following code:

declare module "*.md";

then import it like this:

import readme from "../README.md" // substitute this path with your README.md file path
Osmanli answered 19/6, 2019 at 2:14 Comment(2)
This did it for me!Scotia
To be clear: 'root directory' refers to the src folder, not the directory above containing the package.jsonAirlift
W
19

Angular 8, TypeScript 3.5.2

Create a file globals.d.ts in the src folder (has to be in src to work), add:

declare module '*.md';

In your component or service import with:

import * as pageMarkdown from 'raw-loader!./page.md';

In this case page.md was at the same level as the component I was importing it into. This worked with serve and build --prod also. Make sure to restart your serve if testing it in live reload mode for the first time.

There's a cleaner process for importing json - see the TypeScript 2.9 Release Documentation

Note: you don't have to name the file globals.d.ts, it could be called anything-at-all.d.ts, but that's the convention

Widmer answered 10/8, 2019 at 18:40 Comment(5)
Thanks for the answer, this works the best for me, without the raw-loader!. I'm working with Nx, and the file had to be in /src folder, I wonder why tho?Tunnel
Yes, Angular 8, but inside a library that i share with multiple appsTunnel
I'm in Angular 13. This works to a point. I get an error: Error: Module not found: Error: Can't resolve 'raw-loader'.Lashawn
Raw loader has never been officially supported on Angular, and no longer works accidentally See github.com/angular/angular-cli/issues/21582. In 2022, if you want to statically import anything thats not html/ts/css you need to add a preprocessing step that wraps it in a json file, and then import that json file.Septilateral
Yes, you can import JSON, because resolveJsonModule is just a tsc option so webpack doesn't know about it. Thats why I said you need to first wrap markdown in a json file. But you can't use webpack's raw-loader because angular 13+ doesn't configure webpack that way.Septilateral
D
4

In your linked example, they are importing JSON, not Markdown. They are able to import the JSON because valid JSON is also valid JavaScript/TypeScript. Markdown is not valid TypeScript and so importing it like that just isn't going to work out of the box like that.

If you want to access the Markdown file at runtime, then make an AJAX request to retrieve its contents. If you really want it built within your JavaScript itself, then you will need to have some sort of build script. You mentioned you aren't using Webpack, but it will be able to achieve what you're looking for by adding a module rule tying /\.md$/ to raw-loader. You'll need to use some sort of equivalent.

Edit:

It seems you learn something new every day. As OP pointed out in comments, TypeScript 2.0 has support for importing non-code resources.

Try the following:

declare module "*!txt" {
    const content: string;
    export default content;
}

import readme from "./README.md!txt";

The readme value should then be a string containing the contents of README.md.

Downstairs answered 22/6, 2017 at 1:31 Comment(7)
If you see in typescript changelog 2.0 github.com/Microsoft/TypeScript/wiki/… they have introduced "Wildcard character in module names"Photodynamics
I stand completely corrected, after looking at that link @LokeshDaiya. It does support non-code imports, you just have to specify the relevant content type and pattern in the module declaration.Downstairs
I tried this solution but got this erro module.js:472 throw err; ^ Error: Cannot find module './README.md!txt'Photodynamics
It's working for me. Are you still putting the declare module statement in your typings.d.ts file and the import statement in your regular *.ts code?Downstairs
My typing.d.ts code declare module "*!txt" { const value: any; export default value; } and TS file code is import readme from "./README.md!txt"; console.log(readme);Photodynamics
I have created a plnkr as well plnkr.co/edit/7qT4Tu?p=preview there also its not workingPhotodynamics
I couldn't get this to work with a new Angular CLI 8.2.0 project, TypeScript 3.5.2Widmer
A
3

For future readers, nothing worked for me with this setup: Vite + React + Typescript

Step 1

What I ended up doing is creating a custom plugin in vite.config.ts to get the raw content from markdown files:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [
    react(),
    {
      name: "markdown-loader",
      transform(code, id) {
        if (id.slice(-3) === ".md") {
          // For .md files, get the raw content
          return `export default ${JSON.stringify(code)};`;
        }
      }
    }
  ]
});

Step 2

Then I just tell typescript to import markdown files correctly in vite-env.d.ts

declare module "*.md";
Apprehend answered 8/9, 2023 at 17:41 Comment(1)
Make sure you don't have this settings in vite.config assetsInclude: ['*/.md'], vitejs.dev/config/shared-options.html#assetsincludeRosen
E
1

@Mitch's answer didn't work for me. Using angular v7, I found I could just use this syntax: import * as documentation from 'raw-loader!./documentation.md';

Eklund answered 16/5, 2019 at 2:56 Comment(0)
C
0

For those using React with Typescript:

find file in src/react-app-env.d.ts file with the following code:

declare module "*.md";

then import it like this:

import readme from "../README.md" // substitute this path with your README.md 
Caril answered 7/1, 2022 at 8:12 Comment(0)
B
0

Apart from Other's answers , I need to add a fetch request as well

So, overall steps are :

Step 1 : create a file markdown.d.ts with the code :

declare module '*.md' {
    const value: string; // markdown is just a string
    export default value;
}

Step 2 : Add this code in your desired .tsx file

import data from '<path_to_md_file>.md'

useEffect(() => {
        fetch(data).then(res => res.text()).then(text => console.log(text))
}, [])
Brythonic answered 19/8, 2023 at 10:26 Comment(0)
B
0

I'm using Nx and I don't want to have to add a file to every project, nor do I want yet another config file in my root or src folders. What works for me is adding a .d.ts file somewhere and adding the file to the "files" entry in my tsconfig. For example:

config/markdown.d.ts:

declare module '*.md';

libs/my-lib/tsconfig.lib.json:

"files": ["../../config/markdown.d.ts"]

Note that I do have to add an entry to the tsconfig "files" section of any project using markdown files but I don't mind that as much as having multiple copies of a .d.ts file. If you're not using Nx, you likely don't have this concern.

You can use this method with other file extensions by adding a separate .d.ts file for each extension, or you could combine them into a common .d.ts, depending on your needs.

Boathouse answered 16/4, 2024 at 19:14 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.