From ded143936825c0e454448bfdc35082ac3075e5f5 Mon Sep 17 00:00:00 2001 From: DCloud_LXH <283700113@qq.com> Date: Tue, 5 Mar 2024 17:21:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E8=A1=A8=E6=A0=BC?= =?UTF-8?q?=E8=A1=8C=E5=B1=95=E5=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 +++ docs/.vuepress/config.js | 3 + .../markdown/markdown-it-subtable.js | 146 ++++++++++++++++++ docs/readme.md | 20 ++- package.json | 2 +- yarn.lock | 8 +- 6 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 docs/.vuepress/markdown/markdown-it-subtable.js diff --git a/README.md b/README.md index 4e9ce6c0..7fcf6ea1 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,26 @@ uni-app x 是一个庞大的工程,它包括uts语言、uvue渲染引擎、uni |流量(GB)|0.18 | |售价(元/月)#{colspan=2} |5 | ``` +14. 表格支持行展开 + md 书写格式 + ```md + | |原生语言插件 |uts插件| + |:------ |:------- |:--------| + |开发语言 |java/oc |uts| + |开发环境 |Android Studio/XCode |[HBuilderX](https://www.baidu.com)| + ->|第一列|第二列 |第三列 | + ->|:------ |:-------: |-------: | + ->|左对齐 |[居中](https://www.baidu.com)|右对齐| + |打包方式 |外挂aar 等产出物 |编译时生成原生代码| + |js层调用方式 |uni.requireNativePlugin() |普通的js函数/对象,可以直接 import,支持摇树优化| + ->|第一列|第二列 | + ->|:------ |:------- | + ->|第一列内容 |[HBuilderX](https://www.baidu.com)| + |支持项目类型 |uni-app |uni-app和uni-app x| + ``` + 表现为: + ![](https://qiniudcdn.qnqcdn.net/web-ext-storage.dcloud.net.cn/doc/subtable.png) + ## 文档 Algolia 使用限额 Included Quota: - Records: 1,000,000 diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 23d1190f..26460c39 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -114,6 +114,9 @@ const config = { .end() .plugin('add-base-to-md') .use(require('./markdown/add-base-to-md'), [{ base }]) + .end() + .plugin('subtable') + .use(require('./markdown/markdown-it-subtable').markdownIt, [{ flags: ['->'] }]) } }, chainWebpack (config, isServer) { diff --git a/docs/.vuepress/markdown/markdown-it-subtable.js b/docs/.vuepress/markdown/markdown-it-subtable.js new file mode 100644 index 00000000..50a0332d --- /dev/null +++ b/docs/.vuepress/markdown/markdown-it-subtable.js @@ -0,0 +1,146 @@ +function normalizeMD (md) { + if (typeof md === 'string') { + return md + .replace(/(? { + if (Array.isArray(tokenIndex) && tokenIndex.length > 2) { + const tableOpenIndex = tokenIndex.shift(); + const tableCloseIndex = tokenIndex.pop(); + let deleteOffset = 0; + + tokenIndex.forEach(subtableIndexes => { + const subtableOpenIndex = subtableIndexes.shift() + deleteOffset; + const subtableColumnCount = (subtableIndexes[0] + deleteOffset - subtableOpenIndex - 2) / 3 - 1; + const subtableCloseIndex = subtableIndexes.pop() + deleteOffset + subtableColumnCount * 3; + const subtableTokens = tokens.slice(subtableOpenIndex - 1, subtableCloseIndex + 1); + + // 2 table token 新行开始时固定的 tr_open td_open 数量 + // 3 每个 inline 都会伴随一个 td_close、td_open(行最后一列 inline 会伴随 td_close tr_close) + // 1 为 flag ->(标识符) 的列,需要去掉 + let tableColumnCount = 0; + for (let i = 0; i < tableCloseIndex; i++) { + const token = tokens[i]; + if (i < subtableOpenIndex) { + if (token.type === 'th_open') { + tableColumnCount++; + } else if (token.type === 'thead_close') { + break; + } + } + } + + let subtableMD = subtableTokens + .map(token => { + if (token.type === 'inline' && !flags.includes(token.content)) { + return normalizeMD(token.content); + } else if (token.type === 'tr_close') { + return '\n'; + } + }) + .filter(Boolean); + const subtableLevel = subtableTokens[0].level; + const newTokens = md.parse(`|${subtableMD.join('|')}|`); + newTokens.forEach(token => { + token.content = ''; // 和 children 内容重复 + token.level = token.level + subtableLevel; + }); + newTokens[0].attrJoin('style', 'overflow-x: visible;margin: auto;'); + const childrenTableTokenIndex = subtableOpenIndex - 2; + const subtablePrevTrOpenIndex = childrenTableTokenIndex - tableColumnCount * 3 - 2; + tokens[tableOpenIndex].attrJoin('class', 'have-children-table'); // table + tokens[subtablePrevTrOpenIndex].attrJoin('class', 'have-children-tr'); // table tr_open + + // table td_open + const haveChildrenTrTdToken = tokens[subtablePrevTrOpenIndex + 1]; + haveChildrenTrTdToken.attrJoin('class', 'have-children-tr-td'); + haveChildrenTrTdToken.attrJoin('style', ';text-wrap: nowrap'); + + tokens[childrenTableTokenIndex].attrJoin('class', 'children-table'); // subtable tr_open + tokens[childrenTableTokenIndex].attrJoin('hidden', ''); // subtable tr_open + + tokens[subtableOpenIndex - 1].attrJoin('colspan', tableColumnCount); // subtable td_open + const deleteCount = subtableCloseIndex - subtableOpenIndex + 1; + tokens.splice(subtableOpenIndex, deleteCount, ...newTokens); + deleteOffset = deleteOffset + newTokens.length - deleteCount; + }); + } + }); + } +} + +function process(md, tokens, flags = ['->']) { + const subtableMinTokenCount = 3; + if ( + Array.isArray(tokens) && + tokens.length && + tokens.some(token => token.content.includes('->') && token.type === 'inline') + ) { + const tableOpenTokenIndex = tokens.findIndex(token => token.type === 'table_open'); + if (tableOpenTokenIndex > -1) { + /** + * [ + * table_open index, + * [] // subtable indexes, + * table_close index + * ] + */ + let tableTokensIndexes = [[]]; + let tableIndex = 0; + let subtableIndex = 1; + tokens.forEach((token, index) => { + if (token.type === 'table_open' && tableTokensIndexes[tableIndex].length === 0) { + tableTokensIndexes[tableIndex].push(index); + } + if (tableTokensIndexes[tableIndex] && typeof tableTokensIndexes[tableIndex][0] !== 'undefined') { + if (token.type === 'inline') { + if (flags.find(flag => new RegExp(`^\\s*${flag}\\s*$`).test(token.content))) { + ( + tableTokensIndexes[tableIndex][subtableIndex] || (tableTokensIndexes[tableIndex][subtableIndex] = []) + ).push(index); + } else if (tokens[index - 2].type === 'tr_open') { + tableTokensIndexes[tableIndex][++subtableIndex] = []; + } + } + } + if (token.type === 'table_close') { + subtableIndex = 1; + tableTokensIndexes[tableIndex].push(index); + tableTokensIndexes[++tableIndex] = []; + } + }); + tableTokensIndexes.forEach((subtableTokensIndex, index) => { + tableTokensIndexes[index] = subtableTokensIndex.filter( + i => typeof i === 'number' || (Array.isArray(i) && i.length >= subtableMinTokenCount) + ); + }); + tableTokensIndexes = tableTokensIndexes.filter(i => i.length); + if (tableTokensIndexes.length) { + resolveSubtable(md, tokens, tableTokensIndexes, flags); + } + } + } +} + +module.exports = { + process, + markdownIt: function subTablePlugin(md, { flags = ['->'] } = {}) { + md.core.ruler.after( + 'inline', + 'subtable', + (state, startLine, endLine, silent) => { + process(md, state.tokens, flags); + }, + { + alt: ['paragraph', 'reference'], + } + ); + }, +}; diff --git a/docs/readme.md b/docs/readme.md index cc9e0eae..ff27f9b0 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -1,3 +1,17 @@ +| |原生语言插件 |uts插件| +|:------ |:------- |:--------| +|开发语言 |java/oc |uts| +|开发环境 |Android Studio/XCode |[HBuilderX](https://www.baidu.com)| +->|第一列|第二列 |第三列 | +->|:------ |:-------: |-------: | +->|左对齐 |[居中](https://www.baidu.com)|右对齐| +|打包方式 |外挂aar 等产出物 |编译时生成原生代码| +|js层调用方式 |uni.requireNativePlugin() |普通的js函数/对象,可以直接 import,支持摇树优化| +->|第一列|第二列 | +->|:------ |:------- | +->|第一列内容 |[HBuilderX](https://www.baidu.com)| +|支持项目类型 |uni-app |uni-app和uni-app x| + # uni-app x 是什么? > HBuilderX3.9+ @@ -141,7 +155,7 @@ uni-app x支持的API包括: 4. uniCloud.xxx的内置API。[详见](./api/unicloud/README.md) 5. dom的API [详见](./dom/README.md) 6. 原生API - + 由于uts可以直接调用Android和iOS的api,所以os和三方sdk的能力都可以在uts中调用。如下: ```vue @@ -307,9 +321,9 @@ uni-app x 毕竟是原生应用,内嵌flutter、rn这些没有任何问题, - 未来 uni-app js引擎版还维护吗? 维护。服务js开发者仍然是DCloud的重点。但nvue和5+将不再维护。不再维护不是下线,而是没有重大问题的话(如新手机不兼容)不会再更新了。 - + 并非所有应用都需要达到微信、抖音的性能,js引擎版如能满足你的性能需求,那继续使用js引擎版。 - + 未来vue页面也会支持uts组件。无论js引擎版还是x版,都支持uts插件生态,未来的原生扩展api和插件会是复用的。 包括官方的组件和API也会复用,比如电量API [uni.getbatteryinfo](https://ext.dcloud.net.cn/plugin?id=9295),和[lottie组件](https://ext.dcloud.net.cn/plugin?id=10674),它们使用uts开发,在 uni-app js引擎版和x版上,调用的都是一套代码。 diff --git a/package.json b/package.json index 2b17b8d4..ba9309a7 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "markdown-it-attrs": "^4.1.6", "markdown-it-raw-table": "^1.0.0", "markdown-it-task-lists": "^2.1.1", - "vuepress-theme-uni-app-test": "^1.4.6" + "vuepress-theme-uni-app-test": "^1.4.7" }, "dependencies": { "@docsearch/js": "^3.1.0", diff --git a/yarn.lock b/yarn.lock index cea94ff5..5d78e6a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9288,10 +9288,10 @@ vuepress-plugin-zooming@^1.1.8: dependencies: zooming "^2.1.1" -vuepress-theme-uni-app-test@^1.4.6: - version "1.4.6" - resolved "https://registry.npmmirror.com/vuepress-theme-uni-app-test/-/vuepress-theme-uni-app-test-1.4.6.tgz#26b73126019c0203e9cd820e2c127e0b9420662e" - integrity sha512-xArLlLQrPvywHHEz7ozBUb7ZT5GZ/quxA0/h2nJ2QZ8wWbDrnhwxDVv+1SUxq0vpVPI20M+r81U2Zz4+1JAV9w== +vuepress-theme-uni-app-test@^1.4.7: + version "1.4.7" + resolved "https://registry.npmmirror.com/vuepress-theme-uni-app-test/-/vuepress-theme-uni-app-test-1.4.7.tgz#566be747f080f551a0f65ac306ccc09dab2ab623" + integrity sha512-O+4FGNetUqEHBpz/EE7KJlwNP3LrU2iz7W1WEq2vHnowPyOxwB2DiSA1aHaHhX1zDAG4n/HILQXhjH48r4uGhw== dependencies: "@vuepress/plugin-back-to-top" "^1.9.5" "@vuepress/theme-default" "^1.8.2" -- GitLab