@vigilkids/section-renderer-vue 0.0.1 → 0.1.0

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.
Files changed (51) hide show
  1. package/dist/composables/useInlineEdit.d.ts +1 -1
  2. package/dist/composables/useInlineEdit.mjs +4 -2
  3. package/dist/composables/useLazyRender.mjs +2 -1
  4. package/dist/composables/useRegistry.d.ts +1 -1
  5. package/dist/composables/useRegistry.mjs +6 -3
  6. package/dist/composables/useSectionSEO.mjs +10 -5
  7. package/dist/composables/useSectionStyle.d.ts +1 -1
  8. package/dist/composables/useSectionStyle.mjs +10 -6
  9. package/dist/editor.d.ts +2 -2
  10. package/dist/editor.mjs +2 -2
  11. package/dist/index.d.ts +12 -12
  12. package/dist/index.mjs +8 -8
  13. package/dist/preview/createPreviewApp.mjs +12 -4
  14. package/dist/renderer/FallbackSection.vue +9 -3
  15. package/dist/renderer/LazySection.vue +25 -22
  16. package/dist/renderer/SectionErrorBoundary.vue +3 -1
  17. package/dist/renderer/SectionRenderer.vue +19 -6
  18. package/dist/renderer/SectionWrapper.vue +4 -5
  19. package/dist/sections/RichTextSection.vue +12 -12
  20. package/dist/sections/article/prosemirror.mjs +8 -4
  21. package/dist/sections/article/shared/ArticleCustomHtml.vue +1 -1
  22. package/dist/sections/article/shared/ArticleImage.vue +3 -3
  23. package/dist/sections/article/vigilkids/ArticleBulletList.vue +2 -2
  24. package/dist/sections/article/vigilkids/ArticleCta.vue +48 -21
  25. package/dist/sections/article/vigilkids/ArticleFaq.vue +11 -5
  26. package/dist/sections/article/vigilkids/ArticleFaqItem.vue +6 -2
  27. package/dist/sections/article/vigilkids/ArticleFeature.vue +16 -8
  28. package/dist/sections/article/vigilkids/ArticleHeading.vue +3 -4
  29. package/dist/sections/article/vigilkids/ArticleNotice.vue +33 -9
  30. package/dist/sections/article/vigilkids/ArticleProsCons.vue +6 -6
  31. package/dist/sections/article/vigilkids/ArticleQuestion.vue +11 -5
  32. package/dist/sections/article/vigilkids/ArticleQuote.vue +6 -4
  33. package/dist/sections/article/vigilkids/ArticleStepList.vue +8 -4
  34. package/dist/sections/article/vigilkids/ArticleSubheading.vue +18 -6
  35. package/dist/sections/article/vigilkids/ArticleTable.vue +9 -8
  36. package/dist/sections/article/vigilkids/ArticleToc.vue +13 -9
  37. package/dist/sections/article/visiva/ArticleBulletList.vue +2 -2
  38. package/dist/sections/article/visiva/ArticleCta.vue +127 -30
  39. package/dist/sections/article/visiva/ArticleFaq.vue +22 -8
  40. package/dist/sections/article/visiva/ArticleFeature.vue +20 -7
  41. package/dist/sections/article/visiva/ArticleHeading.vue +2 -2
  42. package/dist/sections/article/visiva/ArticleNotice.vue +7 -5
  43. package/dist/sections/article/visiva/ArticleProsCons.vue +37 -23
  44. package/dist/sections/article/visiva/ArticleQuestion.vue +18 -7
  45. package/dist/sections/article/visiva/ArticleQuote.vue +9 -5
  46. package/dist/sections/article/visiva/ArticleStepList.vue +9 -4
  47. package/dist/sections/article/visiva/ArticleSubheading.vue +32 -27
  48. package/dist/sections/article/visiva/ArticleTable.vue +79 -60
  49. package/dist/sections/article/visiva/ArticleToc.vue +42 -12
  50. package/dist/styles/products/visiva.css +1 -1
  51. package/package.json +10 -3
@@ -28,9 +28,9 @@ const { editableAttrs } = useInlineEdit({
28
28
  editorMode: () => !!props.editorMode,
29
29
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
30
30
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
31
- onEditStart: (key) => emit('inline-edit-start', key),
31
+ onEditStart: key => emit('inline-edit-start', key),
32
32
  onEditEnd: () => emit('inline-edit-end'),
33
- onUndoRedo: (action) => emit('undo-redo', action),
33
+ onUndoRedo: action => emit('undo-redo', action),
34
34
  })
35
35
  </script>
36
36
 
@@ -38,7 +38,7 @@ const { editableAttrs } = useInlineEdit({
38
38
  <!-- button variant: 单个居中按钮 -->
39
39
  <a
40
40
  v-if="variant === 'button'"
41
- :href="safeUrl(String(s.button_url || ''))"
41
+ :href="editorMode ? undefined : safeUrl(String(s.button_url || ''))"
42
42
  class="btn btn-primary"
43
43
  v-bind="editableAttrs('button_text')"
44
44
  >
@@ -48,7 +48,7 @@ const { editableAttrs } = useInlineEdit({
48
48
  <!-- button-group variant: 两个按钮并排 -->
49
49
  <div v-else-if="variant === 'button-group'" class="btn-group">
50
50
  <a
51
- :href="safeUrl(String(s.button_url || ''))"
51
+ :href="editorMode ? undefined : safeUrl(String(s.button_url || ''))"
52
52
  class="btn btn-primary"
53
53
  v-bind="editableAttrs('button_text')"
54
54
  >
@@ -56,7 +56,7 @@ const { editableAttrs } = useInlineEdit({
56
56
  </a>
57
57
  <a
58
58
  v-if="s.secondary_button_text"
59
- :href="safeUrl(String(s.secondary_button_url || ''))"
59
+ :href="editorMode ? undefined : safeUrl(String(s.secondary_button_url || ''))"
60
60
  class="btn outline-btn"
61
61
  v-bind="editableAttrs('secondary_button_text')"
62
62
  >
@@ -67,12 +67,16 @@ const { editableAttrs } = useInlineEdit({
67
67
  <!-- card variant: 左文字右按钮 -->
68
68
  <div v-else-if="variant === 'card'" class="article-try">
69
69
  <div class="article-try-content">
70
- <p v-if="s.title" class="article-try-title" v-bind="editableAttrs('title')">{{ s.title }}</p>
71
- <p v-if="s.description" class="article-try-description" v-bind="editableAttrs('description')">{{ s.description }}</p>
70
+ <p v-if="s.title" class="article-try-title" v-bind="editableAttrs('title')">
71
+ {{ s.title }}
72
+ </p>
73
+ <p v-if="s.description" class="article-try-description" v-bind="editableAttrs('description')">
74
+ {{ s.description }}
75
+ </p>
72
76
  </div>
73
77
  <a
74
78
  v-if="s.button_text"
75
- :href="safeUrl(String(s.button_url || ''))"
79
+ :href="editorMode ? undefined : safeUrl(String(s.button_url || ''))"
76
80
  class="btn btn-primary"
77
81
  v-bind="editableAttrs('button_text')"
78
82
  >
@@ -83,39 +87,62 @@ const { editableAttrs } = useInlineEdit({
83
87
  <!-- showcase variant: 左文字+按钮,右图片 -->
84
88
  <div v-else-if="variant === 'showcase'" class="article-show">
85
89
  <div class="article-show-content">
86
- <p v-if="s.title" class="article-show-title" v-bind="editableAttrs('title')">{{ s.title }}</p>
87
- <p v-if="s.description" class="article-show-description" v-bind="editableAttrs('description')">{{ s.description }}</p>
90
+ <p v-if="s.title" class="article-show-title" v-bind="editableAttrs('title')">
91
+ {{ s.title }}
92
+ </p>
93
+ <p
94
+ v-if="s.description"
95
+ class="article-show-description"
96
+ v-bind="editableAttrs('description')"
97
+ >
98
+ {{ s.description }}
99
+ </p>
88
100
  <a
89
101
  v-if="s.button_text"
90
- :href="safeUrl(String(s.button_url || ''))"
102
+ :href="editorMode ? undefined : safeUrl(String(s.button_url || ''))"
91
103
  class="btn btn-primary"
92
104
  v-bind="editableAttrs('button_text')"
93
105
  >
94
106
  {{ s.button_text }}
95
107
  </a>
96
108
  </div>
97
- <img
98
- v-if="s.image_src"
99
- :src="String(s.image_src)"
100
- alt=""
101
- loading="lazy"
102
- >
109
+ <img v-if="s.image_src" :src="String(s.image_src)" alt="" loading="lazy">
103
110
  </div>
104
111
 
105
112
  <!-- button-group-dark variant: 黑底容器+白边主按钮+渐变次按钮 (Visiva) -->
106
113
  <div v-else-if="variant === 'button-group-dark'" class="btn-group-dark">
107
114
  <div class="btn-group-dark__buttons">
108
115
  <div v-if="s.button_text" class="btn-group-dark__item">
109
- <a :href="safeUrl(String(s.button_url || ''))" class="btn btn-outline-white" v-bind="editableAttrs('button_text')">
116
+ <a
117
+ :href="editorMode ? undefined : safeUrl(String(s.button_url || ''))"
118
+ class="btn btn-outline-white"
119
+ v-bind="editableAttrs('button_text')"
120
+ >
110
121
  {{ s.button_text }}
111
122
  </a>
112
- <p v-if="s.button_caption" class="btn-group-dark__caption" v-bind="editableAttrs('button_caption')">{{ s.button_caption }}</p>
123
+ <p
124
+ v-if="s.button_caption"
125
+ class="btn-group-dark__caption"
126
+ v-bind="editableAttrs('button_caption')"
127
+ >
128
+ {{ s.button_caption }}
129
+ </p>
113
130
  </div>
114
131
  <div v-if="s.secondary_button_text" class="btn-group-dark__item">
115
- <a :href="safeUrl(String(s.secondary_button_url || ''))" class="btn btn-gradient" v-bind="editableAttrs('secondary_button_text')">
132
+ <a
133
+ :href="editorMode ? undefined : safeUrl(String(s.secondary_button_url || ''))"
134
+ class="btn btn-gradient"
135
+ v-bind="editableAttrs('secondary_button_text')"
136
+ >
116
137
  {{ s.secondary_button_text }}
117
138
  </a>
118
- <p v-if="s.secondary_button_caption" class="btn-group-dark__caption" v-bind="editableAttrs('secondary_button_caption')">{{ s.secondary_button_caption }}</p>
139
+ <p
140
+ v-if="s.secondary_button_caption"
141
+ class="btn-group-dark__caption"
142
+ v-bind="editableAttrs('secondary_button_caption')"
143
+ >
144
+ {{ s.secondary_button_caption }}
145
+ </p>
119
146
  </div>
120
147
  </div>
121
148
  </div>
@@ -27,9 +27,9 @@ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
27
27
  editorMode: () => !!props.editorMode,
28
28
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
29
29
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
30
- onEditStart: (key) => emit('inline-edit-start', key),
30
+ onEditStart: key => emit('inline-edit-start', key),
31
31
  onEditEnd: () => emit('inline-edit-end'),
32
- onUndoRedo: (action) => emit('undo-redo', action),
32
+ onUndoRedo: action => emit('undo-redo', action),
33
33
  })
34
34
  </script>
35
35
 
@@ -37,13 +37,19 @@ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
37
37
  <!-- Visiva 风格:浅绿卡片 + 绿色标题 + 静态列表 -->
38
38
  <div v-if="s.title" class="faq-card">
39
39
  <div class="faq-card__header">
40
- <h2 class="faq-card__title" v-bind="editableAttrs('title')">{{ s.title }}</h2>
40
+ <h2 class="faq-card__title" v-bind="editableAttrs('title')">
41
+ {{ s.title }}
42
+ </h2>
41
43
  </div>
42
44
  <div class="faq-card__list">
43
45
  <template v-for="blockId in blockOrder" :key="blockId">
44
46
  <div v-if="blocks[blockId]" class="faq-card__item">
45
- <h3 class="faq-card__question" v-bind="blockEditableAttrs(blockId, 'question')">{{ blocks[blockId]!.settings.question }}</h3>
46
- <p class="faq-card__answer" v-bind="blockEditableAttrs(blockId, 'answer')">{{ blocks[blockId]!.settings.answer }}</p>
47
+ <h3 class="faq-card__question" v-bind="blockEditableAttrs(blockId, 'question')">
48
+ {{ blocks[blockId]!.settings.question }}
49
+ </h3>
50
+ <p class="faq-card__answer" v-bind="blockEditableAttrs(blockId, 'answer')">
51
+ {{ blocks[blockId]!.settings.answer }}
52
+ </p>
47
53
  </div>
48
54
  </template>
49
55
  </div>
@@ -14,8 +14,12 @@ function toggle() {
14
14
 
15
15
  <template>
16
16
  <div class="faq-item" :class="{ active }" @click="toggle">
17
- <p class="faq-item-title">{{ settings.question }}</p>
18
- <p class="faq-item-answer">{{ settings.answer }}</p>
17
+ <p class="faq-item-title">
18
+ {{ settings.question }}
19
+ </p>
20
+ <p class="faq-item-answer">
21
+ {{ settings.answer }}
22
+ </p>
19
23
  </div>
20
24
  </template>
21
25
 
@@ -28,9 +28,9 @@ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
28
28
  editorMode: () => !!props.editorMode,
29
29
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
30
30
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
31
- onEditStart: (key) => emit('inline-edit-start', key),
31
+ onEditStart: key => emit('inline-edit-start', key),
32
32
  onEditEnd: () => emit('inline-edit-end'),
33
- onUndoRedo: (action) => emit('undo-redo', action),
33
+ onUndoRedo: action => emit('undo-redo', action),
34
34
  })
35
35
  </script>
36
36
 
@@ -38,13 +38,17 @@ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
38
38
  <!-- light / dark 变体:图片+特性列表+CTA (Visiva) -->
39
39
  <div
40
40
  v-if="variant === 'light' || variant === 'dark'"
41
- :class="['feature-card', { 'feature-card--dark': variant === 'dark' }]"
41
+ class="feature-card" :class="[{ 'feature-card--dark': variant === 'dark' }]"
42
42
  >
43
43
  <div class="feature-card__text">
44
- <h2 v-if="s.title" class="feature-card__title" v-bind="editableAttrs('title')">{{ s.title }}</h2>
44
+ <h2 v-if="s.title" class="feature-card__title" v-bind="editableAttrs('title')">
45
+ {{ s.title }}
46
+ </h2>
45
47
  <ul class="feature-card__list">
46
48
  <template v-for="blockId in blockOrder" :key="blockId">
47
- <li v-if="blocks[blockId]" v-bind="blockEditableAttrs(blockId, 'text')">{{ blocks[blockId]!.settings.text }}</li>
49
+ <li v-if="blocks[blockId]" v-bind="blockEditableAttrs(blockId, 'text')">
50
+ {{ blocks[blockId]!.settings.text }}
51
+ </li>
48
52
  </template>
49
53
  </ul>
50
54
  <a
@@ -57,16 +61,20 @@ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
57
61
  </a>
58
62
  </div>
59
63
  <div v-if="s.image_src" class="feature-card__image">
60
- <img :src="String(s.image_src)" alt="" loading="lazy" />
64
+ <img :src="String(s.image_src)" alt="" loading="lazy">
61
65
  </div>
62
66
  </div>
63
67
 
64
68
  <!-- default 变体:原有灰色特性框 (VigilKids,完全不动) -->
65
69
  <div v-else class="article-feature">
66
- <p v-if="s.title" class="article-feature-title" v-bind="editableAttrs('title')">{{ s.title }}</p>
70
+ <p v-if="s.title" class="article-feature-title" v-bind="editableAttrs('title')">
71
+ {{ s.title }}
72
+ </p>
67
73
  <ul class="article-feature-list">
68
74
  <template v-for="blockId in blockOrder" :key="blockId">
69
- <li v-if="blocks[blockId]" v-bind="blockEditableAttrs(blockId, 'text')">{{ blocks[blockId]!.settings.text }}</li>
75
+ <li v-if="blocks[blockId]" v-bind="blockEditableAttrs(blockId, 'text')">
76
+ {{ blocks[blockId]!.settings.text }}
77
+ </li>
70
78
  </template>
71
79
  </ul>
72
80
  </div>
@@ -27,17 +27,16 @@ const { editableAttrs } = useInlineEdit({
27
27
  editorMode: () => !!props.editorMode,
28
28
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
29
29
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
30
- onEditStart: (key) => emit('inline-edit-start', key),
30
+ onEditStart: key => emit('inline-edit-start', key),
31
31
  onEditEnd: () => emit('inline-edit-end'),
32
- onUndoRedo: (action) => emit('undo-redo', action),
32
+ onUndoRedo: action => emit('undo-redo', action),
33
33
  })
34
34
  </script>
35
35
 
36
36
  <template>
37
37
  <h2
38
38
  :id="String(s.anchor || '')"
39
- :class="[
40
- 'article-heading',
39
+ class="article-heading" :class="[
41
40
  {
42
41
  'article-heading--plain': variant === 'plain',
43
42
  'article-heading--accent': variant === 'accent',
@@ -29,9 +29,9 @@ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
29
29
  editorMode: () => !!props.editorMode,
30
30
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
31
31
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
32
- onEditStart: (key) => emit('inline-edit-start', key),
32
+ onEditStart: key => emit('inline-edit-start', key),
33
33
  onEditEnd: () => emit('inline-edit-end'),
34
- onUndoRedo: (action) => emit('undo-redo', action),
34
+ onUndoRedo: action => emit('undo-redo', action),
35
35
  })
36
36
  </script>
37
37
 
@@ -39,11 +39,15 @@ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
39
39
  <!-- tips / note 变体:角标样式 (Visiva) -->
40
40
  <div v-if="variant === 'tips' || variant === 'note'" class="notice-badge">
41
41
  <div class="notice-badge__tag">
42
- <span class="notice-badge__label" v-bind="editableAttrs('title')">{{ s.title || 'Tips' }}</span>
42
+ <span class="notice-badge__label" v-bind="editableAttrs('title')">{{
43
+ s.title || 'Tips'
44
+ }}</span>
43
45
  </div>
44
46
  <div class="notice-badge__content">
45
47
  <template v-for="blockId in blockOrder" :key="blockId">
46
- <p v-if="blocks[blockId]" v-bind="blockEditableAttrs(blockId, 'text')">{{ blocks[blockId]!.settings.text }}</p>
48
+ <p v-if="blocks[blockId]" v-bind="blockEditableAttrs(blockId, 'text')">
49
+ {{ blocks[blockId]!.settings.text }}
50
+ </p>
47
51
  </template>
48
52
  </div>
49
53
  </div>
@@ -51,12 +55,30 @@ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
51
55
  <!-- info 变体:圆角卡片+图标标题 (Visiva) -->
52
56
  <div v-else-if="variant === 'info'" class="notice-card">
53
57
  <div v-if="s.title" class="notice-card__header">
54
- <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
55
- <h3 class="notice-card__title" v-bind="editableAttrs('title')">{{ s.title }}</h3>
58
+ <svg
59
+ xmlns="http://www.w3.org/2000/svg"
60
+ width="22"
61
+ height="22"
62
+ viewBox="0 0 24 24"
63
+ fill="none"
64
+ stroke="currentColor"
65
+ stroke-width="2"
66
+ stroke-linecap="round"
67
+ stroke-linejoin="round"
68
+ >
69
+ <circle cx="12" cy="12" r="10" />
70
+ <path d="M12 16v-4" />
71
+ <path d="M12 8h.01" />
72
+ </svg>
73
+ <h3 class="notice-card__title" v-bind="editableAttrs('title')">
74
+ {{ s.title }}
75
+ </h3>
56
76
  </div>
57
77
  <div class="notice-card__content">
58
78
  <template v-for="blockId in blockOrder" :key="blockId">
59
- <p v-if="blocks[blockId]" v-bind="blockEditableAttrs(blockId, 'text')">{{ blocks[blockId]!.settings.text }}</p>
79
+ <p v-if="blocks[blockId]" v-bind="blockEditableAttrs(blockId, 'text')">
80
+ {{ blocks[blockId]!.settings.text }}
81
+ </p>
60
82
  </template>
61
83
  </div>
62
84
  </div>
@@ -66,12 +88,14 @@ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
66
88
  v-else
67
89
  class="notice-info"
68
90
  :class="{
69
- warning: isWarning,
91
+ 'warning': isWarning,
70
92
  'notice-info--row-child': isRow,
71
93
  }"
72
94
  >
73
95
  <template v-for="blockId in blockOrder" :key="blockId">
74
- <p v-if="blocks[blockId]" v-bind="blockEditableAttrs(blockId, 'text')">{{ blocks[blockId]!.settings.text }}</p>
96
+ <p v-if="blocks[blockId]" v-bind="blockEditableAttrs(blockId, 'text')">
97
+ {{ blocks[blockId]!.settings.text }}
98
+ </p>
75
99
  </template>
76
100
  </div>
77
101
  </template>
@@ -24,14 +24,14 @@ const s = computed(() => props.settings)
24
24
 
25
25
  const pros = computed(() =>
26
26
  props.blockOrder
27
- .filter((id) => props.blocks[id]?.type === 'pro')
28
- .map((id) => ({ id, block: props.blocks[id]! })),
27
+ .filter(id => props.blocks[id]?.type === 'pro')
28
+ .map(id => ({ id, block: props.blocks[id]! })),
29
29
  )
30
30
 
31
31
  const cons = computed(() =>
32
32
  props.blockOrder
33
- .filter((id) => props.blocks[id]?.type === 'con')
34
- .map((id) => ({ id, block: props.blocks[id]! })),
33
+ .filter(id => props.blocks[id]?.type === 'con')
34
+ .map(id => ({ id, block: props.blocks[id]! })),
35
35
  )
36
36
 
37
37
  const isDashed = computed(() => String(s.value.variant) === 'dashed')
@@ -40,9 +40,9 @@ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
40
40
  editorMode: () => !!props.editorMode,
41
41
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
42
42
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
43
- onEditStart: (key) => emit('inline-edit-start', key),
43
+ onEditStart: key => emit('inline-edit-start', key),
44
44
  onEditEnd: () => emit('inline-edit-end'),
45
- onUndoRedo: (action) => emit('undo-redo', action),
45
+ onUndoRedo: action => emit('undo-redo', action),
46
46
  })
47
47
  </script>
48
48
 
@@ -29,9 +29,9 @@ const { blockEditableAttrs } = useInlineEdit({
29
29
  editorMode: () => !!props.editorMode,
30
30
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
31
31
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
32
- onEditStart: (key) => emit('inline-edit-start', key),
32
+ onEditStart: key => emit('inline-edit-start', key),
33
33
  onEditEnd: () => emit('inline-edit-end'),
34
- onUndoRedo: (action) => emit('undo-redo', action),
34
+ onUndoRedo: action => emit('undo-redo', action),
35
35
  })
36
36
  </script>
37
37
 
@@ -40,15 +40,21 @@ const { blockEditableAttrs } = useInlineEdit({
40
40
  <div v-if="blockOrder.length > 0" class="qa-card">
41
41
  <template v-for="blockId in blockOrder" :key="blockId">
42
42
  <div v-if="blocks[blockId]" class="qa-card__item">
43
- <h3 class="qa-card__question" v-bind="blockEditableAttrs(blockId, 'question')">{{ blocks[blockId]!.settings.question }}</h3>
44
- <p class="qa-card__answer">{{ blocks[blockId]!.settings.answer }}</p>
43
+ <h3 class="qa-card__question" v-bind="blockEditableAttrs(blockId, 'question')">
44
+ {{ blocks[blockId]!.settings.question }}
45
+ </h3>
46
+ <p class="qa-card__answer" v-bind="blockEditableAttrs(blockId, 'answer')">
47
+ {{ blocks[blockId]!.settings.answer }}
48
+ </p>
45
49
  </div>
46
50
  </template>
47
51
  </div>
48
52
 
49
53
  <!-- VigilKids: 单条 richtext 问答 -->
50
54
  <div v-else class="article-question">
51
- <p class="article-question-title">{{ title }}</p>
55
+ <p class="article-question-title">
56
+ {{ title }}
57
+ </p>
52
58
  <div class="article-question-content" v-html="renderedContent" />
53
59
  </div>
54
60
  </template>
@@ -28,18 +28,20 @@ const { editableAttrs } = useInlineEdit({
28
28
  editorMode: () => !!props.editorMode,
29
29
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
30
30
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
31
- onEditStart: (key) => emit('inline-edit-start', key),
31
+ onEditStart: key => emit('inline-edit-start', key),
32
32
  onEditEnd: () => emit('inline-edit-end'),
33
- onUndoRedo: (action) => emit('undo-redo', action),
33
+ onUndoRedo: action => emit('undo-redo', action),
34
34
  })
35
35
  </script>
36
36
 
37
37
  <template>
38
38
  <div class="article-info">
39
- <p v-if="s.title" class="article-info-title" v-bind="editableAttrs('title')">{{ s.title }}</p>
39
+ <p v-if="s.title" class="article-info-title" v-bind="editableAttrs('title')">
40
+ {{ s.title }}
41
+ </p>
40
42
  <div class="article-info-content" v-html="renderedContent" />
41
43
  <cite v-if="s.attribution" class="article-info-attribution">
42
- <span class="article-info-divider"></span>
44
+ <span class="article-info-divider" />
43
45
  <span v-bind="editableAttrs('attribution')">by {{ s.attribution }}</span>
44
46
  </cite>
45
47
  </div>
@@ -27,9 +27,9 @@ const { blockEditableAttrs } = useInlineEdit({
27
27
  editorMode: () => !!props.editorMode,
28
28
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
29
29
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
30
- onEditStart: (key) => emit('inline-edit-start', key),
30
+ onEditStart: key => emit('inline-edit-start', key),
31
31
  onEditEnd: () => emit('inline-edit-end'),
32
- onUndoRedo: (action) => emit('undo-redo', action),
32
+ onUndoRedo: action => emit('undo-redo', action),
33
33
  })
34
34
  </script>
35
35
 
@@ -37,8 +37,12 @@ const { blockEditableAttrs } = useInlineEdit({
37
37
  <ul class="step-list">
38
38
  <template v-for="blockId in blockOrder" :key="blockId">
39
39
  <li v-if="blocks[blockId]">
40
- <span class="primary-color" v-bind="blockEditableAttrs(blockId, 'label')">{{ blocks[blockId]!.settings.label }}</span>
41
- {{ blocks[blockId]!.settings.description }}
40
+ <span class="primary-color" v-bind="blockEditableAttrs(blockId, 'label')">{{
41
+ blocks[blockId]!.settings.label
42
+ }}</span>
43
+ <span v-bind="blockEditableAttrs(blockId, 'description')">{{
44
+ blocks[blockId]!.settings.description
45
+ }}</span>
42
46
  </li>
43
47
  </template>
44
48
  </ul>
@@ -27,24 +27,36 @@ const { editableAttrs } = useInlineEdit({
27
27
  editorMode: () => !!props.editorMode,
28
28
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
29
29
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
30
- onEditStart: (key) => emit('inline-edit-start', key),
30
+ onEditStart: key => emit('inline-edit-start', key),
31
31
  onEditEnd: () => emit('inline-edit-end'),
32
- onUndoRedo: (action) => emit('undo-redo', action),
32
+ onUndoRedo: action => emit('undo-redo', action),
33
33
  })
34
34
  </script>
35
35
 
36
36
  <template>
37
- <h3 :class="['article-subheading', `article-subheading--${variant}`]">
37
+ <h3 class="article-subheading" :class="[`article-subheading--${variant}`]">
38
38
  <!-- numbered: 实心绿色圆形+白色数字 (VigilKids) -->
39
- <span v-if="variant === 'numbered' && s.number" class="article-subheading__number" v-bind="editableAttrs('number')">
39
+ <span
40
+ v-if="variant === 'numbered' && s.number"
41
+ class="article-subheading__number"
42
+ v-bind="editableAttrs('number')"
43
+ >
40
44
  {{ s.number }}
41
45
  </span>
42
46
  <!-- pill: 绿色药丸标签 (Visiva) -->
43
- <span v-else-if="variant === 'pill' && s.label" class="article-subheading__pill" v-bind="editableAttrs('label')">
47
+ <span
48
+ v-else-if="variant === 'pill' && s.label"
49
+ class="article-subheading__pill"
50
+ v-bind="editableAttrs('label')"
51
+ >
44
52
  {{ s.label }}
45
53
  </span>
46
54
  <!-- icon: 浅色圆形+深色数字 (Visiva) -->
47
- <span v-else-if="variant === 'icon' && s.number" class="article-subheading__icon" v-bind="editableAttrs('number')">
55
+ <span
56
+ v-else-if="variant === 'icon' && s.number"
57
+ class="article-subheading__icon"
58
+ v-bind="editableAttrs('number')"
59
+ >
48
60
  {{ s.number }}
49
61
  </span>
50
62
  <span v-bind="editableAttrs('title')">{{ s.title }}</span>
@@ -18,12 +18,15 @@ interface ColumnDef {
18
18
  }
19
19
 
20
20
  function parseJsonOrArray<T>(value: unknown): T[] {
21
- if (Array.isArray(value)) return value as T[]
21
+ if (Array.isArray(value))
22
+ return value as T[]
22
23
  if (typeof value === 'string') {
23
24
  try {
24
25
  const parsed = JSON.parse(value)
25
- if (Array.isArray(parsed)) return parsed as T[]
26
- } catch {
26
+ if (Array.isArray(parsed))
27
+ return parsed as T[]
28
+ }
29
+ catch {
27
30
  /* JSON 解析失败,返回空数组 */
28
31
  }
29
32
  }
@@ -32,13 +35,11 @@ function parseJsonOrArray<T>(value: unknown): T[] {
32
35
 
33
36
  const isSticky = computed(() => String(s.value.variant) === 'sticky')
34
37
 
35
- const columns = computed<ColumnDef[]>(() =>
36
- parseJsonOrArray<ColumnDef>(s.value.columns),
37
- )
38
+ const columns = computed<ColumnDef[]>(() => parseJsonOrArray<ColumnDef>(s.value.columns))
38
39
 
39
40
  const rows = computed(() =>
40
41
  props.blockOrder
41
- .filter((id) => props.blocks[id]?.type === 'table-row')
42
+ .filter(id => props.blocks[id]?.type === 'table-row')
42
43
  .map((id) => {
43
44
  const block = props.blocks[id]!
44
45
  return parseJsonOrArray<string>(block.settings.cells)
@@ -47,7 +48,7 @@ const rows = computed(() =>
47
48
  </script>
48
49
 
49
50
  <template>
50
- <div :class="['contrast-table', { 'sticky-table': isSticky }]">
51
+ <div class="contrast-table" :class="[{ 'sticky-table': isSticky }]">
51
52
  <table>
52
53
  <thead align="left">
53
54
  <tr>
@@ -10,7 +10,7 @@ interface TocGroup {
10
10
  text: string
11
11
  anchor: string
12
12
  hot: boolean
13
- children: { id: string; text: string; anchor: string }[]
13
+ children: { id: string, text: string, anchor: string }[]
14
14
  }
15
15
 
16
16
  const props = defineProps<{
@@ -36,7 +36,8 @@ const tocGroups = computed<TocGroup[]>(() => {
36
36
 
37
37
  for (const blockId of props.blockOrder) {
38
38
  const block = props.blocks[blockId]
39
- if (!block) continue
39
+ if (!block)
40
+ continue
40
41
 
41
42
  if (block.type === 'toc-h2') {
42
43
  groups.push({
@@ -46,7 +47,8 @@ const tocGroups = computed<TocGroup[]>(() => {
46
47
  hot: Boolean(block.settings.hot),
47
48
  children: [],
48
49
  })
49
- } else if (block.type === 'toc-h3' && groups.length > 0) {
50
+ }
51
+ else if (block.type === 'toc-h3' && groups.length > 0) {
50
52
  groups[groups.length - 1]!.children.push({
51
53
  id: blockId,
52
54
  text: String(block.settings.text || ''),
@@ -58,22 +60,24 @@ const tocGroups = computed<TocGroup[]>(() => {
58
60
  return groups
59
61
  })
60
62
 
61
- const hotIconSrc =
62
- "data:image/svg+xml,%3Csvg viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.5479 11.9702C10.0966 11.9702 9.71456 12.5389 9.71456 13.2188C9.71456 13.8948 10.0966 14.4668 10.5479 14.4668C10.9992 14.4668 11.3819 13.8968 11.3819 13.2175C11.3819 12.5389 10.9999 11.9689 10.5485 11.9689L10.5479 11.9702ZM15.3977 3.54841C15.3258 3.46817 15.2338 3.40848 15.1312 3.37545C15.0286 3.34242 14.919 3.33723 14.8138 3.36042C14.6018 3.41108 14.4271 3.57374 14.3471 3.79507C14.1688 4.31816 14.0036 4.84565 13.8518 5.37704C13.6385 4.93438 13.3985 4.50972 13.1318 4.10374C12.1478 2.60444 10.7985 1.3318 8.88657 0.0985037C8.7956 0.0391916 8.69032 0.00547728 8.58182 0.000902909C8.47331 -0.00367146 8.36558 0.021063 8.26993 0.0725076C8.17116 0.129583 8.08767 0.209723 8.02661 0.306079C7.96554 0.402435 7.92871 0.512143 7.91927 0.625828C7.65327 3.22973 7.16395 5.86901 5.492 7.72696L5.27001 7.25364C5.0747 6.84432 4.89202 6.45901 4.7747 6.12901C4.64802 5.76569 4.27671 5.5837 3.94538 5.72237C3.7931 5.78848 3.67093 5.90898 3.60272 6.06034L3.46806 6.347C2.64741 8.08696 1.52544 10.4736 1.3561 12.4915C1.00477 16.7687 4.55669 19.4567 8.25059 19.9033C9.06192 20.0013 9.87722 20.0233 10.6919 19.9733C13.5965 19.784 17.125 18.1554 18.3143 14.1468C19.0843 11.5449 18.7837 7.21032 15.3977 3.54708V3.54774V3.54841ZM7.82794 15.1521C7.82794 15.4901 7.57528 15.7655 7.26462 15.7655C6.95464 15.7668 6.70329 15.4921 6.70196 15.1521V13.7588L5.542 13.7788V15.1861C5.542 15.5234 5.28934 15.7994 4.97868 15.7994C4.66936 15.8008 4.41669 15.5261 4.41536 15.1861V11.4189C4.41536 11.0802 4.66735 10.8056 4.97868 10.8056C5.28934 10.8056 5.54134 11.0802 5.54134 11.4189V12.5515L6.70196 12.5322V11.3855C6.70196 11.0469 6.95395 10.7716 7.26462 10.7716C7.57528 10.7716 7.82727 11.0469 7.82727 11.3849V15.1515H7.82794V15.1521ZM10.5479 15.6908C9.4679 15.6908 8.59059 14.5801 8.59059 13.2155C8.59059 11.8509 9.4679 10.7402 10.5479 10.7402C11.6278 10.7402 12.5078 11.8509 12.5078 13.2155C12.5065 14.5801 11.6278 15.6908 10.5479 15.6908V15.6908ZM15.6504 12.1022H14.9351V15.1188C14.9351 15.4568 14.6838 15.7321 14.3731 15.7321C14.0631 15.7334 13.8111 15.4588 13.8091 15.1188V12.1022H13.0951C13.0202 12.1022 12.9461 12.0862 12.8778 12.0553C12.8095 12.0244 12.7486 11.9792 12.6991 11.9229C12.5931 11.8023 12.5339 11.6475 12.5325 11.4869C12.5325 11.1482 12.7845 10.8736 13.0951 10.8736H15.6484C15.9591 10.8736 16.2104 11.1482 16.2104 11.4869C16.2099 11.6477 16.1506 11.8028 16.0437 11.9229C15.9951 11.9796 15.9348 12.0251 15.8669 12.0562C15.799 12.0872 15.7251 12.1032 15.6504 12.1029V12.1022Z' fill='%23F74343'/%3E%3C/svg%3E"
63
+ const hotIconSrc
64
+ = 'data:image/svg+xml,%3Csvg viewBox=\'0 0 20 20\' fill=\'none\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath d=\'M10.5479 11.9702C10.0966 11.9702 9.71456 12.5389 9.71456 13.2188C9.71456 13.8948 10.0966 14.4668 10.5479 14.4668C10.9992 14.4668 11.3819 13.8968 11.3819 13.2175C11.3819 12.5389 10.9999 11.9689 10.5485 11.9689L10.5479 11.9702ZM15.3977 3.54841C15.3258 3.46817 15.2338 3.40848 15.1312 3.37545C15.0286 3.34242 14.919 3.33723 14.8138 3.36042C14.6018 3.41108 14.4271 3.57374 14.3471 3.79507C14.1688 4.31816 14.0036 4.84565 13.8518 5.37704C13.6385 4.93438 13.3985 4.50972 13.1318 4.10374C12.1478 2.60444 10.7985 1.3318 8.88657 0.0985037C8.7956 0.0391916 8.69032 0.00547728 8.58182 0.000902909C8.47331 -0.00367146 8.36558 0.021063 8.26993 0.0725076C8.17116 0.129583 8.08767 0.209723 8.02661 0.306079C7.96554 0.402435 7.92871 0.512143 7.91927 0.625828C7.65327 3.22973 7.16395 5.86901 5.492 7.72696L5.27001 7.25364C5.0747 6.84432 4.89202 6.45901 4.7747 6.12901C4.64802 5.76569 4.27671 5.5837 3.94538 5.72237C3.7931 5.78848 3.67093 5.90898 3.60272 6.06034L3.46806 6.347C2.64741 8.08696 1.52544 10.4736 1.3561 12.4915C1.00477 16.7687 4.55669 19.4567 8.25059 19.9033C9.06192 20.0013 9.87722 20.0233 10.6919 19.9733C13.5965 19.784 17.125 18.1554 18.3143 14.1468C19.0843 11.5449 18.7837 7.21032 15.3977 3.54708V3.54774V3.54841ZM7.82794 15.1521C7.82794 15.4901 7.57528 15.7655 7.26462 15.7655C6.95464 15.7668 6.70329 15.4921 6.70196 15.1521V13.7588L5.542 13.7788V15.1861C5.542 15.5234 5.28934 15.7994 4.97868 15.7994C4.66936 15.8008 4.41669 15.5261 4.41536 15.1861V11.4189C4.41536 11.0802 4.66735 10.8056 4.97868 10.8056C5.28934 10.8056 5.54134 11.0802 5.54134 11.4189V12.5515L6.70196 12.5322V11.3855C6.70196 11.0469 6.95395 10.7716 7.26462 10.7716C7.57528 10.7716 7.82727 11.0469 7.82727 11.3849V15.1515H7.82794V15.1521ZM10.5479 15.6908C9.4679 15.6908 8.59059 14.5801 8.59059 13.2155C8.59059 11.8509 9.4679 10.7402 10.5479 10.7402C11.6278 10.7402 12.5078 11.8509 12.5078 13.2155C12.5065 14.5801 11.6278 15.6908 10.5479 15.6908V15.6908ZM15.6504 12.1022H14.9351V15.1188C14.9351 15.4568 14.6838 15.7321 14.3731 15.7321C14.0631 15.7334 13.8111 15.4588 13.8091 15.1188V12.1022H13.0951C13.0202 12.1022 12.9461 12.0862 12.8778 12.0553C12.8095 12.0244 12.7486 11.9792 12.6991 11.9229C12.5931 11.8023 12.5339 11.6475 12.5325 11.4869C12.5325 11.1482 12.7845 10.8736 13.0951 10.8736H15.6484C15.9591 10.8736 16.2104 11.1482 16.2104 11.4869C16.2099 11.6477 16.1506 11.8028 16.0437 11.9229C15.9951 11.9796 15.9348 12.0251 15.8669 12.0562C15.799 12.0872 15.7251 12.1032 15.6504 12.1029V12.1022Z\' fill=\'%23F74343\'/%3E%3C/svg%3E'
63
65
 
64
66
  const { editableAttrs } = useInlineEdit({
65
67
  editorMode: () => !!props.editorMode,
66
68
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
67
69
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
68
- onEditStart: (key) => emit('inline-edit-start', key),
70
+ onEditStart: key => emit('inline-edit-start', key),
69
71
  onEditEnd: () => emit('inline-edit-end'),
70
- onUndoRedo: (action) => emit('undo-redo', action),
72
+ onUndoRedo: action => emit('undo-redo', action),
71
73
  })
72
74
  </script>
73
75
 
74
76
  <template>
75
77
  <ul class="level-1">
76
- <li class="table-of-contents" v-bind="editableAttrs('title')">{{ title }}</li>
78
+ <li class="table-of-contents" v-bind="editableAttrs('title')">
79
+ {{ title }}
80
+ </li>
77
81
  <template v-for="group in tocGroups" :key="group.id">
78
82
  <li :class="{ 'hot-link': group.hot }">
79
83
  <a :href="`#${group.anchor}`">
@@ -85,7 +89,7 @@ const { editableAttrs } = useInlineEdit({
85
89
  width="20"
86
90
  height="20"
87
91
  alt="hot"
88
- />
92
+ >
89
93
  </a>
90
94
  </li>
91
95
  <ul v-if="group.children.length > 0" class="level-2">
@@ -27,9 +27,9 @@ const { blockEditableAttrs } = useInlineEdit({
27
27
  editorMode: () => !!props.editorMode,
28
28
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
29
29
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
30
- onEditStart: (key) => emit('inline-edit-start', key),
30
+ onEditStart: key => emit('inline-edit-start', key),
31
31
  onEditEnd: () => emit('inline-edit-end'),
32
- onUndoRedo: (action) => emit('undo-redo', action),
32
+ onUndoRedo: action => emit('undo-redo', action),
33
33
  })
34
34
  </script>
35
35