hookehuyr

fix(rich-text): 修复 v-html 样式不生效问题

移除 scoped 和 :deep(),使用 #rich-text-renderer ID 选择器限制作用范围。
参考 @tarojs/taro/html.css 添加完整 HTML4 样式支持。

- 移除 scoped(v-html 内容不受 scoped 影响)
- 移除 :deep()(小程序 WXSS 不支持)
- 新增完整的 .h5-* 样式定义(表格、代码、列表等)
- 使用 ID 选择器避免全局样式污染

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
...@@ -263,81 +263,294 @@ watch(() => props.enableTransform, () => { ...@@ -263,81 +263,294 @@ watch(() => props.enableTransform, () => {
263 // transformElement 已在初始化时设置,watch immediate 已处理首次渲染 263 // transformElement 已在初始化时设置,watch immediate 已处理首次渲染
264 </script> 264 </script>
265 265
266 -<style lang="less" scoped> 266 +<style lang="less">
267 -.rich-text-content { 267 +// 注意:v-html 内容不受 scoped 样式影响,因此不使用 scoped
268 - // Taro v-html 基础样式(替代 @tarojs/taro/html.css) 268 +// 通过 #rich-text-renderer ID 选择器限制样式作用范围,避免污染全局
269 - :deep(.h5-p) { 269 +// 参考 @tarojs/taro/html.css 的完整 HTML4 样式
270 - margin: 16rpx 0; 270 +#rich-text-renderer {
271 + // ========== 基础显示属性 ==========
272 + .h5-html,
273 + .h5-address,
274 + .h5-blockquote,
275 + .h5-body,
276 + .h5-dd,
277 + .h5-div,
278 + .h5-dl,
279 + .h5-dt,
280 + .h5-fieldset,
281 + .h5-form,
282 + .h5-frame,
283 + .h5-frameset,
284 + .h5-h1,
285 + .h5-h2,
286 + .h5-h3,
287 + .h5-h4,
288 + .h5-h5,
289 + .h5-h6,
290 + .h5-noframes,
291 + .h5-ol,
292 + .h5-p,
293 + .h5-ul,
294 + .h5-center,
295 + .h5-dir,
296 + .h5-hr,
297 + .h5-menu,
298 + .h5-pre {
299 + display: block;
300 + unicode-bidi: embed;
271 } 301 }
272 302
273 - :deep(.h5-img) { 303 + .h5-li {
274 - max-width: 100%; 304 + display: list-item;
275 - height: auto; 305 + }
276 - display: block; 306 +
307 + .h5-head {
308 + display: none;
309 + }
310 +
311 + // ========== 表格样式 ==========
312 + .h5-table {
313 + display: table;
314 + border-spacing: 2px;
315 + }
316 +
317 + .h5-tr {
318 + display: table-row;
319 + }
320 +
321 + .h5-thead {
322 + display: table-header-group;
323 + }
324 +
325 + .h5-tbody {
326 + display: table-row-group;
327 + }
328 +
329 + .h5-tfoot {
330 + display: table-footer-group;
331 + }
332 +
333 + .h5-col {
334 + display: table-column;
277 } 335 }
278 336
279 - :deep(h1) { 337 + .h5-colgroup {
280 - font-size: 48rpx; 338 + display: table-column-group;
281 - font-weight: bold;
282 - margin: 32rpx 0 16rpx;
283 } 339 }
284 340
285 - :deep(h2) { 341 + .h5-td,
286 - font-size: 40rpx; 342 + .h5-th {
287 - font-weight: bold; 343 + display: table-cell;
288 - margin: 24rpx 0 12rpx;
289 } 344 }
290 345
291 - :deep(h3) { 346 + .h5-caption {
292 - font-size: 36rpx; 347 + display: table-caption;
293 - font-weight: bold; 348 + text-align: center;
294 - margin: 20rpx 0 12rpx;
295 } 349 }
296 350
297 - :deep(h4) { 351 + .h5-th {
298 - font-size: 32rpx; 352 + text-align: center;
299 - font-weight: bold; 353 + font-weight: bolder;
300 - margin: 16rpx 0 8rpx;
301 } 354 }
302 355
303 - :deep(p) { 356 + .h5-thead,
304 - font-size: 28rpx; 357 + .h5-tbody,
305 - line-height: 1.6; 358 + .h5-tfoot {
306 - margin: 12rpx 0; 359 + vertical-align: middle;
307 - color: #333;
308 } 360 }
309 361
310 - :deep(ul), 362 + .h5-td,
311 - :deep(ol) { 363 + .h5-th,
312 - padding-left: 48rpx; 364 + .h5-tr {
313 - margin: 16rpx 0; 365 + vertical-align: inherit;
314 } 366 }
315 367
316 - :deep(li) { 368 + // ========== 标题样式 ==========
317 - font-size: 28rpx; 369 + .h5-body {
318 - line-height: 1.6; 370 + margin: 8px;
319 - margin: 8rpx 0;
320 } 371 }
321 372
322 - :deep(strong) { 373 + .h5-h1 {
323 - font-weight: bold; 374 + margin: 0.67em 0;
375 + font-size: 2em;
324 } 376 }
325 377
326 - :deep(em) { 378 + .h5-h2 {
379 + margin: 0.75em 0;
380 + font-size: 1.5em;
381 + }
382 +
383 + .h5-h3 {
384 + margin: 0.83em 0;
385 + font-size: 1.17em;
386 + }
387 +
388 + .h5-h4,
389 + .h5-p,
390 + .h5-blockquote,
391 + .h5-ul,
392 + .h5-fieldset,
393 + .h5-form,
394 + .h5-ol,
395 + .h5-dl,
396 + .h5-dir,
397 + .h5-menu {
398 + margin: 1.12em 0;
399 + }
400 +
401 + .h5-h5 {
402 + margin: 1.5em 0;
403 + font-size: 0.83em;
404 + }
405 +
406 + .h5-h6 {
407 + margin: 1.67em 0;
408 + font-size: 0.75em;
409 + }
410 +
411 + .h5-h1,
412 + .h5-h2,
413 + .h5-h3,
414 + .h5-h4,
415 + .h5-h5,
416 + .h5-h6 {
417 + line-height: 1;
418 + }
419 +
420 + .h5-h1,
421 + .h5-h2,
422 + .h5-h3,
423 + .h5-h4,
424 + .h5-h5,
425 + .h5-h6,
426 + .h5-b,
427 + .h5-strong {
428 + font-weight: bolder;
429 + }
430 +
431 + // ========== 文本样式 ==========
432 + .h5-blockquote {
433 + margin-left: 40px;
434 + margin-right: 40px;
435 + }
436 +
437 + .h5-i,
438 + .h5-cite,
439 + .h5-em,
440 + .h5-var,
441 + .h5-address {
327 font-style: italic; 442 font-style: italic;
328 } 443 }
329 444
330 - :deep(a) { 445 + .h5-pre,
331 - color: #1989fa; 446 + .h5-tt,
447 + .h5-code,
448 + .h5-kbd,
449 + .h5-samp {
450 + font-family: monospace;
451 + }
452 +
453 + .h5-pre {
454 + white-space: pre;
455 + }
456 +
457 + .h5-big {
458 + font-size: 1.17em;
459 + }
460 +
461 + .h5-small,
462 + .h5-sub,
463 + .h5-sup {
464 + font-size: 0.83em;
465 + }
466 +
467 + .h5-sub {
468 + vertical-align: sub;
469 + }
470 +
471 + .h5-sup {
472 + vertical-align: super;
473 + }
474 +
475 + .h5-s,
476 + .h5-strike,
477 + .h5-del {
478 + text-decoration: line-through;
479 + }
480 +
481 + .h5-u,
482 + .h5-ins {
332 text-decoration: underline; 483 text-decoration: underline;
333 } 484 }
334 485
335 - :deep(span) { 486 + .h5-center {
336 - font-size: 28rpx; 487 + text-align: center;
488 + }
489 +
490 + // ========== 列表样式 ==========
491 + .h5-ol,
492 + .h5-ul,
493 + .h5-dir,
494 + .h5-menu,
495 + .h5-dd {
496 + margin-left: 40px;
497 + }
498 +
499 + .h5-ol {
500 + list-style-type: decimal;
501 + }
502 +
503 + .h5-ol .h5-ul,
504 + .h5-ul .h5-ol,
505 + .h5-ul .h5-ul,
506 + .h5-ol .h5-ol {
507 + margin-top: 0;
508 + margin-bottom: 0;
509 + }
510 +
511 + // ========== 其他元素 ==========
512 + .h5-button,
513 + .h5-textarea,
514 + .h5-input,
515 + .h5-select {
516 + display: inline-block;
517 + }
518 +
519 + input[type="hidden"] {
520 + display: none !important;
521 + }
522 +
523 + .h5-a {
524 + display: inline;
525 + }
526 +
527 + .h5-button::after {
528 + border: none;
529 + }
530 +
531 + .h5-span {
532 + display: inline;
533 + }
534 +
535 + .h5-hr {
536 + border: 1px inset;
537 + }
538 +
539 + .h5-br::before {
540 + white-space: pre-line;
541 + content: "\A";
542 + }
543 +
544 + // ========== 自定义补充样式 ==========
545 + // 图片样式(transformElement 已添加 mode 和 style,这里做兜底)
546 + .h5-img,
547 + img {
548 + max-width: 100%;
549 + height: auto;
337 } 550 }
338 551
339 - // 文件链接样式 552 + // 文件链接交互样式
340 - :deep(div[data-is-link="true"]) { 553 + div[data-is-link="true"] {
341 cursor: pointer; 554 cursor: pointer;
342 transition: opacity 0.2s; 555 transition: opacity 0.2s;
343 556
......