diff --git a/.github/workflows/ci.marster.yml b/.github/workflows/ci.marster.yml index 4bb5aec0..a95c43b1 100644 --- a/.github/workflows/ci.marster.yml +++ b/.github/workflows/ci.marster.yml @@ -15,17 +15,21 @@ jobs: registry-url: 'https://registry.npmjs.org' - run: npm install + - run: npm run build:lib - run: npm run coverage - - run: npm run doc + - run: npm run build:doc + - run: npm run bundle + working-directory: core - run: npm run bundle:min + working-directory: core - - run: cp -rp coverage build + - run: cp -rp coverage website/build - name: Create Coverage Badges uses: jaywcjlove/coverage-badges-cli@main with: - output: build/badge.svg + output: website/build/badge.svg - name: Generate Contributors Images uses: jaywcjlove/github-action-contributors@main @@ -52,7 +56,7 @@ jobs: user_email: 'github-actions[bot]@users.noreply.github.com' commit_message: ${{steps.tag_version.outputs.tag}} ${{ github.event.head_commit.message }} github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./build + publish_dir: ./website/build - name: Generate Changelog id: changelog @@ -86,11 +90,13 @@ jobs: - name: package.json info uses: jaywcjlove/github-action-package@main with: - unset: scripts,jest,eslintConfig,engines,browserslist,devDependencies + path: core/package.json + unset: scripts,devDependencies - run: npm publish name: 📦 @uiw/react-markdown-preview publish to NPM continue-on-error: true + working-directory: core env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -109,15 +115,20 @@ jobs: scope: '@uiwjs' - run: npm install + - run: npm run bundle + working-directory: core - run: npm run bundle:min + working-directory: core - name: Modify @uiw/react-markdown-preview => @uiwjs/react-markdown-preview uses: jaywcjlove/github-action-package@main with: + path: core/package.json rename: '@uiwjs/react-markdown-preview' - run: npm publish continue-on-error: true + working-directory: core env: NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} \ No newline at end of file diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 377febdf..2c290da3 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,4 +1,4 @@ -name: Build & Deploy +name: PR on: pull_request: @@ -10,10 +10,14 @@ jobs: - uses: actions/setup-node@v3 with: node-version: 16 + registry-url: 'https://registry.npmjs.org' - run: npm install - - run: npm run build + - run: npm run build:lib - run: npm run coverage - - run: npm run doc + - run: npm run build:doc + - run: npm run bundle - - run: npm run bundle:min \ No newline at end of file + working-directory: core + - run: npm run bundle:min + working-directory: core \ No newline at end of file diff --git a/.kktrc.ts b/.kktrc.ts deleted file mode 100644 index 0eb86cfd..00000000 --- a/.kktrc.ts +++ /dev/null @@ -1,56 +0,0 @@ -import path from 'path'; -import webpack from 'webpack'; -import { LoaderConfOptions, WebpackConfiguration } from 'kkt'; -import lessModules from '@kkt/less-modules'; -import rawModules from '@kkt/raw-modules'; -import scopePluginOptions from '@kkt/scope-plugin-options'; -import pkg from './package.json'; - -export default (conf: WebpackConfiguration, env: 'production' | 'development', options: LoaderConfOptions) => { - conf = lessModules(conf, env, options); - if (options.bundle) { - conf.output!.library = '@uiw/react-markdown-preview'; - conf.externals = { - react: { - root: 'React', - commonjs2: 'react', - commonjs: 'react', - amd: 'react', - }, - }; - } else { - conf = rawModules(conf, env, { ...options }); - conf = scopePluginOptions(conf, env, { - ...options, - allowedFiles: [path.resolve(process.cwd(), 'README.md')], - }); - // Get the project version. - conf.plugins!.push( - new webpack.DefinePlugin({ - VERSION: JSON.stringify(pkg.version), - }), - ); - if (env === 'production') { - conf.output = { ...conf.output, publicPath: './' }; - conf.optimization = { - ...conf.optimization, - splitChunks: { - cacheGroups: { - reactvendor: { - test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, - name: 'react-vendor', - chunks: 'all', - }, - prismjs: { - test: /[\\/]node_modules[\\/](refractor)[\\/]/, - name: 'refractor-vendor', - chunks: 'all', - }, - }, - }, - }; - } - } - - return conf; -}; diff --git a/core/.kktrc.ts b/core/.kktrc.ts new file mode 100644 index 00000000..bada0619 --- /dev/null +++ b/core/.kktrc.ts @@ -0,0 +1,18 @@ +import { LoaderConfOptions, WebpackConfiguration } from 'kkt'; +import lessModules from '@kkt/less-modules'; + +export default (conf: WebpackConfiguration, env: 'production' | 'development', options: LoaderConfOptions) => { + conf = lessModules(conf, env, options); + if (options.bundle) { + conf.output!.library = '@uiw/react-markdown-preview'; + conf.externals = { + react: { + root: 'React', + commonjs2: 'react', + commonjs: 'react', + amd: 'react', + }, + }; + } + return conf; +}; diff --git a/README.md b/core/README.md similarity index 98% rename from README.md rename to core/README.md index 1be5bd8d..d2146775 100644 --- a/README.md +++ b/core/README.md @@ -31,7 +31,8 @@ $ npm install @uiw/react-markdown-preview --save [![Open in CodeSandbox](https://img.shields.io/badge/Open%20in-CodeSandbox-blue?logo=codesandbox)](https://codesandbox.io/embed/react-markdown-preview-co1mj?fontsize=14&hidenavigation=1&theme=dark) -```js test:meta +```jsx mdx:preview +import React from 'react'; import MarkdownPreview from '@uiw/react-markdown-preview'; const source = ` @@ -40,7 +41,7 @@ const source = ` > todo: React component preview markdown text. `; -function Demo() { +export default function Demo() { return ( ) @@ -49,7 +50,8 @@ function Demo() { ## Disable Header links -```js test:meta +```jsx mdx:preview +import React from 'react'; import MarkdownPreview from '@uiw/react-markdown-preview'; const source = ` @@ -60,7 +62,7 @@ const source = ` ### Header 3 `; -function Demo() { +export default function Demo() { return ( ", + "license": "MIT", + "files": [ + "dist", + "lib", + "esm", + "markdown.css", + "src/**/*.{ts,tsx,less}" + ], + "keywords": [ + "react", + "markdown", + "prismjs", + "react-markdown" + ], + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + }, + "dependencies": { + "@babel/runtime": "^7.17.2", + "@uiw/copy-to-clipboard": "~1.0.12", + "react-markdown": "~8.0.0", + "rehype-attr": "~2.1.0", + "rehype-autolink-headings": "~6.1.1", + "rehype-ignore": "^1.0.1", + "rehype-prism-plus": "~1.5.0", + "rehype-raw": "^6.1.1", + "rehype-rewrite": "~3.0.6", + "rehype-slug": "~5.1.0", + "remark-gfm": "~3.0.1", + "unist-util-visit": "^4.1.0" + } +} diff --git a/src/index.tsx b/core/src/index.tsx similarity index 100% rename from src/index.tsx rename to core/src/index.tsx diff --git a/src/nodes/copy.ts b/core/src/nodes/copy.ts similarity index 100% rename from src/nodes/copy.ts rename to core/src/nodes/copy.ts diff --git a/src/nodes/octiconLink.ts b/core/src/nodes/octiconLink.ts similarity index 100% rename from src/nodes/octiconLink.ts rename to core/src/nodes/octiconLink.ts diff --git a/src/plugins/reservedMeta.ts b/core/src/plugins/reservedMeta.ts similarity index 100% rename from src/plugins/reservedMeta.ts rename to core/src/plugins/reservedMeta.ts diff --git a/src/plugins/useCopied.tsx b/core/src/plugins/useCopied.tsx similarity index 100% rename from src/plugins/useCopied.tsx rename to core/src/plugins/useCopied.tsx diff --git a/src/styles/markdown.less b/core/src/styles/markdown.less similarity index 100% rename from src/styles/markdown.less rename to core/src/styles/markdown.less diff --git a/src/tsconfig.json b/core/tsconfig.json similarity index 70% rename from src/tsconfig.json rename to core/tsconfig.json index 7c0aaeb7..10a607f6 100644 --- a/src/tsconfig.json +++ b/core/tsconfig.json @@ -3,5 +3,6 @@ "compilerOptions": { "baseUrl": "./", "noEmit": false - } + }, + "include": ["src", "./.kktrc.ts"] } diff --git a/lerna.json b/lerna.json new file mode 100644 index 00000000..2ed34ef2 --- /dev/null +++ b/lerna.json @@ -0,0 +1,5 @@ +{ + "version": "4.1.9", + "packages": ["core", "website"], + "useWorkspaces": true +} diff --git a/package.json b/package.json index dd91df0d..f35aaf91 100644 --- a/package.json +++ b/package.json @@ -1,45 +1,17 @@ { - "name": "@uiw/react-markdown-preview", - "version": "4.1.9", - "description": "React component preview markdown text in web browser. The minimal amount of CSS to replicate the GitHub Markdown style.", - "homepage": "https://uiwjs.github.io/react-markdown-preview", - "main": "lib/index.js", - "module": "esm/index.js", + "private": true, "scripts": { + "build": "npm run build:lib", + "build:lib": "lerna exec --scope @uiw/* -- npm run build", + "build:doc": "lerna exec --scope website -- npm run build", + "doc": "lerna exec --scope website -- npm run start", + "start": "lerna exec --scope @uiw/* -- npm run watch", "prepare": "npm run build && husky install", - "doc": "kkt build --app-src ./website", - "start": "kkt start --app-src ./website", - "css:build": "compile-less -d src -o esm", - "css:watch": "compile-less -d src -o esm --watch", - "css:build:dist": "compile-less -d src --combine markdown.css --rm-global", - "bundle": "ncc build src/index.tsx --target web --filename markdown", - "bundle:min": "ncc build src/index.tsx --target web --filename markdown --minify", - "watch": "tsbb watch & npm run css:watch", - "build": "tsbb build && npm run css:build && npm run css:build:dist", "prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'", "pretty-quick": "pretty-quick --staged", "test": "tsbb test --env=jsdom", "coverage": "tsbb test --env=jsdom --coverage" }, - "repository": { - "type": "git", - "url": "https://github.com/uiwjs/react-markdown-preview.git" - }, - "author": "kenny wang ", - "license": "MIT", - "files": [ - "dist", - "lib", - "esm", - "markdown.css", - "src/**/*.{ts,tsx,less}" - ], - "keywords": [ - "react", - "markdown", - "prismjs", - "react-markdown" - ], "jest": { "coverageReporters": [ "lcov", @@ -49,47 +21,18 @@ "/node_modules/?!(.*)" ] }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - }, - "dependencies": { - "@babel/runtime": "^7.17.2", - "@uiw/copy-to-clipboard": "~1.0.12", - "react-markdown": "~8.0.0", - "rehype-attr": "~2.1.0", - "rehype-autolink-headings": "~6.1.1", - "rehype-ignore": "^1.0.1", - "rehype-prism-plus": "~1.5.0", - "rehype-raw": "^6.1.1", - "rehype-rewrite": "~3.0.6", - "rehype-slug": "~5.1.0", - "remark-gfm": "~3.0.1", - "unist-util-visit": "^4.1.0" - }, "devDependencies": { - "@kkt/less-modules": "~7.2.0", - "@kkt/ncc": "^1.0.13", - "@kkt/raw-modules": "~7.2.0", - "@kkt/scope-plugin-options": "~7.2.0", + "@testing-library/react": "^14.0.0", "@types/react": "~18.0.9", "@types/react-dom": "~18.0.3", "@types/react-test-renderer": "~18.0.0", - "@uiw/react-back-to-top": "^1.2.0", - "@uiw/react-codesandbox": "~1.1.4", - "@uiw/react-github-corners": "~1.5.3", - "@uiw/react-shields": "~1.1.2", - "@uiw/reset.css": "~1.0.5", - "@wcj/dark-mode": "~1.0.9", + "@kkt/ncc": "^1.0.15", "compile-less-cli": "~1.8.11", "husky": "~8.0.0", - "kkt": "~7.2.0", "prettier": "^2.7.1", "pretty-quick": "~3.1.3", - "react": "~18.2.0", - "react-dom": "~18.2.0", - "react-test-renderer": "~18.2.0", - "tsbb": "~3.7.0" + "lerna": "^6.1.0", + "tsbb": "^3.7.9" }, "eslintConfig": { "extends": "react-app" @@ -97,16 +40,8 @@ "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } + "workspaces": [ + "core", + "website" + ] } diff --git a/test/index.test.tsx b/test/index.test.tsx index 3e9bd211..59395482 100644 --- a/test/index.test.tsx +++ b/test/index.test.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef } from 'react'; import TestRenderer from 'react-test-renderer'; import { render } from '@testing-library/react'; -import MarkdownPreview, { MarkdownPreviewRef } from '../src'; +import MarkdownPreview, { MarkdownPreviewRef } from '../core/src'; it('Should output a TestRenderer', async () => { const component = TestRenderer.create(); diff --git a/tsconfig.json b/tsconfig.json index 2fcfccda..59cc958e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,5 +17,5 @@ "noFallthroughCasesInSwitch": true, "noEmit": true }, - "include": ["website", "test", "src"] + "include": ["test"] } diff --git a/website/.kktrc.ts b/website/.kktrc.ts new file mode 100644 index 00000000..4c0dda02 --- /dev/null +++ b/website/.kktrc.ts @@ -0,0 +1,45 @@ +import path from 'path'; +import webpack from 'webpack'; +import { LoaderConfOptions, WebpackConfiguration } from 'kkt'; +import lessModules from '@kkt/less-modules'; +import scopePluginOptions from '@kkt/scope-plugin-options'; +import pkg from '@uiw/react-markdown-preview/package.json'; +import { mdCodeModulesLoader } from 'markdown-react-code-preview-loader'; + +export default (conf: WebpackConfiguration, env: 'production' | 'development', options: LoaderConfOptions) => { + conf = lessModules(conf, env, options); + conf = scopePluginOptions(conf, env, { + ...options, + allowedFiles: [path.resolve(process.cwd(), 'README.md')], + }); + // Get the project version. + conf.plugins!.push( + new webpack.DefinePlugin({ + VERSION: JSON.stringify(pkg.version), + }), + ); + conf = mdCodeModulesLoader(conf); + // https://github.com/kktjs/kkt/issues/336#issue-1097660932 + conf.module!.exprContextCritical = false; + if (env === 'production') { + conf.output = { ...conf.output, publicPath: './' }; + conf.optimization = { + ...conf.optimization, + splitChunks: { + cacheGroups: { + reactvendor: { + test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, + name: 'react-vendor', + chunks: 'all', + }, + prismjs: { + test: /[\\/]node_modules[\\/](refractor)[\\/]/, + name: 'refractor-vendor', + chunks: 'all', + }, + }, + }, + }; + } + return conf; +}; diff --git a/website/README.md b/website/README.md new file mode 100644 index 00000000..e69de29b diff --git a/website/package.json b/website/package.json new file mode 100644 index 00000000..3dacff3f --- /dev/null +++ b/website/package.json @@ -0,0 +1,49 @@ +{ + "name": "website", + "version": "4.1.9", + "private": true, + "scripts": { + "build": "kkt build", + "start": "kkt start" + }, + "dependencies": { + "@uiw/react-markdown-preview": "4.1.9", + "@uiw/react-back-to-top": "^1.2.0", + "@uiw/react-codesandbox": "~1.1.4", + "@uiw/react-github-corners": "~1.5.3", + "@uiw/react-shields": "~1.1.2", + "@uiw/reset.css": "~1.0.5", + "@wcj/dark-mode": "~1.0.9", + "react": "~18.2.0", + "react-code-preview-layout": "~2.1.0", + "react-dom": "~18.2.0", + "react-router-dom": "^6.8.1" + }, + "devDependencies": { + "@kkt/less-modules": "^7.4.7", + "@kkt/scope-plugin-options": "^7.4.7", + "kkt": "^7.4.7", + "markdown-react-code-preview-loader": "^2.1.4", + "prettier": "^2.8.4", + "pretty-quick": "^3.1.3", + "react-test-renderer": "^18.2.0" + }, + "eslintConfig": { + "extends": "react-app" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/public/bundle.html b/website/public/bundle.html similarity index 100% rename from public/bundle.html rename to website/public/bundle.html diff --git a/public/favicon.ico b/website/public/favicon.ico similarity index 100% rename from public/favicon.ico rename to website/public/favicon.ico diff --git a/public/index.html b/website/public/index.html similarity index 100% rename from public/index.html rename to website/public/index.html diff --git a/website/App.css b/website/src/App.css similarity index 97% rename from website/App.css rename to website/src/App.css index db2a94b9..ea18f2f6 100644 --- a/website/App.css +++ b/website/src/App.css @@ -58,7 +58,6 @@ dark-mode { .App-markdown { text-align: left; - font-size: calc(10px + 2vmin); padding: 16px; border-radius: 5px; } diff --git a/website/App.tsx b/website/src/App.tsx similarity index 92% rename from website/App.tsx rename to website/src/App.tsx index 3836fc5d..443497b4 100644 --- a/website/App.tsx +++ b/website/src/App.tsx @@ -3,11 +3,11 @@ import GitHubCorners from '@uiw/react-github-corners'; import Github from '@uiw/react-shields/esm/github'; import Npm from '@uiw/react-shields/esm/npm'; import BackToUp from '@uiw/react-back-to-top'; +import MarkdownPreview from '@uiw/react-markdown-preview'; import '@wcj/dark-mode'; import logo from './logo.svg'; +import { Preview } from './preview'; import './App.css'; -import MarkdownPreview from '../'; -import MDStr from '../README.md'; let val = 1; @@ -39,7 +39,7 @@ const App = () => { /> - /, '')} /> +
diff --git a/website/index.tsx b/website/src/index.tsx similarity index 100% rename from website/index.tsx rename to website/src/index.tsx diff --git a/website/logo.svg b/website/src/logo.svg similarity index 100% rename from website/logo.svg rename to website/src/logo.svg diff --git a/website/src/preview/index.tsx b/website/src/preview/index.tsx new file mode 100644 index 00000000..8effea3a --- /dev/null +++ b/website/src/preview/index.tsx @@ -0,0 +1,73 @@ +import MarkdownPreview from '@uiw/react-markdown-preview'; +import MDStr from '@uiw/react-markdown-preview/README.md'; +import CodeLayout from 'react-code-preview-layout'; +import { Root, Element, RootContent } from 'hast'; +import { getMetaId, isMeta, getURLParameters } from 'markdown-react-code-preview-loader'; + +const getBooleanValue = (param: Record, field: string, defaultValue: boolean) => { + if (Reflect.has(param, field)) { + const newValue = Reflect.get(param, field); + if (newValue === 'true') { + return true; + } + if (newValue === 'false') { + return false; + } + } + return defaultValue; +}; + +export const Preview = () => { + return ( + { + if (node.type === 'element' && node.tagName === 'pre' && node.children[0].data?.meta) { + const meta = node.children[0].data?.meta as string; + if (isMeta(meta)) { + node.tagName = 'div'; + if (!node.properties) { + node.properties = {}; + } + node.properties!['data-md'] = meta; + node.properties!['data-meta'] = 'preview'; + } + } + }} + components={{ + div: ({ node, ...props }) => { + const { 'data-meta': meta, 'data-md': metaData } = props as any; + if (meta === 'preview') { + const line = node.position?.start.line; + const metaId = getMetaId(meta) || String(line); + const Child = MDStr.components[metaId]; + if (metaId && typeof Child === 'function') { + const code = MDStr.data[metaId].value || ''; + const param = getURLParameters(metaData); + return ( + )} />} + text={code} + > + + + ); + } + } + return
; + }, + }} + /> + ); +}; diff --git a/website/react-app-env.d.ts b/website/src/react-app-env.d.ts similarity index 73% rename from website/react-app-env.d.ts rename to website/src/react-app-env.d.ts index e88adf09..b3339d63 100644 --- a/website/react-app-env.d.ts +++ b/website/src/react-app-env.d.ts @@ -9,7 +9,9 @@ declare module '*.less' { const src: string; export default src; } + declare module '*.md' { - const src: string; + import { CodeBlockData } from 'markdown-react-code-preview-loader'; + const src: CodeBlockData; export default src; } diff --git a/website/tsconfig.json b/website/tsconfig.json new file mode 100644 index 00000000..ff1060d0 --- /dev/null +++ b/website/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../tsconfig", + "compilerOptions": { + "baseUrl": "./" + }, + "include": ["src", "./.kktrc.ts"] +}