Skip to content

Commit

Permalink
feat: 支持高亮块语法(老费劲了) #37
Browse files Browse the repository at this point in the history
  • Loading branch information
Mereithhh committed Sep 7, 2022
1 parent 8d086f2 commit ccf6356
Show file tree
Hide file tree
Showing 18 changed files with 657 additions and 10 deletions.
4 changes: 3 additions & 1 deletion packages/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@
"react-dom": "^17.0.0",
"react-helmet-async": "^1.2.0",
"react-monaco-editor": "^0.50.1",
"umi": "^3.5.0"
"remark-directive": "^2.0.1",
"umi": "^3.5.0",
"unist-util-visit": "^4.1.1"
},
"devDependencies": {
"@ant-design/pro-cli": "^2.1.0",
Expand Down
109 changes: 109 additions & 0 deletions packages/admin/src/components/Editor/customContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { BytemdPlugin } from 'bytemd';

import remarkDirective from 'remark-directive';
import { visit } from 'unist-util-visit';
import { icons } from './icons';
export function customContainer(): BytemdPlugin {
return {
remark: (processer) => processer.use(remarkDirective).use(customContainerPlugin),

viewerEffect: ({ markdownBody }) => {
const els = markdownBody.querySelectorAll('.custom-container');
els.forEach((el) => {
const type = el.className.replace('custom-container', '').trim();
const title = el.getAttribute('type');
const titleEl = document.createElement('p');
titleEl.className = `custom-container-title ${title}`;

const icon = icons[type];
const html = `${icon}<span>${title}</span>`;

titleEl.innerHTML = html;

el.insertBefore(titleEl, el.firstChild);
});
},
actions: [
{
title: '自定义高亮块',
icon: '<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3441" width="16" height="16" fill="currentColor"><path d="M157.399245 966.003965a99.435203 99.435203 0 0 1-99.33321-99.287213V668.09133a99.4682 99.4682 0 0 1 99.33321-99.287213h709.322511a99.425203 99.425203 0 0 1 99.282213 99.287213v198.625422a99.393206 99.393206 0 0 1-99.282213 99.287213z m-14.199029-297.912635v198.625422a14.234027 14.234027 0 0 0 14.199029 14.199029h709.322511a14.233027 14.233027 0 0 0 14.19903-14.199029V668.09133a14.266025 14.266025 0 0 0-14.19903-14.19903H157.399245a14.266025 14.266025 0 0 0-14.198029 14.19903z m14.199029-212.824452a99.436203 99.436203 0 0 1-99.33321-99.288212V157.353243a99.4682 99.4682 0 0 1 99.33321-99.287212h709.322511a99.424203 99.424203 0 0 1 99.282213 99.287212v198.625423a99.393206 99.393206 0 0 1-99.282213 99.287212z m-14.198029-297.913635v198.625423a14.233027 14.233027 0 0 0 14.199029 14.199029h709.321511a14.233027 14.233027 0 0 0 14.19903-14.199029V157.353243a14.266025 14.266025 0 0 0-14.19903-14.199029H157.399245a14.267025 14.267025 0 0 0-14.198029 14.199029z" p-id="3442"></path></svg>',
cheatsheet: `:::info{title="标题"}`,
handler: {
type: 'dropdown',
actions: customContainerActionItems.map(({ title, code }) => {
return {
title,
handler: {
type: 'action',
click({ editor, appendBlock, codemirror }) {
const { line } = appendBlock(code);
editor.setSelection(codemirror.Pos(line + 1, 0), codemirror.Pos(line + 1));
editor.focus();
},
},
};
}),
},
},
],
};
}

const customContainerActionItems = [
{
title: 'info',
code: `:::info{title="相关信息"}\n相关信息\n:::`,
},
{
title: 'note',
code: `:::note{title="注"}\n注\n:::`,
},
{
title: 'warning',
code: `:::warning{title="注意"}\n注意\n:::`,
},
{
title: 'danger',
code: `:::danger{title="警告"}\n警告\n:::`,
},
{
title: 'tip',
code: `:::tip{title="提示"}\n提示\n:::`,
},
];

const customContainerTitleMap: Record<string, string> = {
note: '注',
info: '相关信息',
warning: '注意',
danger: '警告',
tip: '提示',
};
function customContainerPlugin() {
return (tree) => {
visit(tree, (node) => {
if (
node.type === 'textDirective' ||
node.type === 'leafDirective' ||
node.type === 'containerDirective'
) {
if (node.type == 'containerDirective') {
const data = node.data || (node.data = {});
const tagName = node.name;
data.hName = 'div';
const { attributes } = node || {};
const title = attributes?.title || customContainerTitleMap[tagName];
const cls = `custom-container ${tagName}`;
data.hProperties = {
class: cls,
['type']: title,
};
return {
...node,
data,
};
}
}
});
};
}
29 changes: 29 additions & 0 deletions packages/admin/src/components/Editor/icons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export const icons: Record<string, string> = {
tip: `<svg viewBox="0 0 12 16" fill="currentColor" width="20" height="20">
<path
fill-rule="evenodd"
d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"
/>
</svg>`,
warning: `<svg viewBox="0 0 16 16" fill="currentColor" width="20" height="20">
<path
fill-rule="evenodd"
d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"
/>
</svg>`,
danger: `<svg viewBox="0 0 1024 1024" fill="currentColor" width="20" height="20">
<path d="M147.911 833.422V560.356a364.089 364.089 0 1 1 728.178 0v273.066H921.6v91.022H102.4v-91.022h45.511zm91.022-273.066h91.023A182.044 182.044 0 0 1 512 378.31v-91.02a273.067 273.067 0 0 0-273.067 273.067zM466.49 14.222h91.022v136.534H466.49V14.222zm399.496 127.795 64.353 64.353-96.483 96.53-64.399-64.354 96.53-96.529zM93.662 206.37l64.353-64.353 96.529 96.484-64.308 64.444-96.574-96.575z" />
</svg>`,
note: `<svg viewBox="0 0 14 16" fill="currentColor" width="20" height="20">
<path
fill-rule="evenodd"
d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"
/>
</svg>`,
info: `<svg viewBox="0 0 14 16" fill="currentColor" width="20" height="20">
<path
fill-rule="evenodd"
d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"
/>
</svg>`,
};
100 changes: 100 additions & 0 deletions packages/admin/src/components/Editor/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
.custom-container {
--info-title-color: #193c47;
--info-bg-color: #eef9fd;
--info-border-color: #4cb3d4;

--note-title-color: #474748;
--note-bg-color: #fdfdfe;
--note-border-color: #d4d5d8;

--tip-title-color: #003100;
--tip-bg-color: #e6f6e6;
--tip-border-color: #009400;

--warning-title-color: #4d3800;
--warning-bg-color: #fff8e6;
--warning-border-color: #e6a700;

--danger-title-color: #4b1113;
--danger-bg-color: #ffebec;
--danger-border-color: #e13238;
}
.dark .custom-container {

--info-title-color: #eef9fd;
--info-bg-color: #193c47;

--note-title-color: #fdfdfe;
--note-bg-color: #474748;

--tip-title-color: #e6f6e6;
--tip-bg-color: #003100;

--warning-title-color: #fff8e6;
--warning-bg-color: #4d3800;


--danger-title-color: #ffebec;
--danger-bg-color: #4b1113;

--detail-bg-color: #333;
--detail-text-color: #a8a8a8;
}

.custom-container.info {
background-color: var(--info-bg-color);
border-color: var(--info-border-color);
}
.custom-container.note {
background-color: var(--note-bg-color);
border-color: var(--note-border-color);
}
.custom-container.tip {
background-color: var(--tip-bg-color);
border-color: var(--tip-border-color);
}
.custom-container.warning {
background-color: var(--warning-bg-color);
border-color: var(--warning-border-color);
}
.custom-container.danger {
background-color: var(--danger-bg-color);
border-color: var(--danger-border-color);
}
.custom-container-title.info {
color: var(--info-title-color);
}
.custom-container-title.note {
color: var(--note-title-color);
}
.custom-container-title.warning {
color: var(--warning-title-color);
}
.custom-container-title.tip {
color: var(--tip-title-color);
}
.custom-container-title.danger {
color: var(--danger-title-color);
}

.custom-container {
margin: 1rem 0;
padding: 0.25rem 1rem;
border-left-width: 0.3rem;
border-left-style: solid;
border-radius: 0.5rem;
color: inherit;
}

.markdown-body .custom-container-title {
font-weight: 600;
margin: 16px 0;
display: flex;
align-items: center;
}
.markdown-body .custom-container-title svg {
margin-right: 4px;
}
body .markdown-body .custom-container .relative > pre {
margin: 0 !important;
}
5 changes: 5 additions & 0 deletions packages/admin/src/components/Editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ import 'highlight.js/styles/vs.css';
import 'katex/dist/katex.css';
import { useMemo } from 'react';
import { imgUploadPlugin, uploadImg } from './imgUpload';
import './index.less';
import { insertMore } from './insertMore';
import { cn } from './locales';

import { customContainer } from './customContainer';

export default function EditorComponent(props: {
value: string;
onChange: (string: string) => void;
Expand All @@ -25,13 +28,15 @@ export default function EditorComponent(props: {
const { loading, setLoading } = props;
const plugins = useMemo(() => {
return [
customContainer(),
gfm({ locale: cn }),
highlight(),
breaks(),
frontmatter(),
math({ locale: cn }),
mediumZoom(),
mermaid({ locale: cn }),

imgUploadPlugin(setLoading),
insertMore(),
];
Expand Down
2 changes: 2 additions & 0 deletions packages/admin/src/global.less
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,5 @@ body .ant-page-header-heading-title {
padding: 0;
}
}


Loading

0 comments on commit ccf6356

Please sign in to comment.