-
+
@@ -20,7 +20,14 @@ export default defineComponent({
using namespace std;
int main() {
- cout << "最孤独的人最亲切,受过伤的人总是笑的最灿烂。" << "—— 素媛" << endl;
+ cout <<"你" << endl;
+ cout <<"觉" << endl;
+ cout <<"得" << endl;
+ cout <<"恨" << endl;
+ cout <<"却" << endl;
+ cout <<"离" << endl;
+ cout <<"不" << endl;
+ cout <<"开" << endl;
return 0;
}`
}
diff --git a/src/code/src/Code.tsx b/src/code/src/Code.tsx
index 2f6a0cdfd..0e6fa4991 100644
--- a/src/code/src/Code.tsx
+++ b/src/code/src/Code.tsx
@@ -36,7 +36,7 @@ export const codeProps = {
uri: Boolean,
inline: Boolean,
wordWrap: Boolean,
- lineNumbers: Boolean,
+ showLineNumbers: Boolean,
// In n-log, we only need to mount code's style for highlight
internalFontSize: Number,
internalNoHighlight: Boolean
@@ -68,20 +68,10 @@ export default defineComponent({
language
}).value
}
- // reference: https://www.yangdx.com/2020/04/144.html
- const addLineNumbersForCode = (html: string): string => {
- let num = 1
- html += ''
- html = html.replace(/\r\n|\r|\n/g, function (a) {
- num++
- const text = (' ' + String(num)).slice(-4) // 最大支持到千位数
- return a + ''
- })
- html = '' + html
- html = '' + html
- return html
- }
-
+ const mergedShowLineNumbersRef = computed(() => {
+ if (props.inline || props.wordWrap) return false
+ return props.showLineNumbers
+ })
const setCode = (): void => {
if (slots.default) return
const { value: codeEl } = codeRef
@@ -93,11 +83,16 @@ export default defineComponent({
if (language) {
const html = createCodeHtml(language, code, props.trim)
if (html !== null) {
- codeEl.innerHTML = props.inline
- ? html
- : `${
- props.lineNumbers ? addLineNumbersForCode(html) : html
- }
`
+ if (props.inline) {
+ codeEl.innerHTML = html
+ } else {
+ const prevPreEl = codeEl.querySelector('.__code__')
+ if (prevPreEl) codeEl.removeChild(prevPreEl)
+ const preEl = document.createElement('pre')
+ preEl.className = '__code__'
+ preEl.innerHTML = html
+ codeEl.appendChild(preEl)
+ }
return
}
}
@@ -105,24 +100,15 @@ export default defineComponent({
codeEl.textContent = code
return
}
- const maybePreEl = codeEl.children[0]
- if (maybePreEl && maybePreEl.tagName === 'PRE') {
- if (props.lineNumbers) {
- maybePreEl.classList.add('hljsln')
- maybePreEl.innerHTML = addLineNumbersForCode(code)
- } else {
- maybePreEl.textContent = code
- }
+ const maybePreEl = codeEl.querySelector('.__code__')
+ if (maybePreEl) {
+ maybePreEl.textContent = code
} else {
- const warp = document.createElement('pre')
- if (props.lineNumbers) {
- warp.classList.add('hljsln')
- warp.innerHTML = code
- } else {
- warp.textContent = code
- }
+ const wrap = document.createElement('pre')
+ wrap.className = '__code__'
+ wrap.textContent = code
codeEl.innerHTML = ''
- codeEl.appendChild(warp)
+ codeEl.appendChild(wrap)
}
}
onMounted(setCode)
@@ -144,6 +130,7 @@ export default defineComponent({
textColor,
fontSize,
fontWeightStrong,
+ lineNumberTextColor,
// extracted from hljs atom-one-light.scss
'mono-3': $1,
'hue-1': $2,
@@ -153,9 +140,7 @@ export default defineComponent({
'hue-5': $6,
'hue-5-2': $7,
'hue-6': $8,
- 'hue-6-2': $9,
- 'padding-color': $10,
- 'line-number-color': $11
+ 'hue-6-2': $9
}
} = themeRef.value
const { internalFontSize } = props
@@ -174,8 +159,7 @@ export default defineComponent({
'--n-hue-5-2': $7,
'--n-hue-6': $8,
'--n-hue-6-2': $9,
- '--n-padding-color': $10,
- '--n-line-number-color': $11
+ '--n-line-number-text-color': lineNumberTextColor
}
})
const themeClassHandle = inlineThemeDisabled
@@ -191,25 +175,49 @@ export default defineComponent({
return {
mergedClsPrefix: mergedClsPrefixRef,
codeRef,
+ mergedShowLineNumbers: mergedShowLineNumbersRef,
+ lineNumbers: computed(() => {
+ let number = 1
+ const numbers: number[] = []
+ let lastIsLineWrap = false
+ for (const char of props.code) {
+ if (char === '\n') {
+ lastIsLineWrap = true
+ numbers.push(number++)
+ } else {
+ lastIsLineWrap = false
+ }
+ }
+ if (!lastIsLineWrap) {
+ numbers.push(number++)
+ }
+ return numbers.join('\n')
+ }),
cssVars: inlineThemeDisabled ? undefined : cssVarsRef,
themeClass: themeClassHandle?.themeClass,
onRender: themeClassHandle?.onRender
}
},
render () {
- const { mergedClsPrefix, wordWrap, onRender } = this
+ const { mergedClsPrefix, wordWrap, mergedShowLineNumbers, onRender } = this
onRender?.()
return (
- {this.$slots}
+ {mergedShowLineNumbers ? (
+
+ {this.lineNumbers}
+
+ ) : null}
+ {this.$slots.default?.()}
)
}
diff --git a/src/code/src/styles/index.cssr.ts b/src/code/src/styles/index.cssr.ts
index f6a4b05e1..8ed10d534 100644
--- a/src/code/src/styles/index.cssr.ts
+++ b/src/code/src/styles/index.cssr.ts
@@ -1,4 +1,4 @@
-import { c, cB, cM } from '../../../_utils/cssr'
+import { c, cB, cE, cM } from '../../../_utils/cssr'
// vars:
// --n-font-size
@@ -15,11 +15,23 @@ import { c, cB, cM } from '../../../_utils/cssr'
// --n-hue-5-2
// --n-hue-6
// --n-hue-6-2
+// --n-line-number-color
+// --n-line-number-text-color
export default c([
cB('code', `
font-size: var(--n-font-size);
font-family: var(--n-font-family);
`, [
+ cM('show-line-numbers', `
+ display: flex;
+ `),
+ cE('line-numbers', `
+ user-select: none;
+ padding-right: 12px;
+ text-align: right;
+ transition: color .3s var(--n-bezier);
+ color: var(--n-line-number-text-color);
+ `),
cM('word-wrap', [
c('pre', `
white-space: pre-wrap;
@@ -28,6 +40,8 @@ export default c([
]),
c('pre', `
margin: 0;
+ line-height: inherit;
+ font-size: inherit;
font-family: inherit;
`),
c('[class^=hljs]', `
@@ -97,57 +111,6 @@ export default c([
}`,
`${codeClass} .hljs-link {
text-decoration: underline;
- }`,
- // 行号显示
- `.hljsln {
- position: relative;
- display: block;
- padding-left: 3.1em !important;
- }`,
- `.hljsln::-webkit-scrollbar {
- height: 15px;
- }`,
- `.hljsln::-webkit-scrollbar-thumb {
- background: #666;
- }`,
- `.hljsln::-webkit-scrollbar-thumb:hover {
- background: #797979;
- }`,
- `.hljsln::-webkit-scrollbar-thumb:active {
- background: #949494;
- }`,
- `.hljsln .ln-bg {
- position: absolute;
- z-index: 1;
- top: 0;
- left: 0;
- width: 2.4em;
- height: 100%;
- background: var(--n-padding-color);
- }`,
- `.hljsln .ln-num {
- position: absolute;
- z-index: 2;
- left: 0;
- width: 2.4em;
- height: 1em;
- text-align: center;
- display: inline-block;
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -khtml-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- }`,
- `.hljsln .ln-num::before {
- color: var(--n-line-number-color);
- font-style: normal;
- font-weight: normal;
- content: attr(data-num);
- }`,
- `.hljsln .ln-eof {
- display: inline-block;
}`
]
}
diff --git a/src/code/styles/dark.ts b/src/code/styles/dark.ts
index f344ee062..46dcf5ab5 100644
--- a/src/code/styles/dark.ts
+++ b/src/code/styles/dark.ts
@@ -21,8 +21,7 @@ const codeDark: CodeTheme = {
'hue-6': '#d19a66',
'hue-6-2': '#e6c07b',
// line-number styles
- 'padding-color': 'rgb(39, 39, 39)',
- 'line-number-color': textColor3
+ lineNumberTextColor: textColor3
}
}
}
diff --git a/src/code/styles/light.ts b/src/code/styles/light.ts
index 1f5bc9ddd..3ecb2d448 100644
--- a/src/code/styles/light.ts
+++ b/src/code/styles/light.ts
@@ -19,8 +19,7 @@ const self = (vars: ThemeCommonVars) => {
'hue-6': '#986801',
'hue-6-2': '#c18401',
// line-number styles
- 'padding-color': 'rgb(243, 243, 243)',
- 'line-number-color': textColor3
+ lineNumberTextColor: textColor3
}
}