mirror of
https://github.com/cupcakearmy/markdown-it-import.git
synced 2024-12-21 07:46:25 +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