Skip to content

Commit

Permalink
feat: initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
norskeld committed Jan 8, 2022
1 parent 133a062 commit 0de0b8e
Show file tree
Hide file tree
Showing 16 changed files with 1,781 additions and 37 deletions.
816 changes: 813 additions & 3 deletions package-lock.json

Large diffs are not rendered by default.

53 changes: 41 additions & 12 deletions package.json
@@ -1,36 +1,55 @@
{
"name": "@nrsk/shikigami",
"version": "1.0.0",
"description": "Syntax highlighting with shiki for markdown-it.",
"main": "./dist/index.js",
"description": "Opinionated syntax highlighting with shiki for markdown-it.",
"sideEffects": false,
"main": "./index.cjs",
"module": "./index.mjs",
"types": "./index.d.ts",
"exports": {
".": {
"import": "./index.mjs",
"require": "./index.cjs",
"types": "./index.d.ts"
}
},
"files": [
"dist"
"CHANGELOG.md",
"*.d.ts",
"*.cjs*",
"*.mjs*"
],
"engines": {
"node": ">=14.17.0"
},
"scripts": {
"build": "tsc",
"build:watch": "tsc -w",
"build": "npm run build:types && npm run build:rollup",
"build:types": "tsc -p tsconfig.types.json",
"build:rollup": "node --require tsm scripts/compile.ts",
"fmt:prettier": "prettier --write \"**/*.{js,ts,json}\"",
"fmt:lint": "eslint --fix --ext .js,.ts .",
"postbuild": "rimraf dist/types",
"postversion": "node --require tsm ../scripts/release.ts restore",
"prebuild": "rimraf dist",
"prepare": "husky install",
"prepare": "echo husky install",
"prerelease": "node --require tsm scripts/release.ts prepare",
"release": "npx semantic-release",
"release:dry": "npx semantic-release --dry-run",
"test": "jest",
"test:coverage": "jest --coverage",
"test:watch": "jest --watch"
"test:coverage": "jest --coverage --run-in-band",
"test:watch": "jest --watch --max-workers=50%"
},
"repository": {
"type": "git",
"url": "git+https://github.com/norskeld/shikigami.git"
},
"keywords": [
"typescript",
"markdown-it-plugin",
"markdown-it",
"plugin",
"shiki"
"markdown",
"shiki",
"syntax-highlighting",
"typescript"
],
"author": {
"name": "Vladislav Mamon",
Expand All @@ -41,12 +60,20 @@
"url": "https://github.com/norskeld/shikigami/issues"
},
"homepage": "https://github.com/norskeld/shikigami#readme",
"peerDependencies": {
"markdown-it": "^12.3.0"
},
"dependencies": {
"shiki": "^0.10.0"
},
"devDependencies": {
"@commitlint/cli": "^16.0.1",
"@nrsk/config-conventional": "^1.0.0",
"@rollup/plugin-typescript": "^8.3.0",
"@semantic-release/changelog": "^6.0.1",
"@semantic-release/git": "^10.0.1",
"@types/jest": "^27.4.0",
"@types/markdown-it": "^12.2.3",
"@typescript-eslint/eslint-plugin": "^5.8.1",
"@typescript-eslint/parser": "^5.8.1",
"eslint": "^8.6.0",
Expand All @@ -56,9 +83,11 @@
"lint-staged": "^12.1.4",
"prettier": "^2.5.1",
"rimraf": "^3.0.2",
"rollup": "^2.62.0",
"rollup-plugin-dts": "^4.1.0",
"semantic-release": "^18.0.1",
"ts-jest": "^27.1.2",
"ts-node": "^10.4.0",
"tsm": "^2.2.1",
"typescript": "^4.5.4"
},
"commitlint": {
Expand Down
83 changes: 83 additions & 0 deletions scripts/compile.ts
@@ -0,0 +1,83 @@
import { rollup, InputOptions, OutputOptions } from 'rollup'
import typescript from '@rollup/plugin-typescript'
import dts from 'rollup-plugin-dts'

interface BundleOptions {
input: InputOptions
output: Array<OutputOptions>
}

function createBundleOptions(entry: string, destination: string): BundleOptions {
return {
input: {
external: ['shiki', 'markdown-it'],
input: `${entry}.ts`,
plugins: [
typescript({
module: 'esnext',
tsconfig: 'tsconfig.rollup.json'
})
]
},
output: [
{
file: `${destination}.cjs`,
format: 'cjs',
sourcemap: true,
globals: {
lodash: 'lodash'
}
},
{
file: `${destination}.mjs`,
format: 'esm',
sourcemap: true
}
]
}
}

function createTypesBundleOptions(entry: string, destination: string): BundleOptions {
return {
input: {
input: `${entry}.d.ts`,
plugins: [dts()]
},
output: [
{
file: `${destination}.d.ts`,
format: 'esm'
}
]
}
}

async function compile() {
const options = [
// Roll-up sources.
createBundleOptions('src/index', 'dist/index'),

// Roll-up already existing d.ts created by `tsc`.
createTypesBundleOptions('dist/types/index', 'dist/index')
]

try {
await Promise.all(
options.map(async ({ input, output }) => {
const bundle = await rollup(input)

for (const out of output) {
await bundle.generate(out)
await bundle.write(out)
}

await bundle.close()
})
)
} catch (error) {
console.error(error)
process.exit(1)
}
}

compile()
100 changes: 100 additions & 0 deletions scripts/release.ts
@@ -0,0 +1,100 @@
import { access, copyFile } from 'fs/promises'
import { constants } from 'fs'
import { resolve } from 'path'

interface Success {
kind: 'success'
message: string
}

interface Failure {
kind: 'failure'
reason: string
}

type Result = Success | Failure
type Actions = Record<string, () => Promise<Result>>

async function actions(actions: Actions): Promise<Result> {
const [passed] = process.argv.slice(2)
const resolved = actions[passed]

if (resolved) {
return await resolved()
}

return {
kind: 'failure',
reason: `Action '${passed}' is not defined.`
}
}

async function run(result: Result) {
switch (result.kind) {
case 'success': {
console.log(result.message)
return
}

case 'failure': {
console.error(result.reason)
process.exit(1)
}
}
}

async function main() {
const cwd = process.cwd()

await run(
await actions({
/** This should be called in `prerelease`. */
async prepare() {
try {
// Just double-check for `dist` directory.
await access(`${cwd}/package.json`, constants.F_OK)

// Copy necessary files.
await copyFile(`${cwd}/package.json`, `${cwd}/dist/package.json`)
await copyFile(`${cwd}/CHANGELOG.md`, `${cwd}/dist/CHANGELOG.md`)
await copyFile(`${cwd}/README.md`, `${cwd}/dist/README.md`)
await copyFile(`${cwd}/LICENSE`, `${cwd}/dist/LICENSE`)

// This is kinda needed for local publishes to `verdaccio`, so I do not accidentally
// publish my experiments to the actual `npm` registry.
await copyFile(`${cwd}/.npmrc`, `${cwd}/dist/.npmrc`)

return {
kind: 'success',
message: 'Successfully prepared files for a release.'
}
} catch (error) {
return {
kind: 'failure',
reason: (error as Error).message
}
}
},

/** This should be called in `postversion`. Here we actually are inside the `dist`. */
async restore() {
try {
// Copy back.
await copyFile(`${cwd}/package.json`, resolve(cwd, '..', 'package.json'))

return {
kind: 'success',
message: 'Successfully restored `package.json`.'
}
} catch (error) {
return {
kind: 'failure',
reason: (error as Error).message
}
}
}
})
)
}

main()
14 changes: 14 additions & 0 deletions src/builder.ts
@@ -0,0 +1,14 @@
type SetterFn = (value: string) => void
type GetterFn = (separator?: string) => string

type Builder = [getter: GetterFn, setter: SetterFn]

/** Simple string builder. */
export function useBuilder(initial: Array<string> = []): Builder {
const strings = Array.from(initial)

const setterFn: SetterFn = (value: string) => strings.push(value)
const getterFn: GetterFn = (separator = '') => strings.join(separator)

return [getterFn, setterFn]
}
15 changes: 0 additions & 15 deletions src/index.spec.ts

This file was deleted.

5 changes: 2 additions & 3 deletions src/index.ts
@@ -1,3 +1,2 @@
export async function identity<T>(value: T): Promise<T> {
return value
}
export type { ShikigamiOptions } from './shikigami.options'
export { shikigami, loadTheme } from './shikigami'
73 changes: 73 additions & 0 deletions src/renderer.options.ts
@@ -0,0 +1,73 @@
import { merge } from './utils'

export interface LineOption {
/** Line number. **1-based**. */
line: number

/** Line's classes list. */
classes: Array<string>
}

export type HtmlRendererDefaultOptions = Required<HtmlRendererOptions>

export interface HtmlRendererOptions {
/**
* Set to `true` to render language specified in a fenced code block.
*
* @defaultValue false
*/
withLanguage?: boolean

/**
* Set to `true` to render line numbers.
*
* @defaultValue false
*/
withLineNumbers?: boolean

/**
* Use this to assign classes for specific lines.
*
* @defaultValue []
*/
lineOptions?: Array<LineOption>

/**
* Use this to change rendered language (if enabled).
*
* @defaultValue ''
*/
languageId?: string

/**
* Use this to override text color for unstyled tokens.
*
* @defaultValue "#000"
*/
foreground?: string

/**
* Use this to override background color for the whole `<pre>` block.
*
* @defaultValue "#fff"
*/
background?: string
}

export function mergeOptions(
defaults: HtmlRendererDefaultOptions,
user: HtmlRendererOptions
): HtmlRendererDefaultOptions {
return merge(defaults, user)
}

export function getDefaultOptions(): HtmlRendererDefaultOptions {
return {
withLanguage: false,
withLineNumbers: false,
languageId: '',
lineOptions: [],
foreground: '#000',
background: '#fff'
}
}

0 comments on commit 0de0b8e

Please sign in to comment.