@ant-design/x-markdown-mini 0.1.0-beta.0 → 0.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Markdown/index.acss +65 -7
- package/dist/components/MiniNodeRenderer/index.acss +19 -4
- package/dist/components/MiniNodeRenderer/index.axml +109 -29
- package/dist/components/MiniNodeRenderer/index.js +12 -0
- package/dist/components/MiniNodeRenderer/index.sjs +48 -0
- package/dist/es/Markdown/index.acss +65 -7
- package/dist/es/MiniNodeRenderer/index.acss +19 -4
- package/dist/es/MiniNodeRenderer/index.axml +109 -29
- package/dist/es/MiniNodeRenderer/index.js +12 -0
- package/dist/es/MiniNodeRenderer/index.sjs +48 -0
- package/dist/index.d.mts +39 -1
- package/dist/index.d.ts +39 -1
- package/dist/index.js +134 -56
- package/dist/index.mjs +134 -56
- package/dist/miniprogram_dist/components/Markdown/index.json +1 -1
- package/dist/miniprogram_dist/components/Markdown/index.wxss +65 -7
- package/dist/miniprogram_dist/components/MiniNodeRenderer/index.js +12 -0
- package/dist/miniprogram_dist/components/MiniNodeRenderer/index.json +1 -1
- package/dist/miniprogram_dist/components/MiniNodeRenderer/index.wxml +98 -21
- package/dist/miniprogram_dist/components/MiniNodeRenderer/index.wxs +41 -0
- package/dist/miniprogram_dist/components/MiniNodeRenderer/index.wxss +13 -2
- package/dist/miniprogram_dist/es/Markdown/index.json +1 -1
- package/dist/miniprogram_dist/es/Markdown/index.wxss +65 -7
- package/dist/miniprogram_dist/es/MiniNodeRenderer/index.js +12 -0
- package/dist/miniprogram_dist/es/MiniNodeRenderer/index.json +1 -1
- package/dist/miniprogram_dist/es/MiniNodeRenderer/index.wxml +98 -21
- package/dist/miniprogram_dist/es/MiniNodeRenderer/index.wxs +41 -0
- package/dist/miniprogram_dist/es/MiniNodeRenderer/index.wxss +13 -2
- package/dist/miniprogram_dist/index.js +134 -56
- package/dist/miniprogram_dist/plugins/CodeHighlight/index.js +13 -5
- package/dist/miniprogram_dist/plugins/CodeHighlight/style.wxss +41 -31
- package/dist/miniprogram_dist/plugins/Latex/index.js +44 -23
- package/dist/miniprogram_dist/plugins/Latex/style.wxss +11 -11
- package/dist/miniprogram_dist/shared/flattenInline.js +33 -5
- package/dist/plugins/CodeHighlight/index.d.mts +1 -1
- package/dist/plugins/CodeHighlight/index.d.ts +1 -1
- package/dist/plugins/CodeHighlight/index.js +13 -5
- package/dist/plugins/CodeHighlight/index.mjs +13 -5
- package/dist/plugins/CodeHighlight/style.acss +41 -31
- package/dist/plugins/Latex/index.d.mts +1 -1
- package/dist/plugins/Latex/index.d.ts +1 -1
- package/dist/plugins/Latex/index.js +44 -23
- package/dist/plugins/Latex/index.mjs +47 -23
- package/dist/plugins/Latex/style.acss +11 -6
- package/dist/shared/flattenInline.js +33 -5
- package/dist/{types-CegkonfJ.d.mts → types-BcxGtbQZ.d.mts} +25 -0
- package/dist/{types-CegkonfJ.d.ts → types-BcxGtbQZ.d.ts} +25 -0
- package/package.json +3 -2
|
@@ -45,11 +45,47 @@
|
|
|
45
45
|
|
|
46
46
|
.md-code-block {
|
|
47
47
|
display: block;
|
|
48
|
-
margin: 12rpx 0;
|
|
49
48
|
padding: 16rpx;
|
|
50
49
|
background: #f6f8fa;
|
|
51
|
-
border-radius: 8rpx;
|
|
52
50
|
overflow-x: auto;
|
|
51
|
+
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
|
52
|
+
font-size: 26rpx;
|
|
53
|
+
line-height: 1.6;
|
|
54
|
+
white-space: pre;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* code & table cards share a captioned header bar with an icon copy button */
|
|
58
|
+
.md-codeblock,
|
|
59
|
+
.md-tableblock {
|
|
60
|
+
margin: 16rpx 0;
|
|
61
|
+
border: 2rpx solid #eceef1;
|
|
62
|
+
border-radius: 16rpx;
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
}
|
|
65
|
+
.md-codeblock-bar,
|
|
66
|
+
.md-tableblock-bar {
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: space-between;
|
|
70
|
+
height: 64rpx;
|
|
71
|
+
padding: 0 24rpx;
|
|
72
|
+
background: #eceef2;
|
|
73
|
+
font-size: 24rpx;
|
|
74
|
+
color: #4e5969;
|
|
75
|
+
}
|
|
76
|
+
.md-codeblock-lang {
|
|
77
|
+
text-transform: uppercase;
|
|
78
|
+
letter-spacing: 1rpx;
|
|
79
|
+
font-weight: 600;
|
|
80
|
+
color: #1d2129;
|
|
81
|
+
}
|
|
82
|
+
.md-tableblock-title {
|
|
83
|
+
font-weight: 600;
|
|
84
|
+
color: #1d2129;
|
|
85
|
+
}
|
|
86
|
+
.md-copy-icon {
|
|
87
|
+
width: 32rpx;
|
|
88
|
+
height: 32rpx;
|
|
53
89
|
}
|
|
54
90
|
|
|
55
91
|
.md-code {
|
|
@@ -78,6 +114,8 @@
|
|
|
78
114
|
.md-img {
|
|
79
115
|
display: block;
|
|
80
116
|
max-width: 100%;
|
|
117
|
+
margin: 16rpx 0;
|
|
118
|
+
border-radius: 12rpx;
|
|
81
119
|
}
|
|
82
120
|
|
|
83
121
|
.md-hr {
|
|
@@ -87,17 +125,37 @@
|
|
|
87
125
|
margin: 16rpx 0;
|
|
88
126
|
}
|
|
89
127
|
|
|
90
|
-
.md-
|
|
128
|
+
/* table body scrolls horizontally inside the .md-tableblock card */
|
|
129
|
+
.md-table-scroll {
|
|
91
130
|
display: block;
|
|
92
131
|
width: 100%;
|
|
93
|
-
|
|
94
|
-
|
|
132
|
+
overflow: hidden;
|
|
133
|
+
white-space: nowrap;
|
|
95
134
|
}
|
|
135
|
+
.md-table {
|
|
136
|
+
display: table;
|
|
137
|
+
table-layout: auto;
|
|
138
|
+
width: max-content;
|
|
139
|
+
min-width: 100%;
|
|
140
|
+
border-collapse: separate;
|
|
141
|
+
border-spacing: 0;
|
|
142
|
+
font-size: 26rpx;
|
|
143
|
+
}
|
|
144
|
+
.md-tr { display: table-row; }
|
|
96
145
|
.md-th, .md-td {
|
|
97
146
|
display: table-cell;
|
|
98
|
-
padding:
|
|
99
|
-
|
|
147
|
+
padding: 12rpx 20rpx;
|
|
148
|
+
max-width: 480rpx;
|
|
149
|
+
border-right: 2rpx solid #e5e5e5;
|
|
150
|
+
border-bottom: 2rpx solid #e5e5e5;
|
|
151
|
+
text-align: left;
|
|
152
|
+
vertical-align: top;
|
|
153
|
+
word-break: break-word;
|
|
154
|
+
white-space: normal;
|
|
100
155
|
}
|
|
101
156
|
.md-th { background: #fafafa; font-weight: 600; }
|
|
157
|
+
.md-tr .md-th:last-child,
|
|
158
|
+
.md-tr .md-td:last-child { border-right: none; }
|
|
159
|
+
.md-table .md-tr:last-child .md-td { border-bottom: none; }
|
|
102
160
|
|
|
103
161
|
.md-html { display: block; }
|
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
.md-animate-block {
|
|
2
2
|
animation-fill-mode: forwards;
|
|
3
3
|
animation-name: md-block-appear;
|
|
4
|
-
animation-timing-function:
|
|
5
|
-
animation-duration:
|
|
4
|
+
animation-timing-function: ease-in;
|
|
5
|
+
animation-duration: 300ms;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
/* 纯透明度淡入:不做 translateY 位移,避免流式逐字重渲染时块体上下抖动。 */
|
|
8
9
|
@keyframes md-block-appear {
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
from { opacity: 0.3; }
|
|
11
|
+
to { opacity: 1; }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* 流式逐字淡入:每个新字符从透明渐显,已显示的字符(按下标复用)不会重播。
|
|
15
|
+
Alipay 不能嵌套 <text>,包裹层用 inline view 维持文本流。 */
|
|
16
|
+
.md-anim-text {
|
|
17
|
+
display: inline;
|
|
18
|
+
}
|
|
19
|
+
.md-anim-char {
|
|
20
|
+
opacity: 0;
|
|
21
|
+
animation: md-char-in 360ms ease-out forwards;
|
|
22
|
+
}
|
|
23
|
+
@keyframes md-char-in {
|
|
24
|
+
from { opacity: 0; }
|
|
25
|
+
to { opacity: 1; }
|
|
11
26
|
}
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
<import-sjs from="./index.sjs" name="u" />
|
|
2
2
|
|
|
3
3
|
<block a:for="{{nodes}}" a:for-item="node" a:for-index="i" a:key="i">
|
|
4
|
-
<!-- text leaf
|
|
4
|
+
<!-- text leaf: 流式时逐字淡入(Alipay 不能嵌套 <text>,用 inline <view> 包裹字符 <text>,
|
|
5
|
+
按下标 key 复用,只有新字触发动画);非流式时整段渲染为单个 <text>。 -->
|
|
6
|
+
<view
|
|
7
|
+
a:if="{{u.isText(node.name) && animation}}"
|
|
8
|
+
class="md-anim-text {{u.classOf(node)}}"
|
|
9
|
+
>
|
|
10
|
+
<text
|
|
11
|
+
a:for="{{u.charsOf(node)}}"
|
|
12
|
+
a:for-item="ch"
|
|
13
|
+
a:for-index="ci"
|
|
14
|
+
a:key="ci"
|
|
15
|
+
class="md-anim-char"
|
|
16
|
+
selectable="{{selectable}}"
|
|
17
|
+
>{{ch}}</text>
|
|
18
|
+
</view>
|
|
5
19
|
<text
|
|
6
|
-
a:
|
|
20
|
+
a:elif="{{u.isText(node.name)}}"
|
|
7
21
|
class="{{u.classOf(node)}}"
|
|
8
22
|
selectable="{{selectable}}"
|
|
9
23
|
>{{u.valueOf(node)}}</text>
|
|
@@ -26,34 +40,101 @@
|
|
|
26
40
|
onAppear="_appear"
|
|
27
41
|
/>
|
|
28
42
|
|
|
29
|
-
<!-- pre: scrollable
|
|
30
|
-
<
|
|
43
|
+
<!-- pre: code block with language label + copy toolbar, scrollable body -->
|
|
44
|
+
<view
|
|
31
45
|
a:elif="{{u.isPre(node.name)}}"
|
|
32
|
-
|
|
33
|
-
class="{{u.classOf(node)}}"
|
|
34
|
-
style="{{u.styleOf(node)}}"
|
|
35
|
-
data-data="{{node}}"
|
|
36
|
-
catchTap="_tap"
|
|
46
|
+
class="md-codeblock {{node.animate ? 'md-animate-block' : ''}}"
|
|
37
47
|
>
|
|
38
|
-
<
|
|
39
|
-
a:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
<view a:if="{{node.header}}" class="md-codeblock-bar">
|
|
49
|
+
<block a:for="{{node.header}}" a:for-item="h" a:for-index="hi" a:key="hi">
|
|
50
|
+
<text a:if="{{u.isText(h.name)}}" class="{{u.classOf(h)}}">{{u.valueOf(h)}}</text>
|
|
51
|
+
<image
|
|
52
|
+
a:elif="{{u.isCopy(h.name)}}"
|
|
53
|
+
class="{{u.classOf(h) || 'md-copy-icon'}}"
|
|
54
|
+
src="https://mdn.alipayobjects.com/huamei_y8xg5f/afts/img/JXzqSoHDzm4AAAAAHpAAAAgADuJhAQFr/original"
|
|
55
|
+
data-copy="{{u.copyOf(h)}}"
|
|
56
|
+
catchTap="_copy"
|
|
57
|
+
/>
|
|
58
|
+
<view a:else class="{{u.classOf(h)}}" style="{{u.styleOf(h)}}">
|
|
59
|
+
<mini-node-renderer
|
|
60
|
+
a:if="{{h.children}}"
|
|
61
|
+
nodes="{{h.children}}"
|
|
62
|
+
selectable="{{selectable}}"
|
|
63
|
+
animation="{{false}}"
|
|
64
|
+
slotComponents="{{slotComponents}}"
|
|
65
|
+
onTap="onTap"
|
|
66
|
+
>
|
|
67
|
+
<slot slot-scope="prop" data="{{prop.data}}" />
|
|
68
|
+
</mini-node-renderer>
|
|
69
|
+
</view>
|
|
70
|
+
</block>
|
|
71
|
+
</view>
|
|
72
|
+
<scroll-view scroll-x class="md-code-block">
|
|
73
|
+
<mini-node-renderer
|
|
74
|
+
a:if="{{node.children}}"
|
|
75
|
+
nodes="{{node.children}}"
|
|
76
|
+
selectable="{{selectable}}"
|
|
77
|
+
animation="{{false}}"
|
|
78
|
+
slotComponents="{{slotComponents}}"
|
|
79
|
+
onTap="onTap"
|
|
80
|
+
onAppear="onAppear"
|
|
81
|
+
>
|
|
82
|
+
<slot slot-scope="prop" data="{{prop.data}}" />
|
|
83
|
+
</mini-node-renderer>
|
|
84
|
+
</scroll-view>
|
|
85
|
+
</view>
|
|
86
|
+
|
|
87
|
+
<!-- table: caption + copy toolbar card, horizontal-scroll CSS table (columns kept aligned) -->
|
|
88
|
+
<view
|
|
89
|
+
a:elif="{{u.isTable(node.name)}}"
|
|
90
|
+
class="md-tableblock {{node.animate ? 'md-animate-block' : ''}}"
|
|
91
|
+
>
|
|
92
|
+
<view a:if="{{node.header}}" class="md-tableblock-bar">
|
|
93
|
+
<block a:for="{{node.header}}" a:for-item="h" a:for-index="hi" a:key="hi">
|
|
94
|
+
<text a:if="{{u.isText(h.name)}}" class="{{u.classOf(h)}}">{{u.valueOf(h)}}</text>
|
|
95
|
+
<image
|
|
96
|
+
a:elif="{{u.isCopy(h.name)}}"
|
|
97
|
+
class="{{u.classOf(h) || 'md-copy-icon'}}"
|
|
98
|
+
src="https://mdn.alipayobjects.com/huamei_y8xg5f/afts/img/JXzqSoHDzm4AAAAAHpAAAAgADuJhAQFr/original"
|
|
99
|
+
data-copy="{{u.copyOf(h)}}"
|
|
100
|
+
catchTap="_copy"
|
|
101
|
+
/>
|
|
102
|
+
<view a:else class="{{u.classOf(h)}}" style="{{u.styleOf(h)}}">
|
|
103
|
+
<mini-node-renderer
|
|
104
|
+
a:if="{{h.children}}"
|
|
105
|
+
nodes="{{h.children}}"
|
|
106
|
+
selectable="{{selectable}}"
|
|
107
|
+
animation="{{false}}"
|
|
108
|
+
slotComponents="{{slotComponents}}"
|
|
109
|
+
onTap="onTap"
|
|
110
|
+
>
|
|
111
|
+
<slot slot-scope="prop" data="{{prop.data}}" />
|
|
112
|
+
</mini-node-renderer>
|
|
113
|
+
</view>
|
|
114
|
+
</block>
|
|
115
|
+
</view>
|
|
116
|
+
<scroll-view scroll-x class="md-table-scroll">
|
|
117
|
+
<view class="md-table">
|
|
118
|
+
<mini-node-renderer
|
|
119
|
+
a:if="{{node.children}}"
|
|
120
|
+
nodes="{{node.children}}"
|
|
121
|
+
selectable="{{selectable}}"
|
|
122
|
+
animation="{{false}}"
|
|
123
|
+
slotComponents="{{slotComponents}}"
|
|
124
|
+
onTap="onTap"
|
|
125
|
+
onAppear="onAppear"
|
|
126
|
+
>
|
|
127
|
+
<slot slot-scope="prop" data="{{prop.data}}" />
|
|
128
|
+
</mini-node-renderer>
|
|
129
|
+
</view>
|
|
130
|
+
</scroll-view>
|
|
131
|
+
</view>
|
|
50
132
|
|
|
51
133
|
<!-- anchor: kept interactive, children are already flattened text runs -->
|
|
52
|
-
<
|
|
134
|
+
<view
|
|
53
135
|
a:elif="{{node.name === 'a'}}"
|
|
54
136
|
class="{{u.classOf(node)}}"
|
|
55
137
|
style="{{u.styleOf(node)}}"
|
|
56
|
-
selectable="{{selectable}}"
|
|
57
138
|
data-data="{{node}}"
|
|
58
139
|
catchTap="_tap"
|
|
59
140
|
>
|
|
@@ -64,14 +145,13 @@
|
|
|
64
145
|
a:key="ci"
|
|
65
146
|
class="{{u.classOf(c)}}"
|
|
66
147
|
>{{u.valueOf(c)}}</text>
|
|
67
|
-
</
|
|
148
|
+
</view>
|
|
68
149
|
|
|
69
|
-
<!-- inline tag rendered as
|
|
70
|
-
<
|
|
71
|
-
a:elif="{{u.isInline(node.name)}}"
|
|
150
|
+
<!-- inline tag rendered as a flat container because Alipay SDK 2.x rejects nested <text>. -->
|
|
151
|
+
<view
|
|
152
|
+
a:elif="{{u.isInline(node.name) && !u.isRich(node)}}"
|
|
72
153
|
class="{{u.classOf(node)}}"
|
|
73
154
|
style="{{u.styleOf(node)}}"
|
|
74
|
-
selectable="{{selectable}}"
|
|
75
155
|
data-data="{{node}}"
|
|
76
156
|
catchTap="_tap"
|
|
77
157
|
>
|
|
@@ -82,7 +162,7 @@
|
|
|
82
162
|
a:key="ci"
|
|
83
163
|
class="{{u.classOf(c)}}"
|
|
84
164
|
>{{u.valueOf(c)}}</text>
|
|
85
|
-
</
|
|
165
|
+
</view>
|
|
86
166
|
|
|
87
167
|
<!-- custom component: hand off to host scoped slot, keyed by node.tag -->
|
|
88
168
|
<slot
|
|
@@ -16,6 +16,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
16
16
|
// src/components/alipay/MiniNodeRenderer/index.ts
|
|
17
17
|
var MiniNodeRenderer_exports = {};
|
|
18
18
|
module.exports = __toCommonJS(MiniNodeRenderer_exports);
|
|
19
|
+
function copyToClipboard(text) {
|
|
20
|
+
if (!text) return;
|
|
21
|
+
my.setClipboard({
|
|
22
|
+
text,
|
|
23
|
+
success: () => my.showToast({ content: "\u5DF2\u590D\u5236", duration: 1200 }),
|
|
24
|
+
fail: () => my.showToast({ content: "\u590D\u5236\u5931\u8D25" })
|
|
25
|
+
});
|
|
26
|
+
}
|
|
19
27
|
var defaultProps = {
|
|
20
28
|
nodes: [],
|
|
21
29
|
selectable: true,
|
|
@@ -32,6 +40,10 @@ Component({
|
|
|
32
40
|
_appear(e) {
|
|
33
41
|
var _a, _b;
|
|
34
42
|
(_b = (_a = this.props).onAppear) == null ? void 0 : _b.call(_a, e);
|
|
43
|
+
},
|
|
44
|
+
_copy(e) {
|
|
45
|
+
const ds = e && e.currentTarget && e.currentTarget.dataset;
|
|
46
|
+
copyToClipboard(ds && ds.copy || "");
|
|
35
47
|
}
|
|
36
48
|
}
|
|
37
49
|
});
|
|
@@ -13,6 +13,23 @@ function isBr(name) { return name === 'br'; }
|
|
|
13
13
|
function isImg(name) { return name === 'img'; }
|
|
14
14
|
function isHr(name) { return name === 'hr'; }
|
|
15
15
|
function isPre(name) { return name === 'pre'; }
|
|
16
|
+
function isTable(name) { return name === 'table'; }
|
|
17
|
+
function isCopy(name) { return name === 'copy-button'; }
|
|
18
|
+
function copyOf(node) {
|
|
19
|
+
var attrs = node.attrs || {};
|
|
20
|
+
return attrs['data-copy'] || '';
|
|
21
|
+
}
|
|
22
|
+
// 富内联节点(如 KaTeX 公式容器)含有元素子节点,必须走递归 <view> 路径
|
|
23
|
+
// 渲染,保留嵌套结构与 style;普通已扁平化的内联只有 text/br 子节点。
|
|
24
|
+
function isRich(node) {
|
|
25
|
+
var ch = node.children;
|
|
26
|
+
if (!ch) return false;
|
|
27
|
+
for (var i = 0; i < ch.length; i++) {
|
|
28
|
+
var nm = ch[i].name;
|
|
29
|
+
if (nm !== 'text' && nm !== 'br') return true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
16
33
|
function isSlot(name, slotComponents) {
|
|
17
34
|
return !!slotComponents && slotComponents.indexOf(name) > -1;
|
|
18
35
|
}
|
|
@@ -26,6 +43,26 @@ function classOf(node) {
|
|
|
26
43
|
return cls;
|
|
27
44
|
}
|
|
28
45
|
|
|
46
|
+
// 把文本拆成「按 code point 安全」的字符数组(不劈坏 emoji/组合 surrogate pair),
|
|
47
|
+
// 供流式逐字淡入:每个字符渲染成独立 <text>,按下标 key 复用,只有新字符会触发淡入动画。
|
|
48
|
+
function charsOf(node) {
|
|
49
|
+
var v = (node.attrs || {}).value || '';
|
|
50
|
+
var out = [];
|
|
51
|
+
var i = 0;
|
|
52
|
+
var n = v.length;
|
|
53
|
+
while (i < n) {
|
|
54
|
+
var code = v.charCodeAt(i);
|
|
55
|
+
if (code >= 55296 && code <= 56319 && i + 1 < n) {
|
|
56
|
+
out.push(v.charAt(i) + v.charAt(i + 1));
|
|
57
|
+
i += 2;
|
|
58
|
+
} else {
|
|
59
|
+
out.push(v.charAt(i));
|
|
60
|
+
i += 1;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
|
|
29
66
|
function styleOf(node) {
|
|
30
67
|
var attrs = node.attrs || {};
|
|
31
68
|
return attrs.style || '';
|
|
@@ -36,6 +73,11 @@ function srcOf(node) {
|
|
|
36
73
|
return attrs.src || '';
|
|
37
74
|
}
|
|
38
75
|
|
|
76
|
+
function langOf(node) {
|
|
77
|
+
var attrs = node.attrs || {};
|
|
78
|
+
return attrs.lang || '';
|
|
79
|
+
}
|
|
80
|
+
|
|
39
81
|
function altOf(node) {
|
|
40
82
|
var attrs = node.attrs || {};
|
|
41
83
|
return attrs.alt || '';
|
|
@@ -54,10 +96,16 @@ export default {
|
|
|
54
96
|
isImg: isImg,
|
|
55
97
|
isHr: isHr,
|
|
56
98
|
isPre: isPre,
|
|
99
|
+
isTable: isTable,
|
|
100
|
+
isCopy: isCopy,
|
|
101
|
+
copyOf: copyOf,
|
|
102
|
+
isRich: isRich,
|
|
57
103
|
isSlot: isSlot,
|
|
58
104
|
classOf: classOf,
|
|
105
|
+
charsOf: charsOf,
|
|
59
106
|
styleOf: styleOf,
|
|
60
107
|
srcOf: srcOf,
|
|
108
|
+
langOf: langOf,
|
|
61
109
|
altOf: altOf,
|
|
62
110
|
valueOf: valueOf,
|
|
63
111
|
};
|
|
@@ -45,11 +45,47 @@
|
|
|
45
45
|
|
|
46
46
|
.md-code-block {
|
|
47
47
|
display: block;
|
|
48
|
-
margin: 12rpx 0;
|
|
49
48
|
padding: 16rpx;
|
|
50
49
|
background: #f6f8fa;
|
|
51
|
-
border-radius: 8rpx;
|
|
52
50
|
overflow-x: auto;
|
|
51
|
+
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
|
52
|
+
font-size: 26rpx;
|
|
53
|
+
line-height: 1.6;
|
|
54
|
+
white-space: pre;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* code & table cards share a captioned header bar with an icon copy button */
|
|
58
|
+
.md-codeblock,
|
|
59
|
+
.md-tableblock {
|
|
60
|
+
margin: 16rpx 0;
|
|
61
|
+
border: 2rpx solid #eceef1;
|
|
62
|
+
border-radius: 16rpx;
|
|
63
|
+
overflow: hidden;
|
|
64
|
+
}
|
|
65
|
+
.md-codeblock-bar,
|
|
66
|
+
.md-tableblock-bar {
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: space-between;
|
|
70
|
+
height: 64rpx;
|
|
71
|
+
padding: 0 24rpx;
|
|
72
|
+
background: #eceef2;
|
|
73
|
+
font-size: 24rpx;
|
|
74
|
+
color: #4e5969;
|
|
75
|
+
}
|
|
76
|
+
.md-codeblock-lang {
|
|
77
|
+
text-transform: uppercase;
|
|
78
|
+
letter-spacing: 1rpx;
|
|
79
|
+
font-weight: 600;
|
|
80
|
+
color: #1d2129;
|
|
81
|
+
}
|
|
82
|
+
.md-tableblock-title {
|
|
83
|
+
font-weight: 600;
|
|
84
|
+
color: #1d2129;
|
|
85
|
+
}
|
|
86
|
+
.md-copy-icon {
|
|
87
|
+
width: 32rpx;
|
|
88
|
+
height: 32rpx;
|
|
53
89
|
}
|
|
54
90
|
|
|
55
91
|
.md-code {
|
|
@@ -78,6 +114,8 @@
|
|
|
78
114
|
.md-img {
|
|
79
115
|
display: block;
|
|
80
116
|
max-width: 100%;
|
|
117
|
+
margin: 16rpx 0;
|
|
118
|
+
border-radius: 12rpx;
|
|
81
119
|
}
|
|
82
120
|
|
|
83
121
|
.md-hr {
|
|
@@ -87,17 +125,37 @@
|
|
|
87
125
|
margin: 16rpx 0;
|
|
88
126
|
}
|
|
89
127
|
|
|
90
|
-
.md-
|
|
128
|
+
/* table body scrolls horizontally inside the .md-tableblock card */
|
|
129
|
+
.md-table-scroll {
|
|
91
130
|
display: block;
|
|
92
131
|
width: 100%;
|
|
93
|
-
|
|
94
|
-
|
|
132
|
+
overflow: hidden;
|
|
133
|
+
white-space: nowrap;
|
|
95
134
|
}
|
|
135
|
+
.md-table {
|
|
136
|
+
display: table;
|
|
137
|
+
table-layout: auto;
|
|
138
|
+
width: max-content;
|
|
139
|
+
min-width: 100%;
|
|
140
|
+
border-collapse: separate;
|
|
141
|
+
border-spacing: 0;
|
|
142
|
+
font-size: 26rpx;
|
|
143
|
+
}
|
|
144
|
+
.md-tr { display: table-row; }
|
|
96
145
|
.md-th, .md-td {
|
|
97
146
|
display: table-cell;
|
|
98
|
-
padding:
|
|
99
|
-
|
|
147
|
+
padding: 12rpx 20rpx;
|
|
148
|
+
max-width: 480rpx;
|
|
149
|
+
border-right: 2rpx solid #e5e5e5;
|
|
150
|
+
border-bottom: 2rpx solid #e5e5e5;
|
|
151
|
+
text-align: left;
|
|
152
|
+
vertical-align: top;
|
|
153
|
+
word-break: break-word;
|
|
154
|
+
white-space: normal;
|
|
100
155
|
}
|
|
101
156
|
.md-th { background: #fafafa; font-weight: 600; }
|
|
157
|
+
.md-tr .md-th:last-child,
|
|
158
|
+
.md-tr .md-td:last-child { border-right: none; }
|
|
159
|
+
.md-table .md-tr:last-child .md-td { border-bottom: none; }
|
|
102
160
|
|
|
103
161
|
.md-html { display: block; }
|
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
.md-animate-block {
|
|
2
2
|
animation-fill-mode: forwards;
|
|
3
3
|
animation-name: md-block-appear;
|
|
4
|
-
animation-timing-function:
|
|
5
|
-
animation-duration:
|
|
4
|
+
animation-timing-function: ease-in;
|
|
5
|
+
animation-duration: 300ms;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
/* 纯透明度淡入:不做 translateY 位移,避免流式逐字重渲染时块体上下抖动。 */
|
|
8
9
|
@keyframes md-block-appear {
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
from { opacity: 0.3; }
|
|
11
|
+
to { opacity: 1; }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* 流式逐字淡入:每个新字符从透明渐显,已显示的字符(按下标复用)不会重播。
|
|
15
|
+
Alipay 不能嵌套 <text>,包裹层用 inline view 维持文本流。 */
|
|
16
|
+
.md-anim-text {
|
|
17
|
+
display: inline;
|
|
18
|
+
}
|
|
19
|
+
.md-anim-char {
|
|
20
|
+
opacity: 0;
|
|
21
|
+
animation: md-char-in 360ms ease-out forwards;
|
|
22
|
+
}
|
|
23
|
+
@keyframes md-char-in {
|
|
24
|
+
from { opacity: 0; }
|
|
25
|
+
to { opacity: 1; }
|
|
11
26
|
}
|