@@ -1171,7 +1171,7 @@ function parse(str) {
1171
1171
}
1172
1172
```
1173
1173
1174
- 解析器的参数是模板字符串,解析器会逐个读取字符串模板的字符 ,并根据一定的规则将其处理为我们想要的结果。
1174
+ 解析器的参数是模板字符串,会逐个读取字符串模板的字符 ,并根据一定的规则将其处理为我们想要的结果。
1175
1175
1176
1176
举例来说,假设有这样一段模板:
1177
1177
@@ -1181,6 +1181,110 @@ function parse(str) {
1181
1181
1182
1182
---
1183
1183
1184
+ ``` js
1185
+ /**
1186
+ * 解析模板字符串
1187
+ * @param {string} str 模板字符串
1188
+ */
1189
+ function parse (str ) {
1190
+ const context = {
1191
+ // 存储模板字符串
1192
+ source: str,
1193
+ // 前进 num 个字符
1194
+ advanceBy (num ) {
1195
+ context .source = context .source .slice (num)
1196
+ },
1197
+ advanceSpaces () {
1198
+ // 匹配空格换行符等
1199
+ const match = / ^ [\t\r\n\f ] + / .exec (context .source )
1200
+ if (match) {
1201
+ context .advanceBy (match[0 ].length )
1202
+ }
1203
+ }
1204
+ }
1205
+ const nodes = parseChildren (context, [])
1206
+ const root = { // 根节点
1207
+ type: ' Root' ,
1208
+ children: nodes
1209
+ }
1210
+ return root
1211
+ }
1212
+ ```
1213
+
1214
+ ---
1215
+
1216
+ ``` js
1217
+ /**
1218
+ * 解析子节点
1219
+ * @param {*} context 上下文
1220
+ * @param {*} ancestors 祖先节点列表
1221
+ */
1222
+ function parseChildren (context , ancestors = []) {
1223
+ const nodes = []
1224
+ while (! isEnd (context, ancestors)) { // 如果还没有解析到模板的末尾
1225
+ let node
1226
+ const s = context .source
1227
+ if (s .startsWith (' {{' )) {
1228
+ // 解析插值表达式
1229
+ node = parseInterpolation (context)
1230
+ } else if (s[0 ] === ' <' ) {
1231
+ if (s[1 ] === ' /' ) {
1232
+ // 结束标签
1233
+ } else if (/ [a-z ] / i .test (s[1 ])) { // 解析开始标签
1234
+ node = parseElement (context, ancestors)
1235
+ }
1236
+ }
1237
+ if (! node) { // 解析文本节点
1238
+ node = parseText (context)
1239
+ }
1240
+ nodes .push (node)
1241
+ }
1242
+ return nodes
1243
+ }
1244
+ ```
1245
+
1246
+ ---
1247
+
1248
+ <div grid =" ~ cols-2 gap-2 " >
1249
+
1250
+ ``` js
1251
+ /**
1252
+ * 解析插值表达式
1253
+ * @param {*} context 上下文
1254
+ * @example
1255
+ *
1256
+ * 模板: {{ msg }}
1257
+ */
1258
+ function parseInterpolation (context ) {
1259
+ const { advanceBy } = context
1260
+ // 移除 {{
1261
+ advanceBy (2 )
1262
+ const closeIndex = context .source .indexOf (' }}' )
1263
+ const rawContent = context .source .slice (0 , closeIndex)
1264
+ // 去掉前后空格
1265
+ const content = rawContent .trim ()
1266
+ advanceBy (rawContent .length )
1267
+ // 移除 }}
1268
+ advanceBy (2 )
1269
+
1270
+ return {
1271
+ type: ' Interpolation' ,
1272
+ content: {
1273
+ type: ' Expression' ,
1274
+ content
1275
+ }
1276
+ }
1277
+ }
1278
+ ```
1279
+
1280
+ ``` js
1281
+
1282
+ ```
1283
+
1284
+ </div >
1285
+
1286
+ ---
1287
+
1184
1288
# Learn More
1185
1289
1186
1290
[ Documentations] ( https://sli.dev ) · [ GitHub] ( https://github.com/slidevjs/slidev ) · [ Showcases] ( https://sli.dev/showcases.html )
0 commit comments