diff --git a/README.md b/README.md
index a9690b935b26e7bb6c9a60515d22993a50e32760..c5a550b575bc86e05f86d15aa37101af1138ff03 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,18 @@
# osui
-#### 介绍
+## 介绍
osui是基于开源组件库(例如antd),封装的一套业务性质的组件
-#### 软件架构
+## 软件架构
采用monorepo模式,
快速了解monorepo基本用法:https://zhuanlan.zhihu.com/p/71385053
可以参考这篇文章快速了解monorepo的基本用法
+## 使用说明
-#### 安装教程
-
-#### 使用说明
-
-
-#### 参与贡献
+## 参与贡献
1. Fork 本仓库 (可以不fork直接拉分支)
2. 新建 feat_xxx 或者 fix_xxx 分支,对分支名尽量和 convertional commits(见下面)保持一致
@@ -35,5 +31,55 @@ osui是基于开源组件库(例如antd),封装的一套业务性质的组
最短操作路径: yarn commit -> 选feat或者fix -> 回车跳过 -> 输入你干了啥概述(字数限制) -> 回车跳过 -> 回车(没有breaking change的话) -> 回车
+熟练之后,可以用git commit 提交符合conventional commits的message。
+
4. 新建 Pull Request
+## 开发说明
+
+### 准备工作
+
+1. clone 代码库到本地
+2. 执行:
+
+```
+yarn
+```
+
+### 如何开发一个新组件
+
+#### 创建新组件
+
+执行
+
+```
+yarn new-component 组件名
+```
+
+该命令会在`packages/ui/`目录下创建`组件名`目录,并将`package.json`中的`name`改为`@osui/组件名`
+
+(模板在`templates/component`下, 也可以手动复制到`packages/ui`目录下,但要记得替换`组件名`相关内容)
+
+**注意:**
+
+组件名小写字母,多个词用`-`分割,例如`app-layout`
+
+##### `yarn new-component` 不好用?
+
+手动方式:
+
+1. 把`templates/component`复制到`packages/ui`目录下,重命名成新建组件
+2. 将`package.json`和`README.md`中的`{componentName}`换成新命名的组件
+3. 将`{CapComponentName}`换成大写字母开头,camelcase的形式
+
+#### 开发新组件
+
+组件开发代码在组件文件夹`src/`目录下。开发时可以通过storybook进行调试:
+
+1. 在`stories/`目录下创建`index.stories.tsx`
+2. 从`src`中引入组件, 仿照`alert`
+3. `yarn`
+4. `yarn storybook`
+
+示例: 参考`alert`组件
+
diff --git a/package.json b/package.json
index 20f080456e3cd46b329bd200f755c0aca94aa5a2..504f5bedcb6b785875207e4729999e95451d452e 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,8 @@
"storybook": "start-storybook -p 8777 -s public",
"prepack": "yarn build",
"version": "lerna version --conventional-commits --no-push",
- "commit": "git-cz"
+ "commit": "git-cz",
+ "new-component": "sh scripts/new-component.sh"
},
"devDependencies": {
"@commitlint/cli": "^9.1.1",
diff --git a/packages/ui/alert/README.md b/packages/ui/alert/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..41fbd482e9a6ea1591302774367001d970059cb1
--- /dev/null
+++ b/packages/ui/alert/README.md
@@ -0,0 +1,30 @@
+# @osui/alert
+
+## 安装说明
+
+### 方式一
+
+单包使用
+
+```
+yarn install @osui/alert
+```
+
+```
+import Alert from '@osui/alert'
+```
+
+### 方式二
+
+从 `@osui/alert` 统一引入
+
+```
+yarn install @osui/alert
+```
+
+```
+import {Alert} from '@osui/alert';
+```
+
+
+
diff --git a/packages/ui/alert/stories/index.stories.tsx b/packages/ui/alert/stories/index.stories.tsx
index 8aa058aa32b445f9cfc5d45b32a626e2cf5a0c50..b3f38414006682e6ad59b2cc6a30bcd15d16ac58 100644
--- a/packages/ui/alert/stories/index.stories.tsx
+++ b/packages/ui/alert/stories/index.stories.tsx
@@ -1,7 +1,6 @@
import * as React from 'react';
-import {Alert} from 'antd';
import {CheckCircleFilled, InfoCircleFilled} from '@ant-design/icons';
-import '@osui/theme/dist/theme/vars.css';
+import Alert from '../src';
export default {
title: 'OSUI-Alert',
diff --git a/packages/ui/docs/stories/markdown/index.stories.tsx b/packages/ui/docs/stories/markdown/index.stories.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..72449469d2e1eb8c5f8b5c3964f5c035bbfc021e
--- /dev/null
+++ b/packages/ui/docs/stories/markdown/index.stories.tsx
@@ -0,0 +1,24 @@
+import * as React from 'react';
+import Markdown from '@osui/markdown';
+
+export default {
+ title: 'OSUI-Markdown',
+};
+
+const content = `
+# Writing template strings in Markdown
+
+## Writing template strings in Markdown
+
+adsfasdfasdf
+
+asdfasdf
+
+\`\`\`jsx
+
+\`\`\`
+`;
+
+export const Demo = () => (
+
+);
diff --git a/packages/ui/markdown/.eslintrc.js b/packages/ui/markdown/.eslintrc.js
new file mode 100644
index 0000000000000000000000000000000000000000..5928ca1d6479ff7d0abd9fdec53a30df884f15f2
--- /dev/null
+++ b/packages/ui/markdown/.eslintrc.js
@@ -0,0 +1,7 @@
+module.exports = {
+ extends: require.resolve('@reskript/config-lint/config/eslint'),
+ rules: {
+ 'react/jsx-uses-react': 'error',
+ },
+ root: true,
+};
diff --git a/packages/ui/markdown/.storybook/main.js b/packages/ui/markdown/.storybook/main.js
new file mode 100644
index 0000000000000000000000000000000000000000..34ac840230e8a5f5d2437f06788470d20b106cc0
--- /dev/null
+++ b/packages/ui/markdown/.storybook/main.js
@@ -0,0 +1,73 @@
+const {getBabelConfig} = require('@reskript/config-babel');
+const {loaders} = require('@reskript/config-webpack');
+const path = require('path');
+
+const loaderOptions = {
+ cwd: process.cwd(),
+ srcDirectory: 'src',
+ projectSettings: {
+ build: {
+ extractCSS: false,
+ styleResources: [
+ require.resolve('@osui/theme/dist/antd-vars-patch.less'),
+ require.resolve('@osui/theme/dist/less-functions-overrides.less'),
+ ],
+ },
+ },
+};
+
+module.exports = {
+ stories: [
+ '../stories/**/*.stories.[tj]s{,x}',
+ '../stories/**/*.stories.mdx'
+ ],
+ addons: [
+ {
+ name: '@storybook/addon-docs',
+ options: {
+ configureJSX: true,
+ babelOptions: {},
+ sourceLoaderOptions: null,
+ },
+ },
+ '@storybook/addon-storysource', // https://github.com/storybookjs/storybook/tree/master/addons/storysource
+ '@storybook/addon-a11y/register', // https://github.com/storybookjs/storybook/tree/master/addons/a11y
+ '@storybook/addon-viewport/register', // https://github.com/storybookjs/storybook/tree/master/addons/viewport
+ ],
+ webpackFinal: async (config) => {
+ config.module.rules.push({
+ test: /\.(js|jsx|ts|tsx)$/,
+ use: [
+ {
+ loader: 'babel-loader',
+ options: getBabelConfig(),
+ },
+ ],
+ });
+ config.module.rules.push({
+ test: /\.less$/,
+ loaders: [
+ loaders.style(loaderOptions),
+ loaders.css(loaderOptions),
+ loaders.less(loaderOptions),
+ loaders.styleResources(loaderOptions),
+ ],
+ });
+ // 如果使用css modules 请打开这个,并按需匹配css modules 文件
+ // 这个同时打开了classnames loader, 可以用 import c from 'xxx.less'
+ // config.module.rules.push({
+ // test: /\.less$/,
+ // loaders: [
+ // loaders.classNames(),
+ // loaders.style(loaderOptions),
+ // loaders.cssModules(loaderOptions),
+ // loaders.less(loaderOptions),
+ // loaders.styleResources(loaderOptions),
+ // ],
+ // });
+
+ config.resolve.extensions.push('.ts', '.tsx');
+ config.resolve.alias['@'] = path.resolve(__dirname, '../src');
+ return config;
+ },
+};
diff --git a/packages/ui/markdown/.storybook/preview.js b/packages/ui/markdown/.storybook/preview.js
new file mode 100644
index 0000000000000000000000000000000000000000..de3eb1e46842de317cc4cbaf9e48573e91cfbf79
--- /dev/null
+++ b/packages/ui/markdown/.storybook/preview.js
@@ -0,0 +1,16 @@
+import {addParameters} from '@storybook/react';
+import {DocsPage, DocsContainer} from '@storybook/addon-docs/blocks';
+import {INITIAL_VIEWPORTS} from '@storybook/addon-viewport';
+import '@osui/theme/dist/theme/vars.css';
+
+addParameters({
+ docs: {
+ container: DocsContainer,
+ page: DocsPage,
+ },
+ viewport: {
+ viewports: {
+ ...INITIAL_VIEWPORTS
+ }
+ },
+});
diff --git a/packages/ui/markdown/README.md b/packages/ui/markdown/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..df00cdf4b79df936a71d4f293c93532fbb3d6e60
--- /dev/null
+++ b/packages/ui/markdown/README.md
@@ -0,0 +1,30 @@
+# @osui/markdown
+
+## 安装说明
+
+### 方式一
+
+单包使用
+
+```
+yarn install @osui/markdown
+```
+
+```
+import Markdown from '@osui/markdown'
+```
+
+### 方式二
+
+从 `@osui/markdown` 统一引入
+
+```
+yarn install @osui/markdown
+```
+
+```
+import {Markdown} from '@osui/markdown';
+```
+
+
+
diff --git a/packages/ui/markdown/babel.config.js b/packages/ui/markdown/babel.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..d222841daa0815ccea18188ceb097da34d13aad9
--- /dev/null
+++ b/packages/ui/markdown/babel.config.js
@@ -0,0 +1,11 @@
+const {getTransformBabelConfig} = require('@reskript/config-babel');
+
+const options = {
+ browserSupport: {},
+ usage: 'build',
+ mode: 'production',
+ polyfill: false,
+ hostType: 'library',
+};
+
+module.exports = getTransformBabelConfig(options);
diff --git a/packages/ui/markdown/package.json b/packages/ui/markdown/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..009c7e715a7a05d36b0c21c563922be24bf299a0
--- /dev/null
+++ b/packages/ui/markdown/package.json
@@ -0,0 +1,65 @@
+{
+ "name": "@osui/markdown",
+ "version": "0.1.0",
+ "description": "",
+ "main": "dist/index.js",
+ "scripts": {
+ "lint": "skr lint",
+ "build": "sh scripts/build.sh",
+ "storybook": "start-storybook -p 8700",
+ "clean": "rm -rf node_modules && rm -rf dist",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "sideEffects": [
+ "dist/*.less"
+ ],
+ "devDependencies": {
+ "@babel/cli": "^7.10.5",
+ "@reskript/cli": "^0.9.0",
+ "@reskript/cli-lint": "^0.9.9",
+ "@reskript/config-babel": "^0.9.0",
+ "@reskript/config-lint": "^0.12.3",
+ "@reskript/config-webpack": "^0.11.2",
+ "@storybook/addon-a11y": "^5.3.19",
+ "@storybook/addon-docs": "^5.3.19",
+ "@storybook/addon-storysource": "^5.3.19",
+ "@storybook/addon-viewport": "^5.3.19",
+ "@storybook/addons": "^5.3.19",
+ "@storybook/client-api": "^5.3.19",
+ "@storybook/react": "^5.3.19",
+ "@types/classnames": "^2.2.10",
+ "@types/react-dom": "^16.9.8",
+ "antd": "^4.4.0",
+ "babel-loader": "^8.1.0",
+ "cpy-cli": "^3.1.1",
+ "husky": "^4.2.5",
+ "prop-types": "^15.7.2",
+ "react": "^16.13.1",
+ "react-dom": "^16.13.1",
+ "react-is": "^16.13.1",
+ "typescript": "^3.9.6"
+ },
+ "peerDependencies": {
+ "antd": ">=4.4.0",
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://gitee.com/yuxuanhuo/osui/tree/master"
+ },
+ "author": "huoyuxuan",
+ "license": "MIT",
+ "husky": {
+ "hooks": {
+ "pre-commit": "skr lint ./src"
+ }
+ },
+ "dependencies": {
+ "classnames": "^2.2.6",
+ "github-markdown-css": "^4.0.0",
+ "remark": "^12.0.1",
+ "remark-html": "^12.0.0",
+ "unist-util-visit": "^2.0.3"
+ }
+}
diff --git a/packages/ui/markdown/scripts/build.sh b/packages/ui/markdown/scripts/build.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f1cf5724ccdec601e43fab14da4e8f9f80d5765c
--- /dev/null
+++ b/packages/ui/markdown/scripts/build.sh
@@ -0,0 +1,18 @@
+# export PATH=$NODEJS_BIN_LATEST:$YARN_BIN_LATEST:$PATH
+
+echo "node $(node -v)"
+echo "npm $(npm -v)"
+echo "yarn $(yarn -v)"
+
+rm -rf dist
+
+yarn install --production=false
+# yarn test
+
+$(npm bin)/cpy '**/*' '!**/*.ts' '!**/*.tsx' '!**/*.js' '!**/*.jsx' ../tmp/ --cwd=src/ --parents
+$(npm bin)/tsc
+$(npm bin)/babel tmp --out-dir dist --ignore "src/**/*.test.js" --copy-files --source-maps
+
+rm -rf tmp
+
+echo "build success"
diff --git a/packages/ui/markdown/src/Markdown.tsx b/packages/ui/markdown/src/Markdown.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a240b643560a45f052f796238a45e096e7a38f6b
--- /dev/null
+++ b/packages/ui/markdown/src/Markdown.tsx
@@ -0,0 +1,56 @@
+/**
+ * @file Markdown 组件
+ * @author zhangguoqing02
+ */
+import * as React from 'react';
+import classNames from 'classnames';
+import remark from 'remark';
+import htmlPlugin from 'remark-html';
+import 'github-markdown-css/github-markdown.css';
+import './index.less';
+
+const clsPrefix = 'osui-markdown';
+
+interface Props {
+ content?: string;
+ className?: string;
+ plugins?: any[];
+}
+
+const getHtml = (content: string, plugins: any[]) => {
+ let processor = remark();
+ plugins.forEach(plugin => {
+ processor = processor.use(plugin);
+ });
+ return processor.use(htmlPlugin).processSync(content).toString();
+};
+
+const Markdown: React.FC = ({content = '', className, plugins = []}) => {
+ /**
+ * NOTE 这里有 xss 攻击的可能性,但是以下两种方案均不成立
+ * 1. const html = xss(...);
+ * 不成立的地方在于 - [ ] 会首先转译成 ,然后 xss 会把它 stringify
+ * 2. const html = ...processSync(xss(content))...
+ * 不成立的地方在于 markdown 的 code block ``` 中的内容会被首先转译,导致 > 转译为 >
+ * 这个问题首先是由安全部在效率云发现,而 iCode 作为内部系统,安全性较高一些
+ * 故首先 revert 至不处理 xss
+ * 可能的解决方案如下
+ * 利用 remark 找到会被解析为 html 的代码,对这些 html 运行 xss,然后重新 stringify 并得到 html
+ * 相关的 icafe 卡片
+ * @see http://newicafe.baidu.com/issue/icode-12580/show?cid=5
+ * @see http://newicafe.baidu.com/issue/icode-11691/show?cid=5
+ */
+
+ const html = getHtml(content, plugins);
+
+ return (
+
+ );
+};
+
+export default Markdown;
diff --git a/packages/ui/markdown/src/index.less b/packages/ui/markdown/src/index.less
new file mode 100644
index 0000000000000000000000000000000000000000..ed389ebf881189efc68cfd470712debb4ca47557
--- /dev/null
+++ b/packages/ui/markdown/src/index.less
@@ -0,0 +1,34 @@
+@osui-markdown-class-prefix: osui-alert;
+.@{osui-markdown-class-prefix} {
+ .main {
+ padding: 20px;
+
+ ul {
+ list-style: disc;
+ }
+
+ ol {
+ list-style: decimal;
+ }
+
+ ul,
+ ol {
+ ul {
+ list-style: circle;
+ }
+
+ ol {
+ list-style: lower-latin;
+ }
+ }
+
+ strong {
+ font-weight: 900;
+ }
+
+ // 覆盖 prism 中的样式
+ pre code::selection {
+ background-color: var(--ee-theme-primary-color);
+ }
+ }
+}
diff --git a/packages/ui/markdown/src/index.tsx b/packages/ui/markdown/src/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a240b643560a45f052f796238a45e096e7a38f6b
--- /dev/null
+++ b/packages/ui/markdown/src/index.tsx
@@ -0,0 +1,56 @@
+/**
+ * @file Markdown 组件
+ * @author zhangguoqing02
+ */
+import * as React from 'react';
+import classNames from 'classnames';
+import remark from 'remark';
+import htmlPlugin from 'remark-html';
+import 'github-markdown-css/github-markdown.css';
+import './index.less';
+
+const clsPrefix = 'osui-markdown';
+
+interface Props {
+ content?: string;
+ className?: string;
+ plugins?: any[];
+}
+
+const getHtml = (content: string, plugins: any[]) => {
+ let processor = remark();
+ plugins.forEach(plugin => {
+ processor = processor.use(plugin);
+ });
+ return processor.use(htmlPlugin).processSync(content).toString();
+};
+
+const Markdown: React.FC = ({content = '', className, plugins = []}) => {
+ /**
+ * NOTE 这里有 xss 攻击的可能性,但是以下两种方案均不成立
+ * 1. const html = xss(...);
+ * 不成立的地方在于 - [ ] 会首先转译成 ,然后 xss 会把它 stringify
+ * 2. const html = ...processSync(xss(content))...
+ * 不成立的地方在于 markdown 的 code block ``` 中的内容会被首先转译,导致 > 转译为 >
+ * 这个问题首先是由安全部在效率云发现,而 iCode 作为内部系统,安全性较高一些
+ * 故首先 revert 至不处理 xss
+ * 可能的解决方案如下
+ * 利用 remark 找到会被解析为 html 的代码,对这些 html 运行 xss,然后重新 stringify 并得到 html
+ * 相关的 icafe 卡片
+ * @see http://newicafe.baidu.com/issue/icode-12580/show?cid=5
+ * @see http://newicafe.baidu.com/issue/icode-11691/show?cid=5
+ */
+
+ const html = getHtml(content, plugins);
+
+ return (
+
+ );
+};
+
+export default Markdown;
diff --git a/packages/ui/markdown/src/plugins/common.ts b/packages/ui/markdown/src/plugins/common.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6885908019d37a4bfc8cf61ab4a9fac20f18e117
--- /dev/null
+++ b/packages/ui/markdown/src/plugins/common.ts
@@ -0,0 +1,13 @@
+/**
+ * @file 公用代码
+ * @author zhangguoqing02
+ */
+
+// 匹配非协议名开头的字符串,说明此字符串不用做转换
+// `(?!p)` 是零宽负向先行断言,表示接下来的字符串都不与 p 匹配
+// 此处如 `http://`, `ftp://` 或者 `//` 开头的字符串均不能匹配
+export const REGEXP_FILE_PATH = /^(?!(\w+:)?\/\/)/;
+
+// 通过 url 中 `:` 前面的部分,判断当前是文件位置还是文件夹位置
+// 如 `xxx/blob/` 就是文件位置,而 `xxx/tree/` 就是文件夹位置
+export const REGEXP_IS_FILE = /\/(?:blob|edit|create)\/[^/]+:/;
diff --git a/packages/ui/markdown/src/plugins/createImagePlugin.ts b/packages/ui/markdown/src/plugins/createImagePlugin.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ea3d605ee2821525edf097421d86752ae0427088
--- /dev/null
+++ b/packages/ui/markdown/src/plugins/createImagePlugin.ts
@@ -0,0 +1,46 @@
+/**
+ * @file remark image 相对路径替换插件
+ * @author zhangguoqing02
+ */
+import {dirname, join} from 'path';
+import {Node} from 'unist';
+import visit from 'unist-util-visit';
+import {REGEXP_FILE_PATH, REGEXP_IS_FILE} from './common';
+
+interface Params {
+ name: string;
+ ref: string;
+ path?: string;
+}
+
+const getICodeRawFilePath = (relativePath: string, params: Params) => {
+ const {name, ref, path = ''} = params;
+ const targetPath = (() => {
+ if (relativePath.startsWith('/')) {
+ return relativePath.slice(1);
+ }
+ else {
+ const isFile = path && REGEXP_IS_FILE.test(window.location.pathname);
+
+ // 如果 relativePath 不以 / 开头,说明它是相对路径
+ return join(
+ isFile ? dirname(path) : path,
+ relativePath
+ );
+ }
+ })();
+
+ return `/rest/files/blob/get/fileraw?repo=${name}&commit=${ref}&path=${targetPath}`;
+};
+
+const createImagePlugin = (params: Params) => () => (tree: Node) => {
+ visit(tree, 'image', node => {
+ const url = node.url as string;
+ if (REGEXP_FILE_PATH.test(url)) {
+ // eslint-disable-next-line no-param-reassign
+ node.url = getICodeRawFilePath(url, params);
+ }
+ });
+};
+
+export default createImagePlugin;
diff --git a/packages/ui/markdown/src/plugins/createLinkPlugin.ts b/packages/ui/markdown/src/plugins/createLinkPlugin.ts
new file mode 100644
index 0000000000000000000000000000000000000000..895fad97fe590f22094a04811de3c2c6c8c4f6bc
--- /dev/null
+++ b/packages/ui/markdown/src/plugins/createLinkPlugin.ts
@@ -0,0 +1,47 @@
+/**
+ * @file remark link 相对路径替换插件
+ * @author zhangguoqing02
+ */
+import {dirname, join} from 'path';
+import {Node} from 'unist';
+import visit from 'unist-util-visit';
+import {REGEXP_FILE_PATH, REGEXP_IS_FILE} from './common';
+
+interface Params {
+ name: string;
+ ref: string;
+ path?: string;
+}
+
+// 根据相对路径获取兼容 iCode 的绝对路径
+const getICodePath = (relativePath: string, params: Params) => {
+ const {name, ref, path = ''} = params;
+ const targetPrefix = `/repos/${name}/blob/${ref}:`;
+
+ // 如果 relativePath 是 / 开头表示的绝对路径,如:/src/index.js,
+ // 则直接返回从仓库根目录开始的文件路径
+ if (relativePath.startsWith('/')) {
+ return targetPrefix + relativePath.slice(1);
+ }
+
+ const isFile = path && REGEXP_IS_FILE.test(window.location.pathname);
+ const targetPath = join(
+ isFile ? dirname(path) : path,
+ relativePath
+ );
+
+ return targetPrefix + targetPath;
+};
+
+// 传入 Router 中的参数 params
+const createLinkPlugin = (params: Params) => () => (tree: Node) => {
+ visit(tree, 'link', node => {
+ const url = node.url as string;
+ if (REGEXP_FILE_PATH.test(url)) {
+ // eslint-disable-next-line no-param-reassign
+ node.url = getICodePath(url, params);
+ }
+ });
+};
+
+export default createLinkPlugin;
diff --git a/packages/ui/markdown/src/plugins/index.ts b/packages/ui/markdown/src/plugins/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a1549b859941375369b383be5eefa468f13f18ef
--- /dev/null
+++ b/packages/ui/markdown/src/plugins/index.ts
@@ -0,0 +1,7 @@
+/**
+ * @file 导出 remark 的插件
+ * @author zhangguoqing02
+ */
+
+export {default as createImagePlugin} from './createImagePlugin';
+export {default as createLinkPlugin} from './createLinkPlugin';
diff --git a/packages/ui/markdown/stories/index.stories.tsx b/packages/ui/markdown/stories/index.stories.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..d740904dd081dfab7205b269392577bda39727dd
--- /dev/null
+++ b/packages/ui/markdown/stories/index.stories.tsx
@@ -0,0 +1,26 @@
+import * as React from 'react';
+import Markdown from '../src/Markdown';
+
+export default {
+ title: 'OSUI-Markdown',
+};
+
+const content = `
+# Writing template strings in Markdown
+
+## Writing template strings in Markdown
+
+adsfasdfasdf
+
+asdfasdf
+
+\`\`\`jsx
+
+\`\`\`
+`;
+
+export const Demo = () => (
+
+
+
+);
diff --git a/packages/ui/markdown/tsconfig.json b/packages/ui/markdown/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..3a24a511df9639581444c76e59ea1b775c5d8ea6
--- /dev/null
+++ b/packages/ui/markdown/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../../tsconfig.json",
+ "compilerOptions": {
+ "rootDir": "./src",
+ "outDir": "./tmp"
+ },
+ "include": ["src"]
+}
diff --git a/packages/ui/ui/.eslintrc.js b/packages/ui/ui/.eslintrc.js
new file mode 100644
index 0000000000000000000000000000000000000000..5928ca1d6479ff7d0abd9fdec53a30df884f15f2
--- /dev/null
+++ b/packages/ui/ui/.eslintrc.js
@@ -0,0 +1,7 @@
+module.exports = {
+ extends: require.resolve('@reskript/config-lint/config/eslint'),
+ rules: {
+ 'react/jsx-uses-react': 'error',
+ },
+ root: true,
+};
diff --git a/packages/ui/ui/README.md b/packages/ui/ui/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..7a4de3b26eba9099add44f4ab87c47a716bb01d8
--- /dev/null
+++ b/packages/ui/ui/README.md
@@ -0,0 +1,17 @@
+# @osui/ui
+
+## 安装说明
+
+```
+yarn install @osui/ui
+```
+
+named import 组件
+
+```
+import {Alert} from '@osui/ui';
+```
+
+## 说明
+
+在发包之前手动build,不与yarn build统一build,因为依赖可能还没build完
diff --git a/packages/ui/ui/package.json b/packages/ui/ui/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..0073704ecb8a5f8b70340145a951a9b678262257
--- /dev/null
+++ b/packages/ui/ui/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@osui/ui",
+ "version": "0.1.0",
+ "description": "",
+ "main": "dist/index.js",
+ "module": "dist/index.js",
+ "scripts": {
+ "lint": "skr lint",
+ "build": "echi \"release manual build\"",
+ "build-all": "sh scripts/build.sh",
+ "storybook": "start-storybook -p 8700",
+ "clean": "rm -rf node_modules && rm -rf dist",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "sideEffects": [
+ "dist/**/*.less"
+ ],
+ "devDependencies": {
+ "cpy-cli": "^3.1.1",
+ "typescript": "^3.9.6"
+ },
+ "peerDependencies": {
+ "antd": ">=4.4.0",
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://gitee.com/yuxuanhuo/osui/tree/master"
+ },
+ "author": "huoyuxuan",
+ "license": "MIT",
+ "husky": {
+ "hooks": {
+ "pre-commit": "skr lint ./src"
+ }
+ },
+ "dependencies": {
+ }
+}
diff --git a/packages/ui/ui/scripts/build.sh b/packages/ui/ui/scripts/build.sh
new file mode 100644
index 0000000000000000000000000000000000000000..c339490ea343404bc6a38ee0cec08f6c9f5d24be
--- /dev/null
+++ b/packages/ui/ui/scripts/build.sh
@@ -0,0 +1,20 @@
+# export PATH=$NODEJS_BIN_LATEST:$YARN_BIN_LATEST:$PATH
+
+rm -rf dist
+
+ROOT=../ # 在packages/ui/ui 目录下执行本脚本, ROOT目录应该是packages/ui/ui
+EXCLUDE_FOLDER='docs$|ui$|\/$' # docs, ui, / 目录都要过滤掉
+
+# 注意:需要提前build好各个包
+# 把各个包的dist目录复制到 dist
+find $ROOT -maxdepth 1 -type d | grep -v -E $EXCLUDE_FOLDER | while IFS= read -r d; do
+ COMPONENT=`echo $d | sed 's/..\///'`
+ echo "building $COMPONENT"
+ mkdir -p dist/$COMPONENT
+ cp -R $d/dist/* dist/$COMPONENT
+done
+
+# build index
+$(npm bin)/tsc
+
+echo "build success"
diff --git a/packages/ui/ui/src/index.ts b/packages/ui/ui/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d5ce82ccc8661e6f6121fdbee3602b7242dbe9a5
--- /dev/null
+++ b/packages/ui/ui/src/index.ts
@@ -0,0 +1,2 @@
+// @ts-nocheck
+export {default as Alert} from './alert';
diff --git a/packages/ui/ui/tsconfig.json b/packages/ui/ui/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..e9eb0ce1d1a35ba7af80a9090535f5bb516ad9a2
--- /dev/null
+++ b/packages/ui/ui/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../../tsconfig.json",
+ "compilerOptions": {
+ "rootDir": "./src",
+ "outDir": "./dist"
+ },
+ "include": ["src"]
+}
diff --git a/scripts/new-component.sh b/scripts/new-component.sh
new file mode 100644
index 0000000000000000000000000000000000000000..05735b403357aa1b78bced5739d8934620617307
--- /dev/null
+++ b/scripts/new-component.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# @author huoyuxuan
+# 用于根据模板创建组件
+set -e
+
+COMPONENT_NAME=$1
+
+echo "create $COMPONENT_NAME"
+
+# 复制template
+cp -R templates/component packages/ui/$COMPONENT_NAME
+
+# 把组件包名替换
+find packages/ui/$COMPONENT_NAME -type f -exec sed -i "s/{componentName}/${COMPONENT_NAME}/g" {} \;
+
+# 把组件名替换成第一个字母大写, 把 - 换成大小写
+CAP_COMPONENT_NAME=`echo ${COMPONENT_NAME^} | sed -E 's/-(.)/\U\1/g'`
+echo $CAP_COMPONENT_NAME
+find packages/ui/$COMPONENT_NAME -type f -exec sed -i "s/{CapComponentName}/${CAP_COMPONENT_NAME}/g" {} \;
+
+
diff --git a/templates/component/README.md b/templates/component/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4ec47dab183563f867f7782b97362218419c31c8
--- /dev/null
+++ b/templates/component/README.md
@@ -0,0 +1,30 @@
+# @osui/{componentName}
+
+## 安装说明
+
+### 方式一
+
+单包使用
+
+```
+yarn install @osui/{componentName}
+```
+
+```
+import {CapComponentName} from '@osui/{componentName}'
+```
+
+### 方式二
+
+从 `@osui/ui` 统一引入
+
+```
+yarn install @osui/ui
+```
+
+```
+import {{CapComponentName}} from '@osui/ui';
+```
+
+
+
diff --git a/templates/component/package.json b/templates/component/package.json
index 1dfede0d108d73a85fdd7af92f9665dd28c2cc1f..9a288319c161fefd23c2ec7b7cd265990515ee20 100644
--- a/templates/component/package.json
+++ b/templates/component/package.json
@@ -1,5 +1,5 @@
{
- "name": "@osui/alert",
+ "name": "@osui/{componentName}",
"version": "0.1.0",
"description": "",
"main": "dist/index.js",
diff --git a/yarn.lock b/yarn.lock
index c0b9fcb8a8444493c59e161467ac2b4b74bb399f..e099dd58b1d81eeac27e7213fc10b8ec4cf54ccb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7833,6 +7833,11 @@ gitconfiglocal@^1.0.0:
dependencies:
ini "^1.3.2"
+github-markdown-css@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.npm.taobao.org/github-markdown-css/download/github-markdown-css-4.0.0.tgz#be9f4caf7a389228d4c368336260ffc909061f35"
+ integrity sha1-vp9Mr3o4kijUw2gzYmD/yQkGHzU=
+
github-slugger@^1.0.0:
version "1.3.0"
resolved "http://registry.npm.baidu-int.com/github-slugger/-/github-slugger-1.3.0.tgz#9bd0a95c5efdfc46005e82a906ef8e2a059124c9"
@@ -8207,6 +8212,11 @@ hast-util-from-parse5@^6.0.0:
vfile "^4.0.0"
web-namespaces "^1.0.0"
+hast-util-is-element@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.npm.taobao.org/hast-util-is-element/download/hast-util-is-element-1.0.4.tgz#059090a05cc02e275df1ad02caf8cb422fcd2e02"
+ integrity sha1-BZCQoFzALidd8a0CyvjLQi/NLgI=
+
hast-util-parse-selector@^2.0.0:
version "2.2.4"
resolved "http://registry.npm.baidu-int.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.4.tgz#60c99d0b519e12ab4ed32e58f150ec3f61ed1974"
@@ -8228,6 +8238,29 @@ hast-util-raw@6.0.0:
xtend "^4.0.0"
zwitch "^1.0.0"
+hast-util-sanitize@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.npm.taobao.org/hast-util-sanitize/download/hast-util-sanitize-3.0.0.tgz#4cdc26b2991b3bf90ee74b5c932e14d907549312"
+ integrity sha1-TNwmspkbO/kO50tcky4U2QdUkxI=
+ dependencies:
+ xtend "^4.0.0"
+
+hast-util-to-html@^7.0.0:
+ version "7.1.1"
+ resolved "https://registry.npm.taobao.org/hast-util-to-html/download/hast-util-to-html-7.1.1.tgz#39818b8bbfcb8eaa87846a120b3875487b27d094"
+ integrity sha1-OYGLi7/LjqqHhGoSCzh1SHsn0JQ=
+ dependencies:
+ ccount "^1.0.0"
+ comma-separated-tokens "^1.0.0"
+ hast-util-is-element "^1.0.0"
+ hast-util-whitespace "^1.0.0"
+ html-void-elements "^1.0.0"
+ property-information "^5.0.0"
+ space-separated-tokens "^1.0.0"
+ stringify-entities "^3.0.1"
+ unist-util-is "^4.0.0"
+ xtend "^4.0.0"
+
hast-util-to-parse5@^6.0.0:
version "6.0.0"
resolved "http://registry.npm.baidu-int.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479"
@@ -8239,6 +8272,11 @@ hast-util-to-parse5@^6.0.0:
xtend "^4.0.0"
zwitch "^1.0.0"
+hast-util-whitespace@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.npm.taobao.org/hast-util-whitespace/download/hast-util-whitespace-1.0.4.tgz#e4fe77c4a9ae1cb2e6c25e02df0043d0164f6e41"
+ integrity sha1-5P53xKmuHLLmwl4C3wBD0BZPbkE=
+
hastscript@^5.0.0:
version "5.1.2"
resolved "http://registry.npm.baidu-int.com/hastscript/-/hastscript-5.1.2.tgz#bde2c2e56d04c62dd24e8c5df288d050a355fb8a"
@@ -10071,7 +10109,7 @@ mdast-util-definitions@^3.0.0:
dependencies:
unist-util-visit "^2.0.0"
-mdast-util-to-hast@9.1.0:
+mdast-util-to-hast@9.1.0, mdast-util-to-hast@^9.0.0:
version "9.1.0"
resolved "http://registry.npm.baidu-int.com/mdast-util-to-hast/-/mdast-util-to-hast-9.1.0.tgz#6ef121dd3cd3b006bf8650b1b9454da0faf79ffe"
integrity sha1-bvEh3TzTsAa/hlCxuUVNoPr3n/4=
@@ -13304,6 +13342,16 @@ remark-footnotes@1.0.0:
resolved "http://registry.npm.baidu-int.com/remark-footnotes/-/remark-footnotes-1.0.0.tgz#9c7a97f9a89397858a50033373020b1ea2aad011"
integrity sha1-nHqX+aiTl4WKUAMzcwILHqKq0BE=
+remark-html@^12.0.0:
+ version "12.0.0"
+ resolved "https://registry.npm.taobao.org/remark-html/download/remark-html-12.0.0.tgz#f39d2a5e173cce777981cb4171b4ea860313d72a"
+ integrity sha1-850qXhc8znd5gctBcbTqhgMT1yo=
+ dependencies:
+ hast-util-sanitize "^3.0.0"
+ hast-util-to-html "^7.0.0"
+ mdast-util-to-hast "^9.0.0"
+ xtend "^4.0.1"
+
remark-mdx@1.6.16:
version "1.6.16"
resolved "http://registry.npm.baidu-int.com/remark-mdx/-/remark-mdx-1.6.16.tgz#13ee40ad0614a1cc179aca3604d7f1b79e498a2f"
@@ -13376,9 +13424,9 @@ remark-stringify@^8.0.0:
unherit "^1.0.4"
xtend "^4.0.1"
-remark@^12.0.0:
+remark@^12.0.0, remark@^12.0.1:
version "12.0.1"
- resolved "http://registry.npm.baidu-int.com/remark/-/remark-12.0.1.tgz#f1ddf68db7be71ca2bad0a33cd3678b86b9c709f"
+ resolved "https://registry.npm.taobao.org/remark/download/remark-12.0.1.tgz?cache=0&sync_timestamp=1594993800845&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fremark%2Fdownload%2Fremark-12.0.1.tgz#f1ddf68db7be71ca2bad0a33cd3678b86b9c709f"
integrity sha1-8d32jbe+ccorrQozzTZ4uGuccJ8=
dependencies:
remark-parse "^8.0.0"
@@ -14393,7 +14441,7 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"
-stringify-entities@^3.0.0:
+stringify-entities@^3.0.0, stringify-entities@^3.0.1:
version "3.0.1"
resolved "http://registry.npm.baidu-int.com/stringify-entities/-/stringify-entities-3.0.1.tgz#32154b91286ab0869ab2c07696223bd23b6dbfc0"
integrity sha1-MhVLkShqsIaassB2liI70jttv8A=
@@ -15290,9 +15338,9 @@ unist-util-visit-parents@^3.0.0:
"@types/unist" "^2.0.0"
unist-util-is "^4.0.0"
-unist-util-visit@2.0.3, unist-util-visit@^2.0.0:
+unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.3:
version "2.0.3"
- resolved "http://registry.npm.baidu-int.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c"
+ resolved "https://registry.npm.taobao.org/unist-util-visit/download/unist-util-visit-2.0.3.tgz?cache=0&sync_timestamp=1594459623892&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funist-util-visit%2Fdownload%2Funist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c"
integrity sha1-w3A4kxRt9HIDu4qXla9H17lxIIw=
dependencies:
"@types/unist" "^2.0.0"