This is an automated email from the ASF dual-hosted git repository.
critas pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iotdb-docs.git
The following commit(s) were added to refs/heads/main by this push:
new f6936768 Add convert single line button to code block with sql
language (#1033)
f6936768 is described below
commit f6936768aca3b11efaddbf863ac6344d47b8d9a1
Author: LimJiaWenBrenda <[email protected]>
AuthorDate: Fri Mar 27 17:02:53 2026 +0800
Add convert single line button to code block with sql language (#1033)
---
src/.vuepress/client.ts | 88 +++++++++++++++++++++++++++++++++++++++++
src/.vuepress/styles/index.scss | 50 +++++++++++++++++++++++
2 files changed, 138 insertions(+)
diff --git a/src/.vuepress/client.ts b/src/.vuepress/client.ts
index 69dd8a27..33b2fae3 100644
--- a/src/.vuepress/client.ts
+++ b/src/.vuepress/client.ts
@@ -18,6 +18,7 @@
import { defineDocSearchConfig } from '@vuepress/plugin-docsearch/client';
import { computed } from 'vue';
+import { onMounted, nextTick } from 'vue';
import {
defineClientConfig,
usePageData,
@@ -52,6 +53,93 @@ export default defineClientConfig({
lastTo = to.fullPath;
});
+ function addConvertSingleLineButton() {
+ if (typeof document === 'undefined') return;
+
+ const blocks =
document.querySelectorAll<HTMLElement>('div[class*="language-sql"] pre');
+ const copyIcon = `<svg t="1773227012571" class="icon" viewBox="0 0 1024
1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7157" width="18px"
height="18px"><path d="M860.253405 512.000461a431.238022 431.238022 0 0
0-139.308875-316.862415A40.958141 40.958141 0 1 0 665.702238
255.448908a348.144194 348.144194 0 0 1-202.691598
603.108619l30.718605-30.718605a41.019578 41.019578 0 0
0-57.904571-58.109362l-81.301909 81.301909a56.317443 56.317443 0 0 0 0
79.663583l81.301909 81.30 [...]
+ const tipContent = pageData.value.lang === 'zh-CN' ? '已转换为单行' :
'Converted as single line';
+ const hoverTipContent = pageData.value.lang === 'zh-CN' ? '转换为单行' :
'Convert as single line';
+ const copyTipContent = pageData.value.lang === 'zh-CN' ? '复制内容' : 'Copy
content';
+
+ blocks.forEach((pre) => {
+ if (pre.querySelector('.copy-one-line-btn')) return;
+
+ const parentEl = pre.parentElement;
+ if (!parentEl) return;
+ const lineNumbers =
parentEl.querySelector('div[class="line-numbers"]');
+ if (!lineNumbers) return;
+ const copyBtn =
parentEl.querySelector<HTMLElement>('button[class*="vp-copy-code-button"]');
+ if (!copyBtn) return;
+ copyBtn.title = copyTipContent;
+
+ const code = pre.querySelector('code');
+ if (!code) return;
+
+ const copiedTooltip = document.createElement('div');
+ copiedTooltip.className = 'copy-one-line-tooltip';
+ pre.appendChild(copiedTooltip);
+
+ const btn = document.createElement('button');
+ btn.innerHTML = copyIcon;
+ btn.className = 'copy-one-line-btn';
+ btn.title = hoverTipContent;
+
+ btn.onclick = () => {
+ const text = code.innerText;
+ const lines = text.split('\n');
+
+ const single = lines
+ .map((line, i) => {
+ const trimmed = line.trim();
+ if (!trimmed || trimmed === '') return '';
+ console.log('line', trimmed);
+ if (i === lines.length - 1) return trimmed;
+ if (trimmed.endsWith(';')) {
+ return trimmed + '\n';
+ }
+ if (trimmed.endsWith('\\')) {
+ return trimmed.slice(0, -1) + ' ';
+ }
+ return trimmed + ' ';
+ })
+ .join('');
+
+ const convertedSpan = single.split('\n').map((line) => `<span
class="line"><span>${line}\n</span></span>`).join('');
+ const counter = single.split('\n').length;
+ code.innerHTML = convertedSpan;
+ if (lineNumbers) {
+ const childCount = lineNumbers.children.length;
+ for (let i = counter; i < childCount; i++) {
+ const child = lineNumbers.children[0];
+ lineNumbers.removeChild(child);
+ }
+ }
+
+ btn.style.opacity = '80';
+ btn.style.backgroundColor = 'rgb(47, 53, 66)';
+ copiedTooltip.style.opacity = '100';
+ copiedTooltip.innerText = tipContent;
+
+ setTimeout(() => {
+ btn.style.backgroundColor = '';
+ copiedTooltip.innerText = '';
+ btn.style.visibility = 'hidden';
+ copiedTooltip.style.visibility = 'hidden';
+ }, 1500);
+ };
+ pre.appendChild(btn);
+ });
+ }
+
+ onMounted(() => {
+ nextTick(() => addConvertSingleLineButton());
+ });
+
+ router.afterEach(() => {
+ nextTick(() => addConvertSingleLineButton());
+ });
+
const docSearchConfig = computed(() => ({
appId: 'JLT9R2YGAE',
apiKey: 'f1f30c0df04d74534e066d07786bce05',
diff --git a/src/.vuepress/styles/index.scss b/src/.vuepress/styles/index.scss
index 4e1531e1..90f6c43b 100644
--- a/src/.vuepress/styles/index.scss
+++ b/src/.vuepress/styles/index.scss
@@ -16,6 +16,56 @@
* limitations under the License.
*/
+.copy-one-line-tooltip {
+ position: absolute;
+ right: 95px;
+ top: 8px;
+ padding: 10px 10px 7px;
+ background-color: rgb(47, 53, 66);
+ border-radius: 8px;
+ opacity: 0;
+ font-family: var(--vp-font);
+ font-size: 13px;
+}
+
+.copy-one-line-btn {
+ position: absolute;
+ right: 50px;
+ top: 8px;
+ padding: 10px 10px 7px;
+ background-color: transparent;
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ opacity: 0;
+ transition: opacity 0.3s ease;
+}
+
+ .copy-one-line-btn:hover::before {
+ content: attr(data-tooltip);
+ position: absolute;
+ bottom: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ padding: 4px 8px;
+ background: rgba(0, 0, 0, 0.8);
+ color: white;
+ font-size: 12px;
+ border-radius: 4px;
+ white-space: nowrap;
+ margin-bottom: 6px;
+ pointer-events: none;
+ z-index: 1000;
+ }
+
+.language-sql pre:hover .copy-one-line-btn {
+ opacity: 0.8;
+}
+
+.copy-one-line-btn:hover {
+ background-color: rgb(47, 53, 66);
+}
+
#main-description {
max-width: 55rem;
}