mirror of
https://github.com/cupcakearmy/markdown-it-import.git
synced 2024-12-22 00:06:27 +00:00
initial push
This commit is contained in:
commit
bc2f6242b2
176
.gitignore
vendored
Normal file
176
.gitignore
vendored
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
|
||||||
|
logs
|
||||||
|
_.log
|
||||||
|
npm-debug.log_
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
|
||||||
|
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
|
||||||
|
pids
|
||||||
|
_.pid
|
||||||
|
_.seed
|
||||||
|
\*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
|
||||||
|
coverage
|
||||||
|
\*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
|
||||||
|
\*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
|
||||||
|
\*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
|
||||||
|
.cache/
|
||||||
|
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# vuepress v2.x temp and cache directory
|
||||||
|
|
||||||
|
.temp
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Docusaurus cache and generated files
|
||||||
|
|
||||||
|
.docusaurus
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.\*
|
||||||
|
|
||||||
|
# IntelliJ based IDEs
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Finder (MacOS) folder config
|
||||||
|
.DS_Store
|
||||||
|
|
23
README.md
Normal file
23
README.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Markdown import plugin
|
||||||
|
|
||||||
|
This is a `markdown-it` plugin to include/import raw files from your filesystem.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- No dependencies
|
||||||
|
- Recursive import
|
||||||
|
- Import whatever file
|
||||||
|
- Customizable RegEx
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @nicco.io/markdown-it-import
|
||||||
|
```
|
||||||
|
|
||||||
|
## Similar works
|
||||||
|
|
||||||
|
There are two very similar plugins, which this one is def. inspired by, however while the one can only import `.md` files, the other cannot select single lines.
|
||||||
|
|
||||||
|
- https://github.com/camelaissani/markdown-it-include
|
||||||
|
- https://github.com/h-hg/markdown-it-import
|
47
package.json
Normal file
47
package.json
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "@nicco.io/markdown-it-import",
|
||||||
|
"version": "1.0.0-rc.0",
|
||||||
|
"description": "Markdown-it plugin which adds the ability to include markdown fragment files.",
|
||||||
|
"keywords": [
|
||||||
|
"markdown-it-plugin",
|
||||||
|
"markdown-it",
|
||||||
|
"markdown",
|
||||||
|
"include"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/cupcakearmy/markdown-it-import"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"author": {
|
||||||
|
"name": "cupcakearmy",
|
||||||
|
"email": "hi@nicco.io",
|
||||||
|
"url": "https://github.com/cupcakearmy"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"types": "./dist/src/index.d.ts",
|
||||||
|
"import": "./dist/index.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"types": "./dist/src/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"./dist"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "rm -rf ./dist && tsc && bun build ./src/index.ts --outfile dist/index.js --target node"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"bun-types": "latest"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
|
}
|
69
src/index.ts
Normal file
69
src/index.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import fs from 'node:fs'
|
||||||
|
import path from 'node:path'
|
||||||
|
import process from 'node:process'
|
||||||
|
|
||||||
|
const defaultOptions = {
|
||||||
|
matcher: /@import\((?<file>.+)\)(\s*?\[(?<range>\d+-\d+)\])?/g,
|
||||||
|
root: process.cwd(),
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Options = Partial<typeof defaultOptions>
|
||||||
|
|
||||||
|
export function importPlugin(md: any, options: Options = {}) {
|
||||||
|
// Options
|
||||||
|
const o = Object.assign(defaultOptions, options)
|
||||||
|
|
||||||
|
// Parser
|
||||||
|
function parse(code: string, alreadyVisited: string[] = []) {
|
||||||
|
if (!o.matcher.global) throw new Error('RegExp must be global')
|
||||||
|
o.matcher.lastIndex = 0 // Reset Regexp
|
||||||
|
const newFiles = []
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const match = o.matcher.exec(code)
|
||||||
|
if (!match) break
|
||||||
|
|
||||||
|
// Get groups
|
||||||
|
const file = match.groups?.['file']?.trim()
|
||||||
|
if (!file) throw new Error('Regexp must expose a named group "file"')
|
||||||
|
const range = match.groups?.['range']
|
||||||
|
?.trim()
|
||||||
|
.split('-')
|
||||||
|
.map((n) => parseInt(n))
|
||||||
|
|
||||||
|
// Load content
|
||||||
|
const filename = path.resolve(o.root, file)
|
||||||
|
if (alreadyVisited.includes(filename)) throw new Error(`cycles are not allowed, already parsed "${filename}"`)
|
||||||
|
newFiles.push(filename)
|
||||||
|
const exists = fs.existsSync(filename)
|
||||||
|
if (!exists) throw new Error(`cannot locate file "${filename}"`)
|
||||||
|
let contents = fs.readFileSync(filename, 'utf-8')
|
||||||
|
|
||||||
|
// Apply line range
|
||||||
|
if (range) {
|
||||||
|
const lines = contents.split('\n')
|
||||||
|
const maxLines = lines.length
|
||||||
|
const start = range[0]
|
||||||
|
const end = range[1]
|
||||||
|
if (start === undefined || end === undefined) throw new Error(`invalid range "${match.groups?.['range']}"`)
|
||||||
|
if (end < start) throw new Error(`end position "${end}" cannot be smaller than start "${start}"`)
|
||||||
|
if (start < 1) throw new Error(`start position "${start}" needs to be at least 1`)
|
||||||
|
if (end > maxLines) throw new Error(`end position "${end}" is higher than the file contents "${maxLines}"`)
|
||||||
|
contents = lines.slice(start - 1, end).join('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursion
|
||||||
|
contents = parse(contents, [...alreadyVisited, ...newFiles])
|
||||||
|
|
||||||
|
// Replace
|
||||||
|
code = code.slice(0, match.index) + contents + code.slice(match.index + match[0].length, code.length)
|
||||||
|
}
|
||||||
|
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mount hook
|
||||||
|
md.core.ruler.before('normalize', 'include', (state: any) => {
|
||||||
|
state.src = parse(state.src)
|
||||||
|
})
|
||||||
|
}
|
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["ESNext"],
|
||||||
|
"module": "esnext",
|
||||||
|
"target": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"composite": true,
|
||||||
|
"strict": true,
|
||||||
|
"types": [
|
||||||
|
"bun-types" // add Bun global
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": ["./src"]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user