From 588f862a83e78193047f5c8690fe909d36051bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E8=8F=9C=20Cai?= Date: Mon, 9 Sep 2024 09:52:31 +0800 Subject: [PATCH 01/14] =?UTF-8?q?fix:=20=E5=AF=B9=E4=BA=8E=E9=85=8D?= =?UTF-8?q?=E7=BD=AEconfig=20=E7=B1=BB=E5=9E=8B=E7=9A=84=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20(#890)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 对于配置config 类型的修复 * chore: 将`CherryPreviewerOptions`包含的字段设为可选类型 * chore: 修改类型 * chore: 修改CherryDefaultToolbar类型定义 * chore: remove client's change * chore: 添加`syntax` 类型定义 --- .../CherryMarkdown/cherry.config.ts | 2 +- types/cherry.d.ts | 183 +++++++++++++++--- types/previewer.d.ts | 20 +- 3 files changed, 163 insertions(+), 42 deletions(-) diff --git a/client/src/components/CherryMarkdown/cherry.config.ts b/client/src/components/CherryMarkdown/cherry.config.ts index 256a3d43..98e71163 100644 --- a/client/src/components/CherryMarkdown/cherry.config.ts +++ b/client/src/components/CherryMarkdown/cherry.config.ts @@ -283,4 +283,4 @@ const initCherryMarkdown = () => { }) } -export default initCherryMarkdown; +export default initCherryMarkdown; \ No newline at end of file diff --git a/types/cherry.d.ts b/types/cherry.d.ts index 6f6a4703..a018fd6e 100644 --- a/types/cherry.d.ts +++ b/types/cherry.d.ts @@ -2,9 +2,8 @@ import CodeMirror from 'codemirror'; import SyntaxBase from '../src/core/SyntaxBase'; import { FormulaMenu } from '@/toolbars/BubbleFormula'; - export interface CherryExternalsOptions { - [key: string]: any; + [key: symbol]: any; } type CherryToolbarsCustomType = { @@ -69,7 +68,7 @@ export interface _CherryOptions void; /** 变更语言时触发 */ - afterChangeLocale?: ( locale: string ) => void; + afterChangeLocale?: (locale: string) => void; /** 变更主题时触发 */ - changeMainTheme?: ( theme: string ) => void; + changeMainTheme?: (theme: string) => void; /** 变更代码块主题时触发 */ - changeCodeBlockTheme?: ( theme: string ) => void; + changeCodeBlockTheme?: (theme: string) => void; }; /** 预览区域配置 */ previewer: CherryPreviewerOptions; @@ -196,7 +195,133 @@ export interface CherryEngineOptions { flowSessionContext?: boolean; }; /** 内置语法配置 */ - syntax?: Record | false>; + syntax?: { + // 语法开关 + // 'hookName': false, + // 语法配置 + // 'hookName': { + // + // } + link?: { + /** 生成的标签追加target属性的默认值 空:在标签里不会追加target属性, _blank:在标签里追加target="_blank"属性 */ + target?: '_blank' | '', + /** 生成的标签追加rel属性的默认值 空:在标签里不会追加rel属性, nofollow:在标签里追加rel="nofollow:在"属性*/ + rel?: '_blank' | 'nofollow' | '', + }, + autoLink?: { + /** 生成的标签追加target属性的默认值 空:在标签里不会追加target属性, _blank:在标签里追加target="_blank"属性 */ + target?: '_blank' | '', + /** 生成的标签追加rel属性的默认值 空:在标签里不会追加rel属性, nofollow:在标签里追加rel="nofollow:在"属性*/ + rel?: '_blank' | 'nofollow' | '', + /** 是否开启短链接 默认:true */ + enableShortLink?: boolean, + /** 短链接长度 默认:20 */ + shortLinkLength?: number, + }, + list?: { + listNested?: boolean, // 同级列表类型转换后变为子级 + indentSpace?: number, // 默认2个空格缩进 + }, + table: { + enableChart?: boolean, + selfClosing?: boolean, // 自动闭合,为true时,当输入第一行table内容时,cherry会自动按表格进行解析 + // chartRenderEngine: EChartsTableEngine, + // externals: ['echarts'], + }, + inlineCode?: { + /** + * @deprecated 不再支持theme的配置,统一在`themeSettings.inlineCodeTheme`中配置 + */ + // theme: 'red', + }, + codeBlock?: { + /** + * @deprecated 不再支持theme的配置,统一在`themeSettings.codeBlockTheme`中配置 + */ + // theme: 'dark', // 默认为深色主题 + wrap?: boolean, // 超出长度是否换行,false则显示滚动条 + lineNumber?: boolean, // 默认显示行号 + copyCode?: boolean, // 是否显示“复制”按钮 + editCode?: boolean, // 是否显示“编辑”按钮 + changeLang?: boolean, // 是否显示“切换语言”按钮 + expandCode?: boolean, // 是否展开/收起代码块,当代码块行数大于10行时,会自动收起代码块 + selfClosing?: boolean, // 自动闭合,为true时,当md中有奇数个```时,会自动在md末尾追加一个``` + customRenderer?: { + // 自定义语法渲染器 + }, + mermaid?: { + svg2img?: boolean, // 是否将mermaid生成的画图变成img格式 + }, + /** + * indentedCodeBlock是缩进代码块是否启用的开关 + * + * 在6.X之前的版本中默认不支持该语法。 + * 因为cherry的开发团队认为该语法太丑了(容易误触) + * 开发团队希望用```代码块语法来彻底取代该语法 + * 但在后续的沟通中,开发团队发现在某些场景下该语法有更好的显示效果 + * 因此开发团队在6.X版本中才引入了该语法 + * 已经引用6.x以下版本的业务如果想做到用户无感知升级,可以去掉该语法: + * indentedCodeBlock:false + */ + indentedCodeBlock?: boolean, + }, + emoji?: { + useUnicode?: boolean, // 是否使用unicode进行渲染 + }, + fontEmphasis?: { + /** + * 是否允许首尾空格 + * 首尾、前后的定义: 语法前**语法首+内容+语法尾**语法后 + * 例: + * true: + * __ hello __ ====> hello + * __hello__ ====> hello + * false: + * __ hello __ ====> _ hello _ + * __hello__ ====> hello + */ + allowWhitespace?: boolean, + selfClosing?: boolean, // 自动闭合,为true时,当输入**XXX时,会自动在末尾追加** + }, + strikethrough?: { + /** + * 是否必须有前后空格 + * 首尾、前后的定义: 语法前**语法首+内容+语法尾**语法后 + * 例: + * true: + * hello wor~~l~~d ====> hello wor~~l~~d + * hello wor ~~l~~ d ====> hello wor l d + * false: + * hello wor~~l~~d ====> hello world + * hello wor ~~l~~ d ====> hello wor l d + */ + needWhitespace?: boolean, + }, + mathBlock?: { + engine?: 'katex' | 'MathJax', // katex或MathJax + src?: string, + plugins?: boolean, // 加载插件 + }, + inlineMath?: { + engine?: 'katex' | 'MathJax', // katex或MathJax + src?: string, + }, + toc?: { + /** 默认只渲染一个目录 */ + allowMultiToc?: boolean, + /** 是否显示自增序号 */ + showAutoNumber?: boolean, + }, + header?: { + /** + * 标题的样式: + * - default 默认样式,标题前面有锚点 + * - autonumber 标题前面有自增序号锚点 + * - none 标题没有锚点 + */ + anchorStyle?: 'default' | 'autonumber' | 'none', + }, + }; /** 自定义语法 */ customSyntax?: Record; } @@ -241,42 +366,39 @@ export interface CherryEditorOptions { export type CherryLifecycle = (text: string, html: string) => void; export interface CherryPreviewerOptions { - dom: HTMLDivElement | false; + dom?: HTMLDivElement | false; /** 预览区域的DOM className */ - className: string; - enablePreviewerBubble: boolean; - floatWhenClosePreviewer: boolean; + className?: string; + enablePreviewerBubble?: boolean; + floatWhenClosePreviewer?: boolean; // 配置图片懒加载的逻辑 - lazyLoadImg: { + lazyLoadImg?: { // 加载图片时如果需要展示loaing图,则配置loading图的地址 - loadingImgPath: string; + loadingImgPath?: string; // 同一时间最多有几个图片请求,最大同时加载6张图片 - maxNumPerTime: 1 | 2 | 3 | 4 | 5 | 6, + maxNumPerTime?: 1 | 2 | 3 | 4 | 5 | 6, // 不进行懒加载处理的图片数量,如果为0,即所有图片都进行懒加载处理, 如果设置为-1,则所有图片都不进行懒加载处理 - noLoadImgNum: number, + noLoadImgNum?: number, // 首次自动加载几张图片(不论图片是否滚动到视野内),autoLoadImgNum = -1 表示会自动加载完所有图片 - autoLoadImgNum: -1 | number; + autoLoadImgNum?: -1 | number; // 针对加载失败的图片 或 beforeLoadOneImgCallback 返回false 的图片,最多尝试加载几次,为了防止死循环,最多5次。以图片的src为纬度统计重试次数 - maxTryTimesPerSrc: 0 | 1 | 2 | 3 | 4 | 5, + maxTryTimesPerSrc?: 0 | 1 | 2 | 3 | 4 | 5, // 加载一张图片之前的回调函数,函数return false 会终止加载操作 - beforeLoadOneImgCallback: (img: HTMLImageElement) => void | boolean; + beforeLoadOneImgCallback?: (img: HTMLImageElement) => void | boolean; // 加载一张图片失败之后的回调函数 - failLoadOneImgCallback: (img: HTMLImageElement) => void; + failLoadOneImgCallback?: (img: HTMLImageElement) => void; // 加载一张图片之后的回调函数,如果图片加载失败,则不会回调该函数 - afterLoadOneImgCallback: (img: HTMLImageElement) => void; + afterLoadOneImgCallback?: (img: HTMLImageElement) => void; // 加载完所有图片后调用的回调函数 - afterLoadAllImgCallback: () => void; + afterLoadAllImgCallback?: () => void; }; } export type CherryToolbarSeparator = '|'; -export type CherryCustomToolbar = string; - export type CherryDefaultToolbar = - // | CherryToolbarSeparator | 'audio' - | 'barTable' + | 'bar-table' | 'bold' | 'br' | 'checklist' @@ -300,7 +422,7 @@ export type CherryDefaultToolbar = | 'insert' | 'italic' | 'justify' - | 'lineTable' + | 'line-table' | 'link' | 'list' | 'mobilePreview' @@ -390,13 +512,12 @@ export interface CherryToolbarsOptions | CherryDefaultToolbar]?: (keyof F['CustomMenuType'] | CherryDefaultToolbar)[] })[] + { [K in (keyof Partial) | CherryDefaultToolbar]?: (keyof F['CustomMenuType'] | CherryDefaultToolbar)[] })[] | false; toolbarRight?: - | (CherryCustomToolbar | CherryDefaultBubbleToolbar | CherryDefaultToolbar)[] + | (CherryDefaultBubbleToolbar | CherryDefaultToolbar)[] | false; /** 是否展示悬浮目录 */ toc?: false | { @@ -433,7 +554,7 @@ export interface CherryToolbarsOptions void | boolean; + beforeLoadOneImgCallback?: (img: HTMLImageElement) => void | boolean; // 加载一张图片失败之后的回调函数 - failLoadOneImgCallback: (img: HTMLImageElement) => void; + failLoadOneImgCallback?: (img: HTMLImageElement) => void; // 加载一张图片之后的回调函数,如果图片加载失败,则不会回调该函数 - afterLoadOneImgCallback: (img: HTMLImageElement) => void; + afterLoadOneImgCallback?: (img: HTMLImageElement) => void; // 加载完所有图片后调用的回调函数 - afterLoadAllImgCallback: () => void; + afterLoadAllImgCallback?: () => void; }; } From afa5a7f4bf9d5bc0dd420843673eba8f5a54dfe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sunsonliu=28=E5=88=98=E9=98=B3=29?= Date: Wed, 11 Sep 2024 11:47:54 +0800 Subject: [PATCH 02/14] =?UTF-8?q?fix:=20#898=20=E4=BF=AE=E5=A4=8D=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E4=B8=BB=E9=A2=98=E5=A4=B1=E6=95=88=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cherry.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Cherry.js b/src/Cherry.js index 7fe3c6d7..f9e5ab02 100644 --- a/src/Cherry.js +++ b/src/Cherry.js @@ -528,6 +528,7 @@ export default class Cherry extends CherryStatic { mainTheme = getThemeFromLocal(true, this.nameSpace); } else { mainTheme = this.options.themeSettings.mainTheme; + mainTheme = `theme__${mainTheme}`; } if (typeof this.options.toolbars.theme === 'string') { toolbarTheme = this.options.toolbars.theme === 'dark' ? 'dark' : 'light'; From 191206b965a4d6b1ebd6ac5867569aa786b24460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sunsonliu=28=E5=88=98=E9=98=B3=29?= Date: Wed, 11 Sep 2024 11:49:46 +0800 Subject: [PATCH 03/14] =?UTF-8?q?fix:=20#898=20=E4=BF=AE=E5=A4=8D=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E4=B8=BB=E9=A2=98=E5=A4=B1=E6=95=88=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cherry.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Cherry.js b/src/Cherry.js index f9e5ab02..3d962817 100644 --- a/src/Cherry.js +++ b/src/Cherry.js @@ -528,6 +528,7 @@ export default class Cherry extends CherryStatic { mainTheme = getThemeFromLocal(true, this.nameSpace); } else { mainTheme = this.options.themeSettings.mainTheme; + mainTheme = mainTheme.replace(/theme__/g, ''); mainTheme = `theme__${mainTheme}`; } if (typeof this.options.toolbars.theme === 'string') { From 90f3c1db578cc8cfa4305cb5e2537a7fc2033e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sunsonliu=28=E5=88=98=E9=98=B3=29?= Date: Wed, 11 Sep 2024 12:09:14 +0800 Subject: [PATCH 04/14] =?UTF-8?q?fix:=20#898=20=E4=BF=AE=E5=A4=8D=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E4=BB=A3=E7=A0=81=E5=9D=97=E4=B8=BB=E9=A2=98=E5=A4=B1?= =?UTF-8?q?=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cherry.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Cherry.js b/src/Cherry.js index 3d962817..93ee1341 100644 --- a/src/Cherry.js +++ b/src/Cherry.js @@ -545,9 +545,12 @@ export default class Cherry extends CherryStatic { } // @ts-ignore if (typeof this.options.engine.syntax.codeBlock.theme === 'string') { - inlineCodeTheme = /** @type {{theme?: string;}} */ (this.options.engine.syntax.codeBlock).theme; + codeBlockTheme = /** @type {{theme?: string;}} */ (this.options.engine.syntax.codeBlock).theme; } else { - inlineCodeTheme = this.options.themeSettings.codeBlockTheme; + codeBlockTheme = this.options.themeSettings.codeBlockTheme; + } + if (testHasLocal(this.nameSpace, 'codeTheme')) { + codeBlockTheme = getCodeThemeFromLocal(this.nameSpace); } if (codeBlockTheme === 'dark') codeBlockTheme = 'tomorrow-night'; else if (codeBlockTheme === 'light') codeBlockTheme = 'solarized-light'; @@ -556,9 +559,6 @@ export default class Cherry extends CherryStatic { 'data-inlineCodeTheme': inlineCodeTheme, 'data-codeBlockTheme': codeBlockTheme, }); - - wrapperDom.setAttribute('data-code-block-theme', getCodeThemeFromLocal(this.nameSpace)); - this.wrapperDom = wrapperDom; return wrapperDom; } From ad1362ac8ab164182e3f849f75b1d6a7f39d586f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sunsonliu=28=E5=88=98=E9=98=B3=29?= Date: Wed, 11 Sep 2024 12:39:01 +0800 Subject: [PATCH 05/14] =?UTF-8?q?fix:=20#879=20=E4=BF=AE=E5=A4=8D=E8=84=9A?= =?UTF-8?q?=E6=B3=A8=E5=9C=A8=E6=BB=9A=E5=8A=A8=E6=9D=A1=E5=9C=A8html?= =?UTF-8?q?=E6=97=B6=E6=97=A0=E6=B3=95=E6=BB=9A=E5=8A=A8=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Previewer.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Previewer.js b/src/Previewer.js index b8b80107..ee94ca42 100644 --- a/src/Previewer.js +++ b/src/Previewer.js @@ -946,15 +946,21 @@ export default class Previewer { * @return {boolean} 是否有对应id的元素并执行滚动 */ scrollToId(id) { - const dom = this.getDomContainer(); + const previewDom = this.getDomContainer(); + const scrollDom = this.getDomCanScroll(previewDom); let $id = id.replace(/^\s*#/, '').trim(); $id = /[%:]/.test($id) ? $id : encodeURIComponent($id); - const target = dom.querySelector(`[id="${$id}"]`) ?? false; + const target = previewDom.querySelector(`[id="${$id}"]`) ?? false; if (target === false) { return false; } - const scrollTop = dom.scrollTop + target.getBoundingClientRect().y - dom.getBoundingClientRect().y - 20; - dom.scrollTo({ + let scrollTop = 0; + if (scrollDom.nodeName === 'HTML') { + scrollTop = scrollDom.scrollTop + target.getBoundingClientRect().y - 20; + } else { + scrollTop = scrollDom.scrollTop + target.getBoundingClientRect().y - scrollDom.getBoundingClientRect().y - 20; + } + scrollDom.scrollTo({ top: scrollTop, left: 0, behavior: 'smooth', From 3b4bf0d8c1834ce38480492c77a858e33fc7af80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E8=8F=9C=20Cai?= Date: Fri, 20 Sep 2024 16:22:00 +0800 Subject: [PATCH 06/14] chore(ci): create an npm preview version for each PR (#914) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(ci): create an npm preview version for each PR * chore: 修改提示语句错误 --- .../workflows/pr-merge-dev-npm_preview.yml | 197 ++++++++++++++++++ .../{pr-reviewer.yml => pr-reviewer-COS.yml} | 0 2 files changed, 197 insertions(+) create mode 100644 .github/workflows/pr-merge-dev-npm_preview.yml rename .github/workflows/{pr-reviewer.yml => pr-reviewer-COS.yml} (100%) diff --git a/.github/workflows/pr-merge-dev-npm_preview.yml b/.github/workflows/pr-merge-dev-npm_preview.yml new file mode 100644 index 00000000..143735af --- /dev/null +++ b/.github/workflows/pr-merge-dev-npm_preview.yml @@ -0,0 +1,197 @@ +name: PR Merge Dev NPM Preview + +# task: +# 1. 仅在主仓库中运行 (done) +# 2. 仅在pr合并时运行 (done) +# 3. 当pr合并时,获取pr合并后的commit id (done) +# 4. 根据commit id 修改package.json中的版本号和名称 (done) +# 5. 发布到npm (done) +# 6. 发布成功后,将发布的版本号和链接回复到当前pr下(done) +# 7. 发布成功后,将发布的版本号和链接回复到本repo的相关issue中 (done) +# 8. 修改README.md —— 提示dev版本需谨慎使用 (done) + +on: + pull_request_target: + types: + - closed + +permissions: + pull-requests: write + issues: write + +jobs: + dev-deploy: + # 不需要在fork仓库的pr中运行, 仅当pr合并时运行 + if: github.repository == 'Tencent/cherry-markdown' && github.event.pull_request.merged == true + runs-on: ubuntu-latest + + steps: + # 检出仓库代码 + - name: Checkout repository + uses: + actions/checkout@v4 + + # 获取PR合并后的SHA + - name: Get merge commit SHA + run: | + if [ "${{ github.event.pull_request.merged }}" == "true" ]; then + SHORT_SHA=$(echo "${{ github.event.pull_request.merge_commit_sha }}" | cut -c1-7) + echo "MERGE_COMMIT_SHORT_SHA=$SHORT_SHA" >> "$GITHUB_ENV" + + else + echo "Not a merged PR, skipping" + fi + + # 根据commit id 修改package.json中的版本号和名称 + - name: dev package version and name + run: | + if [ -f package.json ]; then + + # 获取当前版本号并添加 merge commit SHA + VERSION=$(node -p "require('./package.json').version")-dev.${{ env.MERGE_COMMIT_SHORT_SHA }} + + # 设置环境变量 + echo "PACKAGE_VERSION=$VERSION" >> "$GITHUB_ENV" + package_name="@cherry-markdown/preview-dev" + echo "PACKAGE_NAME=$package_name" >> "$GITHUB_ENV" + + # 打印当前版本号 + echo "Current version: $PACKAGE_VERSION" + + # 修改 package.json 中的 name 和 version,并检查 scripts 中是否存在 publish 属性,如果存在则移除 + jq --arg package_name "$package_name" --arg package_version "$VERSION" ' + .name=$package_name | + .version=$package_version | + if .scripts.publish then del(.scripts.publish) else . end + ' package.json > temp.json && mv temp.json package.json + + # 打印修改后的 name 和 version + echo "Updated package.json:" + cat package.json | jq '.name, .version' + + echo "$PACKAGE_VERSION" + + # 检查 scripts 中是否存在 publish 属性,如果存在则移除 + if jq -e '.scripts.publish' package.json > /dev/null; then + jq 'del(.scripts.publish)' package.json > temp.json && mv temp.json package.json + fi + + else + echo "package.json 文件不存在" + fi + + # 重写或创建 README.md 文件 + echo -e '

cherry logo

\n' > README.md + echo -e '# Cherry Markdown Writer\n' >> README.md + echo -e '> !WARNING\n This is a dev preview version of `Cherry Markdown`, please use it with caution. No responsibility for production versions.\n' >> README.md + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: "18" + registry-url: https://registry.npmjs.org/ + + - name: yarn install + run: | + npm i yarn -g + yarn install + + - name: build + run: yarn build + + - name: npm publish + run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Comment on related issues + id: get-issues + uses: actions/github-script@v7 + with: + result-encoding: string + retries: 3 + retry-exempt-status-codes: 400,401 + script: | + let issue_array =[context.issue.number]; + + // 添加issue到数组并去重 + const addIssueToArray = (newIssues) => { + issue_array.push(...newIssues); + issue_array = [...new Set(issue_array)]; + }; + + try { + // 获取pr的issue编号并且转换成数字数组 + const getIssueRegex =(issueText)=>{ + const issueRegex = /#(\d+)/g + return Array.from(issueText.matchAll(issueRegex), match => parseInt(match[1], 10)); + }; + + const comment = `谢谢您的大力支持,请安装和此相关的测试版进行极速体验: + \`\`\`shell + npm install ${process.env.PACKAGE_NAME}@${process.env.package_version} + \`\`\` + [查看npm发布版本](https://www.npmjs.com/package/${process.env.PACKAGE_NAME}/v/${process.env.PACKAGE_VERSION}),请注意这是一个开发预览版本,请谨慎使用!`; + + // 发布评论到issue + const createComment= async (issueNumbers) => { + if(typeof value === 'number' && !isNaN(value)) return; + issueNumbers.forEach(async (issueNumber) => { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: comment + }); + }); + }; + + // 获取当前提交的pr信息[title,body] + const { data: pullCommits } = + await github.rest.pulls.get({ + owner:context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number + }); + const pullCommitsIssueTitleNumbers = getIssueRegex(pullCommits.title); + addIssueToArray(pullCommitsIssueTitleNumbers); + const pullCommitsIssueBodyNumbers = getIssueRegex(pullCommits.body); + addIssueToArray(pullCommitsIssueBodyNumbers); + + console.log('pullCommits-title',pullCommitsIssueTitleNumbers); + console.log('pullCommits-body',pullCommitsIssueBodyNumbers); + + // 获取当前pr的issue信息[body] + const { data: listPrIssue } = + await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number + }); + listPrIssue.forEach((item) => { + const listPrIssueIssueNumbers = getIssueRegex(item.body); + addIssueToArray(listPrIssueIssueNumbers); + + console.log('listPrIssue',item.body); + console.log('listPrIssue',listPrIssueIssueNumbers); + }); + + // 获取当前pr的 review 信息[body] + const { data: listReviewComments } = + await github.rest.pulls.listReviewComments({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number + }); + listReviewComments.forEach((item) => { + const listReviewCommentsIssueNumbers = getIssueRegex(item.body); + addIssueToArray(listReviewCommentsIssueNumbers); + + console.log('listReviewComments',item.body); + console.log('listReviewComments',listReviewCommentsIssueNumbers); + }); + + createComment(issue_array); + }catch(error){ + console.log('error',error); + } \ No newline at end of file diff --git a/.github/workflows/pr-reviewer.yml b/.github/workflows/pr-reviewer-COS.yml similarity index 100% rename from .github/workflows/pr-reviewer.yml rename to .github/workflows/pr-reviewer-COS.yml From d7a887dc8d8a4f70214d984b4fafea1fd6c88b44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sunsonliu=28=E5=88=98=E9=98=B3=29?= Date: Sat, 21 Sep 2024 03:13:36 +0800 Subject: [PATCH 07/14] =?UTF-8?q?feat:=20#900=20=E2=80=9C=E5=BC=95?= =?UTF-8?q?=E7=94=A8=E2=80=9C=E8=AF=AD=E6=B3=95=E6=94=AF=E6=8C=81=E5=B5=8C?= =?UTF-8?q?=E5=A5=97=EF=BC=8C=E5=B9=B6=E6=94=AF=E6=8C=81=E5=B5=8C=E5=A5=97?= =?UTF-8?q?=E5=85=B6=E4=BB=96=E8=AF=AD=E6=B3=95=EF=BC=88=E5=A6=82=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=E3=80=81=E4=BB=A3=E7=A0=81=E5=9D=97=E3=80=81=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E3=80=81=E4=BF=A1=E6=81=AF=E9=9D=A2=E6=9D=BF=E7=AD=89?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cherry.js | 9 +++--- src/Engine.js | 7 +++++ src/core/ParagraphBase.js | 38 +++++++++++++++++------ src/core/hooks/Blockquote.js | 55 +++++---------------------------- src/core/hooks/Detail.js | 4 +++ src/core/hooks/Panel.js | 4 +++ src/toolbars/PreviewerBubble.js | 15 ++++++++- src/utils/listContentHandler.js | 2 +- 8 files changed, 70 insertions(+), 64 deletions(-) diff --git a/src/Cherry.js b/src/Cherry.js index 93ee1341..871c4f54 100644 --- a/src/Cherry.js +++ b/src/Cherry.js @@ -232,8 +232,8 @@ export default class Cherry extends CherryStatic { if (this.options.autoScrollByHashAfterInit) { setTimeout(this.scrollByHash.bind(this)); } - // 强制进行一次渲染 - this.editText(null, this.editor.editor); + // 强制进行一次渲染 // 不记得为啥要强制渲染了,先屏蔽了 + // this.editText(null, this.editor.editor); if (this.options.toolbars.toc !== false) { this.createToc(); } @@ -886,11 +886,10 @@ export default class Cherry extends CherryStatic { initText(codemirror) { try { const markdownText = codemirror.getValue(); + this.lastMarkdownText = markdownText; const html = this.engine.makeHtml(markdownText); this.previewer.update(html); - setTimeout(() => { - this.$event.emit('afterInit', { markdownText, html }); - }, 10); + this.$event.emit('afterInit', { markdownText, html }); } catch (e) { throw new NestedError(e); } diff --git a/src/Engine.js b/src/Engine.js index 695fddc3..27bc9849 100644 --- a/src/Engine.js +++ b/src/Engine.js @@ -262,6 +262,13 @@ export default class Engine { return $md; } + makeHtmlForBlockquote(md) { + let $md = md; + $md = this.$dealParagraph($md); + $md = this.$afterMakeHtml($md); + return $md; + } + mounted() { this.$fireHookAction('', 'sentence', 'mounted'); this.$fireHookAction('', 'paragraph', 'mounted'); diff --git a/src/core/ParagraphBase.js b/src/core/ParagraphBase.js index daa32d2d..bcd65524 100644 --- a/src/core/ParagraphBase.js +++ b/src/core/ParagraphBase.js @@ -249,11 +249,12 @@ export default class ParagraphBase extends SyntaxBase { return; } const $sign = sign || this.$engine.md5(str); + const key = `${this.cacheKey}I${$sign}_L${lineCount}$`; this.cache[$sign] = { content: str, - using: true, + key, }; - return `${this.cacheKey}I${$sign}_L${lineCount}$`; + return key; } popCache(sign) { @@ -263,15 +264,28 @@ export default class ParagraphBase extends SyntaxBase { return this.cache[sign].content || ''; } + testHasCache(sign) { + if (!this.needCache || !this.cache[sign]) { + return false; + } + return this.cache[sign].key; + } + + // 当缓存全部被消费后,调用此方法清理多大的缓存 resetCache() { if (!this.needCache) { return; } - for (const key of Object.keys(this.cache)) { - if (!this.cache[key].using) delete this.cache[key]; - } - for (const key of Object.keys(this.cache)) { - this.cache[key].using = false; + // 当缓存队列比较大时,随机抛弃500个缓存 + if (Object.keys(this.cache).length > 3000) { + let limit = 0; + for (const key of Object.keys(this.cache)) { + limit += 1; + if (limit > 500) { + return; + } + delete this.cache[key]; + } } } @@ -285,7 +299,13 @@ export default class ParagraphBase extends SyntaxBase { 'g', ); const $html = html.replace(regex, (match, cacheSign) => this.popCache(cacheSign.replace(/_L\d+$/, ''))); - this.resetCache(); + if (this.timer) { + clearTimeout(this.timer); + this.timer = null; + } + this.timer = setTimeout(() => { + this.resetCache(); + }, 1000); return $html; } @@ -299,8 +319,6 @@ export default class ParagraphBase extends SyntaxBase { if (!this.cache[this.sign]) { return this.toHtml(wholeMatch, sentenceMakeFunc); } - // hit & mark cache - this.cache[this.sign].using = true; return `${this.cacheKey}I${this.sign}_L${lineCount}$`; } diff --git a/src/core/hooks/Blockquote.js b/src/core/hooks/Blockquote.js index 3c35a4db..89a4a79b 100644 --- a/src/core/hooks/Blockquote.js +++ b/src/core/hooks/Blockquote.js @@ -37,61 +37,22 @@ export default class Blockquote extends ParagraphBase { handleMatch(str, sentenceMakeFunc) { return str.replace(this.RULE.reg, (match, lines, content) => { - const { sign: contentSign, html: parsedHtml } = sentenceMakeFunc(content); - const sign = this.signWithCache(parsedHtml) || contentSign; const lineCount = this.getLineCount(match, lines); // 段落所占行数 - const listRegex = - /^(([ \t]{0,3}([*+-]|\d+[.]|[a-z]\.|[I一二三四五六七八九十]+\.)[ \t]+)([^\r]+?)($|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.]|[a-z]\.|[I一二三四五六七八九十]+\.)[ \t]+)))/; - let lastIndent = computeLeadingSpaces(lines); - // 逐行处理 - const contentLines = parsedHtml.split('\n'); - const replaceReg = /^[>\s]+/; - const countReg = />/g; - let lastLevel = 1; - let level = 0; - let handledHtml = `
`; - for (let i = 0; contentLines[i]; i++) { - if (i !== 0) { - const leadIndent = computeLeadingSpaces(contentLines[i]); - if (leadIndent <= lastIndent && listRegex.test(contentLines[i])) { - break; - } - lastIndent = leadIndent; - } - /* eslint-disable no-loop-func */ - const $line = contentLines[i].replace(replaceReg, (leadSymbol) => { - const leadSymbols = leadSymbol.match(countReg); - // 本行引用嵌套层级比上层要多 - if (leadSymbols && leadSymbols.length > lastLevel) { - level = leadSymbols.length; - } else { - // 否则保持当前缩进层级 - level = lastLevel; - } - return ''; - }); - // 同层级,且不为首行时补充一个换行 - if (lastLevel === level && i !== 0) { - handledHtml += '
'; - } - // 补充缩进 - if (lastLevel < level) { - handledHtml += '
'.repeat(level - lastLevel); - lastLevel = level; - } - // 插入当前行内容 - handledHtml += $line; + const sign = this.$engine.md5(match); + const testHasCache = this.testHasCache(sign); + if (testHasCache !== false) { + return this.getCacheWithSpace(testHasCache, match); } + let handledHtml = `
`; + const $content = content.replace(/^([ \t]*>)/gm, ''); + handledHtml += this.$engine.makeHtmlForBlockquote($content); // 标签闭合 - handledHtml += '
'.repeat(lastLevel); + handledHtml += '
'; return this.getCacheWithSpace(this.pushCache(handledHtml, sign, lineCount), match); }); } makeHtml(str, sentenceMakeFunc) { - if (!this.test(str)) { - return str; - } return this.handleMatch(str, sentenceMakeFunc); } diff --git a/src/core/hooks/Detail.js b/src/core/hooks/Detail.js index 1dfba0b1..d21c7b6f 100644 --- a/src/core/hooks/Detail.js +++ b/src/core/hooks/Detail.js @@ -39,6 +39,10 @@ export default class Detail extends ParagraphBase { return str.replace(this.RULE.reg, (match, preLines, isOpen, title, content) => { const lineCount = this.getLineCount(match, preLines); const sign = this.$engine.md5(match); + const testHasCache = this.testHasCache(sign); + if (testHasCache !== false) { + return prependLineFeedForParagraph(match, testHasCache); + } const { type, html } = this.$getDetailInfo(isOpen, title, content, sentenceMakeFunc); const ret = this.pushCache( `
${html}
`, diff --git a/src/core/hooks/Panel.js b/src/core/hooks/Panel.js index 6d377ff5..559bd023 100644 --- a/src/core/hooks/Panel.js +++ b/src/core/hooks/Panel.js @@ -42,6 +42,10 @@ export default class Panel extends ParagraphBase { return str.replace(this.RULE.reg, (match, preLines, name, content) => { const lineCount = this.getLineCount(match, preLines); const sign = this.$engine.md5(match); + const testHasCache = this.testHasCache(sign); + if (testHasCache !== false) { + return prependLineFeedForParagraph(match, testHasCache); + } const { title, body, appendStyle, className } = this.$getPanelInfo(name, content, sentenceMakeFunc); const ret = this.pushCache( `
${title}${body}
`, diff --git a/src/toolbars/PreviewerBubble.js b/src/toolbars/PreviewerBubble.js index 7c7dc10d..ce33e4f4 100644 --- a/src/toolbars/PreviewerBubble.js +++ b/src/toolbars/PreviewerBubble.js @@ -101,6 +101,10 @@ export default class PreviewerBubble { * @returns {boolean|HTMLElement} */ isCherryCodeBlock(element) { + // 引用里的代码块先不支持所见即所得编辑 + if (this.$getClosestNode(element, 'BLOCKQUOTE') !== false) { + return false; + } if (element.nodeName === 'DIV' && element.dataset.type === 'codeBlock') { return element; } @@ -127,6 +131,10 @@ export default class PreviewerBubble { if (/simple-table/.test(container.className) || !/cherry-table-container/.test(container.className)) { return false; } + // 引用里的表格先不支持所见即所得编辑 + if (this.$getClosestNode(element, 'BLOCKQUOTE') !== false) { + return false; + } return container; } @@ -314,7 +322,12 @@ export default class PreviewerBubble { e.stopPropagation(); // 阻止冒泡,避免触发预览区域的点击事件 break; case 'P': - if (target instanceof HTMLParagraphElement && target.parentElement instanceof HTMLLIElement) { + if ( + target instanceof HTMLParagraphElement && + target.parentElement instanceof HTMLLIElement && + // 引用里的列表先不支持所见即所得编辑 + this.$getClosestNode(target, 'BLOCKQUOTE') === false + ) { if (target.children.length !== 0) { // 富文本 e.preventDefault(); diff --git a/src/utils/listContentHandler.js b/src/utils/listContentHandler.js index ed3830fd..badf079e 100644 --- a/src/utils/listContentHandler.js +++ b/src/utils/listContentHandler.js @@ -128,7 +128,7 @@ export default class ListHandler { const from = { line: targetLine, ch: targetCh }; const to = { line: targetLine + targetContent.length - 1, - ch: targetCh + targetContent[targetContent.length - 1].length, + ch: targetCh + targetContent[targetContent.length - 1]?.length, }; this.editor.editor.setSelection(from, to); this.range = [from, to]; From 9366d1eecb2107e93eb42eb38fab18407f3817ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sunsonliu=28=E5=88=98=E9=98=B3=29?= Date: Sat, 21 Sep 2024 03:36:13 +0800 Subject: [PATCH 08/14] =?UTF-8?q?feat:=20#900=20=E2=80=9C=E5=BC=95?= =?UTF-8?q?=E7=94=A8=E2=80=9C=E8=AF=AD=E6=B3=95=E6=94=AF=E6=8C=81=E5=B5=8C?= =?UTF-8?q?=E5=A5=97=EF=BC=8C=E5=B9=B6=E6=94=AF=E6=8C=81=E5=B5=8C=E5=A5=97?= =?UTF-8?q?=E5=85=B6=E4=BB=96=E8=AF=AD=E6=B3=95=EF=BC=88=E5=A6=82=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=E3=80=81=E4=BB=A3=E7=A0=81=E5=9D=97=E3=80=81=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E3=80=81=E4=BF=A1=E6=81=AF=E9=9D=A2=E6=9D=BF=E7=AD=89?= =?UTF-8?q?=EF=BC=89fix=20lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/hooks/Blockquote.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/core/hooks/Blockquote.js b/src/core/hooks/Blockquote.js index 89a4a79b..a3399c57 100644 --- a/src/core/hooks/Blockquote.js +++ b/src/core/hooks/Blockquote.js @@ -16,17 +16,6 @@ import ParagraphBase from '@/core/ParagraphBase'; import { compileRegExp } from '@/utils/regexp'; -function computeLeadingSpaces(leadingChars) { - const indentRegex = /^(\t|[ ]{1,4})/; - let leadingCharsTemp = leadingChars; - let indent = 0; - while (indentRegex.test(leadingCharsTemp)) { - leadingCharsTemp = leadingCharsTemp.replace(/^(\t|[ ]{1,4})/g, ''); - indent += 1; - } - return indent; -} - export default class Blockquote extends ParagraphBase { static HOOK_NAME = 'blockquote'; From 52f01c90681bd79d443d843dbc6a7c0c9361ab03 Mon Sep 17 00:00:00 2001 From: Leo Xia <52569690+Saraph1nes@users.noreply.github.com> Date: Mon, 23 Sep 2024 09:54:35 +0800 Subject: [PATCH 09/14] =?UTF-8?q?fix:=20#913=20=E6=96=87=E7=AB=A0=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E6=94=AF=E6=8C=81=E5=9B=BD=E9=99=85=E5=8C=96=20(#915)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Saraph1nes --- src/core/hooks/Toc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hooks/Toc.js b/src/core/hooks/Toc.js index 185f142d..f18846ab 100644 --- a/src/core/hooks/Toc.js +++ b/src/core/hooks/Toc.js @@ -225,7 +225,7 @@ export default class Toc extends ParagraphBase { const lines = calculateLinesOfParagraph(preLinesMatch, 1); let ret = `
`; - ret += `

目录

`; + ret += `

${this.$locale.toc}

`; if (arr.length <= 0) { return ''; } From e930143a12b95e98d303e1f0b4c1c8c8a5f50cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sunsonliu=28=E5=88=98=E9=98=B3=29?= Date: Mon, 23 Sep 2024 11:33:10 +0800 Subject: [PATCH 10/14] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=BA?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=BC=95=E7=94=A8=E5=B5=8C=E5=A5=97=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E9=A1=B5=E9=9D=A2=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Engine.js | 3 ++- src/core/hooks/Blockquote.js | 11 +++++++++-- src/core/hooks/Footnote.js | 2 +- src/core/hooks/InlineCode.js | 5 ++++- src/sass/markdown.scss | 17 ++++++++++------- 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/Engine.js b/src/Engine.js index 27bc9849..794e91af 100644 --- a/src/Engine.js +++ b/src/Engine.js @@ -258,6 +258,7 @@ export default class Engine { $md = this.$beforeMakeHtml($md); $md = this.$dealParagraph($md); $md = this.$afterMakeHtml($md); + this.$fireHookAction($md, 'paragraph', '$cleanCache'); $md = this.$deCacheBigData($md); return $md; } @@ -265,7 +266,7 @@ export default class Engine { makeHtmlForBlockquote(md) { let $md = md; $md = this.$dealParagraph($md); - $md = this.$afterMakeHtml($md); + $md = this.$fireHookAction($md, 'paragraph', 'afterMakeHtml'); return $md; } diff --git a/src/core/hooks/Blockquote.js b/src/core/hooks/Blockquote.js index a3399c57..d8df426b 100644 --- a/src/core/hooks/Blockquote.js +++ b/src/core/hooks/Blockquote.js @@ -33,15 +33,22 @@ export default class Blockquote extends ParagraphBase { return this.getCacheWithSpace(testHasCache, match); } let handledHtml = `
`; - const $content = content.replace(/^([ \t]*>)/gm, ''); + const htmlDomTest = content.split(/\n 1) { + after = `\n<${htmlDomTest.slice(1).join('\n<')}`; + } + const $content = htmlDomTest[0].replace(/^([ \t]*>)/gm, ''); handledHtml += this.$engine.makeHtmlForBlockquote($content); // 标签闭合 handledHtml += '
'; - return this.getCacheWithSpace(this.pushCache(handledHtml, sign, lineCount), match); + return `${this.getCacheWithSpace(this.pushCache(handledHtml, sign, lineCount), match)}${after}`; }); } makeHtml(str, sentenceMakeFunc) { + // return str; return this.handleMatch(str, sentenceMakeFunc); } diff --git a/src/core/hooks/Footnote.js b/src/core/hooks/Footnote.js index 52942d95..43bbd468 100644 --- a/src/core/hooks/Footnote.js +++ b/src/core/hooks/Footnote.js @@ -106,7 +106,7 @@ export default class Footnote extends ParagraphBase { afterMakeHtml(str) { const footNotes = this.getFootNote(); const $str = str.replace(/\0~fn#([0-9]+)#\0/g, (match, num) => footNotes[num].fn); - this.$cleanCache(); + // this.$cleanCache(); return $str; } diff --git a/src/core/hooks/InlineCode.js b/src/core/hooks/InlineCode.js index b35d7b6f..e9839ad7 100644 --- a/src/core/hooks/InlineCode.js +++ b/src/core/hooks/InlineCode.js @@ -32,11 +32,14 @@ export default class InlineCode extends ParagraphBase { let $str = str; if (Object.keys(CodeBlock.inlineCodeCache).length > 0) { $str = $str.replace(/~~CODE([0-9a-zA-Z]+)\$/g, (match, sign) => CodeBlock.inlineCodeCache[sign]); - CodeBlock.inlineCodeCache = {}; } return $str; } + $cleanCache() { + CodeBlock.inlineCodeCache = {}; + } + rule() { const ret = { begin: '(`+)[ ]*', end: '[ ]*\\1', content: '(.+?(?:\\n.+?)*?)' }; ret.reg = compileRegExp(ret, 'g'); diff --git a/src/sass/markdown.scss b/src/sass/markdown.scss index edee124f..04c1227f 100644 --- a/src/sass/markdown.scss +++ b/src/sass/markdown.scss @@ -213,13 +213,6 @@ overflow-x: auto; } - blockquote { - color: $quoteColor; - padding: 10px 15px; - border-left: 10px solid $quoteBorderColor; - background: $quoteBackground; - } - p, pre, blockquote, @@ -227,6 +220,16 @@ margin: 0 0 $elementGap; } + blockquote { + color: $quoteColor; + padding: 10px 15px; + border-left: 10px solid $quoteBorderColor; + background: $quoteBackground; + p, blockquote, table, pre, ul, ol{ + margin: 0; + } + } + pre { padding: 16px; overflow: auto; From 069efe47c4ca61082aadecae3b1b386a92d1485e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sunsonliu=28=E5=88=98=E9=98=B3=29?= Date: Mon, 23 Sep 2024 11:42:01 +0800 Subject: [PATCH 11/14] =?UTF-8?q?demo:=20=E4=BC=98=E5=8C=96=E7=BA=AF?= =?UTF-8?q?=E9=A2=84=E8=A7=88demo=E7=9A=84=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8Ccherry=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E5=90=8E=E4=BF=9D=E6=8C=81=E5=BD=93=E5=89=8D=E6=BB=9A=E5=8A=A8?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/scripts/preview-demo.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/scripts/preview-demo.js b/examples/scripts/preview-demo.js index 27585354..ac0172a0 100644 --- a/examples/scripts/preview-demo.js +++ b/examples/scripts/preview-demo.js @@ -72,6 +72,7 @@ var cherryConfig = { }, editor: { defaultModel: 'previewOnly', + keepDocumentScrollAfterInit: true, }, callback: { onClickPreview: function(e) { From 688b7ebe888730933bbb69824f5bb59cc95c520f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sunsonliu=28=E5=88=98=E9=98=B3=29?= Date: Mon, 23 Sep 2024 12:28:56 +0800 Subject: [PATCH 12/14] =?UTF-8?q?fix:=20#910=20=E5=9B=BE=E7=89=87=E5=92=8C?= =?UTF-8?q?=E8=B6=85=E9=93=BE=E6=8E=A5=E6=94=AF=E6=8C=81=E4=B8=80=E5=AF=B9?= =?UTF-8?q?=E6=8B=AC=E5=8F=B7=EF=BC=88=E6=97=B6=E9=97=B4=E6=9C=89=E9=99=90?= =?UTF-8?q?=EF=BC=8C=E5=85=88=E5=8F=AA=E6=94=AF=E6=8C=81=E4=B8=80=E5=AF=B9?= =?UTF-8?q?=E6=8B=AC=E5=8F=B7=EF=BC=8C=E5=86=8D=E5=A4=9A=E7=9A=84=E5=90=8E?= =?UTF-8?q?=E7=BB=AD=E5=86=8D=E8=80=83=E8=99=91=E5=AE=9E=E7=8E=B0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/hooks/Image.js | 2 +- src/core/hooks/Link.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/hooks/Image.js b/src/core/hooks/Image.js index ecc01f85..8aa47173 100644 --- a/src/core/hooks/Image.js +++ b/src/core/hooks/Image.js @@ -149,7 +149,7 @@ export default class Image extends SyntaxBase { `${ '(?:' + '\\(' + - '([^"][^\\s]+?)' + // ? url + '((?:[^\\s()]*\\([^\\s()]*\\)[^\\s()]*)|(?:[^"][^\\s]+?))' + // ? url '(?:[ \\t]((?:".*?")|(?:\'.*?\')))?' + // ? optional '\\)' + '|' + // or diff --git a/src/core/hooks/Link.js b/src/core/hooks/Link.js index afbaf851..9a3c9143 100644 --- a/src/core/hooks/Link.js +++ b/src/core/hooks/Link.js @@ -138,9 +138,10 @@ export default class Link extends SyntaxBase { * e.g. * [link](") ⭕️ valid * [link]("") ⭕️ valid + * [link](()) ⭕️ valid * [link](" ") ❌ invalid */ - '([^\\s)]+)' + // ?<link> url + '(([^\\s()]*\\([^\\s()]*\\)[^\\s()]*)|[^\\s)]+)' + // ?<link> url '(?:[ \\t]((?:".*?")|(?:\'.*?\')))?' + // ?<title> optional '\\)' + '|' + // or From e609e95ef776ae831af629c9ffa479e6d7cdd88e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sunsonliu=28=E5=88=98=E9=98=B3=29?= <sunsonliu@tencent.com> Date: Mon, 23 Sep 2024 12:31:31 +0800 Subject: [PATCH 13/14] =?UTF-8?q?fix:=20#910=20=E5=9B=BE=E7=89=87=E5=92=8C?= =?UTF-8?q?=E8=B6=85=E9=93=BE=E6=8E=A5=E6=94=AF=E6=8C=81=E4=B8=80=E5=AF=B9?= =?UTF-8?q?=E6=8B=AC=E5=8F=B7=EF=BC=88=E6=97=B6=E9=97=B4=E6=9C=89=E9=99=90?= =?UTF-8?q?=EF=BC=8C=E5=85=88=E5=8F=AA=E6=94=AF=E6=8C=81=E4=B8=80=E5=AF=B9?= =?UTF-8?q?=E6=8B=AC=E5=8F=B7=EF=BC=8C=E5=86=8D=E5=A4=9A=E7=9A=84=E5=90=8E?= =?UTF-8?q?=E7=BB=AD=E5=86=8D=E8=80=83=E8=99=91=E5=AE=9E=E7=8E=B0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/hooks/Link.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hooks/Link.js b/src/core/hooks/Link.js index 9a3c9143..a56de9e4 100644 --- a/src/core/hooks/Link.js +++ b/src/core/hooks/Link.js @@ -141,7 +141,7 @@ export default class Link extends SyntaxBase { * [link](()) ⭕️ valid * [link](" ") ❌ invalid */ - '(([^\\s()]*\\([^\\s()]*\\)[^\\s()]*)|[^\\s)]+)' + // ?<link> url + '((?:[^\\s()]*\\([^\\s()]*\\)[^\\s()]*)|[^\\s)]+)' + // ?<link> url '(?:[ \\t]((?:".*?")|(?:\'.*?\')))?' + // ?<title> optional '\\)' + '|' + // or From fbf1f0cbf67f7a6ce41493428f928acd200a5271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?sunsonliu=28=E5=88=98=E9=98=B3=29?= <sunsonliu@tencent.com> Date: Mon, 23 Sep 2024 13:32:16 +0800 Subject: [PATCH 14/14] =?UTF-8?q?fix:=20#903=20=E4=BF=AE=E5=A4=8D=E8=81=94?= =?UTF-8?q?=E6=83=B3=E5=8A=9F=E8=83=BD=E5=BC=95=E5=85=A5=E7=9A=84=E6=80=A7?= =?UTF-8?q?=E8=83=BD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/hooks/Suggester.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/hooks/Suggester.js b/src/core/hooks/Suggester.js index 2664b222..2ce11fa3 100644 --- a/src/core/hooks/Suggester.js +++ b/src/core/hooks/Suggester.js @@ -122,6 +122,8 @@ export default class Suggester extends SyntaxBase { const keyword = word .replace(/\s+/g, '') // 删掉空格,避免产生不必要的空数组元素 .replace(new RegExp(`^${suggesterKeyword}`, 'g'), '') // 删掉word当中suggesterKeywords出现的字符 + .replace(/^[#]+/, '#') + .replace(/^[/]+/, '/') .split('') .join('.*?'); // 匹配任何包含 "keyword" 的字符串,无论 "keyword" 是在字符串的开头、中间还是结尾,并且不区分大小写