@blokkli/editor 2.0.0-alpha.42 → 2.0.0-alpha.44
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/module.json +1 -1
- package/dist/module.mjs +4 -4
- package/dist/modules/agent/index.mjs +6 -2
- package/dist/modules/agent/runtime/app/composables/agentProvider.js +28 -19
- package/dist/modules/agent/runtime/app/tools/check_readability/index.js +1 -0
- package/dist/modules/agent/runtime/app/tools/delegate_text_rewrite/Component.d.vue.ts +2 -0
- package/dist/modules/agent/runtime/app/tools/delegate_text_rewrite/Component.vue +7 -3
- package/dist/modules/agent/runtime/app/tools/delegate_text_rewrite/Component.vue.d.ts +2 -0
- package/dist/modules/agent/runtime/app/tools/helpers.js +5 -3
- package/dist/modules/agent/runtime/server/Session.d.ts +2 -0
- package/dist/modules/agent/runtime/server/Session.js +17 -0
- package/dist/modules/agent/runtime/server/agent.js +2 -1
- package/dist/modules/agent/runtime/shared/types.d.ts +1 -0
- package/dist/modules/agent/runtime/shared/types.js +2 -1
- package/dist/runtime/components/BlokkliProvider.vue +14 -13
- package/dist/runtime/editor/components/Actions/Interactions/index.d.vue.ts +3 -0
- package/dist/runtime/editor/components/Actions/Interactions/index.vue +110 -0
- package/dist/runtime/editor/components/Actions/Interactions/index.vue.d.ts +3 -0
- package/dist/runtime/editor/components/Actions/index.vue +34 -3
- package/dist/runtime/editor/components/AnimationCanvas/index.vue +2 -10
- package/dist/runtime/editor/components/BundleSelector/index.vue +39 -11
- package/dist/runtime/editor/components/PreviewProvider.vue +1 -1
- package/dist/runtime/editor/components/Toolbar/index.vue +1 -2
- package/dist/runtime/editor/composables/useStickyToolbar.d.ts +1 -1
- package/dist/runtime/editor/composables/useStickyToolbar.js +25 -7
- package/dist/runtime/editor/css/output.css +1 -1
- package/dist/runtime/editor/features/analyze/Main.d.vue.ts +6 -0
- package/dist/runtime/editor/features/analyze/Main.vue +26 -1
- package/dist/runtime/editor/features/analyze/Main.vue.d.ts +6 -0
- package/dist/runtime/editor/features/analyze/Renderer/index.d.vue.ts +2 -0
- package/dist/runtime/editor/features/analyze/Renderer/index.vue +86 -15
- package/dist/runtime/editor/features/analyze/Renderer/index.vue.d.ts +2 -0
- package/dist/runtime/editor/features/analyze/analyzers/altText.d.ts +2 -0
- package/dist/runtime/editor/features/analyze/analyzers/altText.js +60 -0
- package/dist/runtime/editor/features/analyze/analyzers/headingStructure.d.ts +2 -0
- package/dist/runtime/editor/features/analyze/analyzers/headingStructure.js +141 -0
- package/dist/runtime/editor/features/analyze/analyzers/index.d.ts +5 -1
- package/dist/runtime/editor/features/analyze/analyzers/index.js +11 -1
- package/dist/runtime/editor/features/analyze/analyzers/readability.js +50 -16
- package/dist/runtime/editor/features/analyze/analyzers/types.d.ts +3 -2
- package/dist/runtime/editor/features/analyze/index.vue +12 -0
- package/dist/runtime/editor/features/analyze/readability/builtinAnalyzer.js +38 -22
- package/dist/runtime/editor/features/analyze/readability/types.d.ts +18 -3
- package/dist/runtime/editor/features/dragging-overlay/DragItems/index.d.vue.ts +1 -0
- package/dist/runtime/editor/features/dragging-overlay/DragItems/index.vue +110 -5
- package/dist/runtime/editor/features/dragging-overlay/DragItems/index.vue.d.ts +1 -0
- package/dist/runtime/editor/features/dragging-overlay/Renderer/index.d.vue.ts +1 -0
- package/dist/runtime/editor/features/dragging-overlay/Renderer/index.vue +16 -1
- package/dist/runtime/editor/features/dragging-overlay/Renderer/index.vue.d.ts +1 -0
- package/dist/runtime/editor/features/dragging-overlay/index.vue +2 -1
- package/dist/runtime/editor/features/editable-field/Overlay/ReadabilityIndicator/ChunkOverlay.d.vue.ts +8 -0
- package/dist/runtime/editor/features/editable-field/Overlay/ReadabilityIndicator/ChunkOverlay.vue +135 -0
- package/dist/runtime/editor/features/editable-field/Overlay/ReadabilityIndicator/ChunkOverlay.vue.d.ts +8 -0
- package/dist/runtime/editor/features/editable-field/Overlay/ReadabilityIndicator/index.d.vue.ts +7 -0
- package/dist/runtime/editor/features/editable-field/Overlay/ReadabilityIndicator/index.vue +187 -0
- package/dist/runtime/editor/features/editable-field/Overlay/ReadabilityIndicator/index.vue.d.ts +7 -0
- package/dist/runtime/editor/features/editable-field/Overlay/index.vue +23 -0
- package/dist/runtime/editor/features/hover/Renderer/index.vue +1 -1
- package/dist/runtime/editor/features/options/Form/index.vue +7 -17
- package/dist/runtime/editor/features/options/index.vue +4 -3
- package/dist/runtime/editor/features/search/Overlay/Results/Content/index.vue +7 -11
- package/dist/runtime/editor/features/search/Overlay/Results/Page/index.vue +11 -13
- package/dist/runtime/editor/features/selection/Renderer/index.vue +2 -0
- package/dist/runtime/editor/features/translations/index.vue +1 -1
- package/dist/runtime/editor/helpers/draggable/index.d.ts +3 -0
- package/dist/runtime/editor/helpers/draggable/index.js +9 -0
- package/dist/runtime/editor/providers/analyze.js +1 -1
- package/dist/runtime/editor/providers/animation.js +1 -1
- package/dist/runtime/editor/providers/readability.js +16 -20
- package/dist/runtime/editor/providers/selection.d.ts +0 -4
- package/dist/runtime/editor/providers/selection.js +0 -2
- package/dist/runtime/editor/providers/ui.d.ts +16 -0
- package/dist/runtime/editor/providers/ui.js +5 -1
- package/dist/runtime/editor/translations/de.json +129 -1
- package/dist/runtime/editor/translations/fr.json +128 -0
- package/dist/runtime/editor/translations/gsw_CH.json +128 -0
- package/dist/runtime/editor/translations/it.json +128 -0
- package/package.json +1 -1
|
@@ -27,11 +27,21 @@
|
|
|
27
27
|
v-else-if="!ui.isTransforming.value"
|
|
28
28
|
:key="animation.renderKey.value"
|
|
29
29
|
v-model="isRunning"
|
|
30
|
+
v-model:issue-count="issueCount"
|
|
31
|
+
v-model:has-violation="hasViolation"
|
|
30
32
|
:langcode="context.language"
|
|
31
33
|
:analyze
|
|
32
34
|
:is-shown
|
|
33
35
|
/>
|
|
34
36
|
</template>
|
|
37
|
+
<template v-if="issueCount" #badge>
|
|
38
|
+
<div
|
|
39
|
+
class="bk-sidebar-badge"
|
|
40
|
+
:class="hasViolation ? 'bk-is-red' : 'bk-is-yellow'"
|
|
41
|
+
>
|
|
42
|
+
{{ issueCount }}
|
|
43
|
+
</div>
|
|
44
|
+
</template>
|
|
35
45
|
</PluginSidebar>
|
|
36
46
|
</template>
|
|
37
47
|
|
|
@@ -51,6 +61,8 @@ defineBlokkliFeature({
|
|
|
51
61
|
});
|
|
52
62
|
const { $t, context, animation, ui, analyze } = useBlokkli();
|
|
53
63
|
const isRunning = ref(false);
|
|
64
|
+
const issueCount = ref(0);
|
|
65
|
+
const hasViolation = ref(false);
|
|
54
66
|
</script>
|
|
55
67
|
|
|
56
68
|
<script>
|
|
@@ -1,38 +1,39 @@
|
|
|
1
1
|
const SCORE_CONFIGS = {
|
|
2
2
|
en: {
|
|
3
|
-
label: "
|
|
4
|
-
compute: (tr, text) => tr.
|
|
5
|
-
direction: "
|
|
6
|
-
bands: { easy:
|
|
7
|
-
impactThresholds: [50,
|
|
3
|
+
label: "FRE",
|
|
4
|
+
compute: (tr, text) => tr.fleschReadingEase(text),
|
|
5
|
+
direction: "higher_easier",
|
|
6
|
+
bands: { easy: 60, ok: 30 },
|
|
7
|
+
impactThresholds: [50, 30, 10],
|
|
8
|
+
minWords: 15,
|
|
8
9
|
referenceTable: [
|
|
9
|
-
{ range: "
|
|
10
|
-
{ range: "
|
|
11
|
-
{ range: "
|
|
12
|
-
{ range: "
|
|
10
|
+
{ range: "Above 70", label: "Very easy (simple, conversational)" },
|
|
11
|
+
{ range: "60\u201370", label: "Easy (standard web content)" },
|
|
12
|
+
{ range: "50\u201360", label: "Fairly difficult (could be simpler)" },
|
|
13
|
+
{ range: "30\u201350", label: "Difficult (academic, technical)" },
|
|
13
14
|
{
|
|
14
|
-
range: "
|
|
15
|
+
range: "Below 30",
|
|
15
16
|
label: "Very difficult \u2014 this is what gets flagged"
|
|
16
17
|
},
|
|
17
|
-
{ range: "
|
|
18
|
+
{ range: "Below 10", label: "Critical \u2014 must be simplified" }
|
|
18
19
|
]
|
|
19
20
|
},
|
|
20
21
|
de: {
|
|
21
22
|
label: "WSTF",
|
|
22
23
|
compute: (tr, text) => tr.wienerSachtextformel(text, 1),
|
|
23
24
|
direction: "higher_harder",
|
|
24
|
-
bands: { easy:
|
|
25
|
-
impactThresholds: [
|
|
25
|
+
bands: { easy: 15, ok: 18 },
|
|
26
|
+
impactThresholds: [16, 20, 24],
|
|
27
|
+
minWords: 5,
|
|
26
28
|
referenceTable: [
|
|
27
|
-
{ range: "Below
|
|
28
|
-
{ range: "
|
|
29
|
-
{ range: "
|
|
30
|
-
{ range: "11\u201314", label: "Moderately difficult (official documents)" },
|
|
29
|
+
{ range: "Below 8", label: "Very easy (children's books)" },
|
|
30
|
+
{ range: "8\u201315", label: "Easy (standard website content)" },
|
|
31
|
+
{ range: "15\u201318", label: "Moderately difficult (could be simpler)" },
|
|
31
32
|
{
|
|
32
|
-
range: "Above
|
|
33
|
+
range: "Above 18",
|
|
33
34
|
label: "Difficult \u2014 this is what gets flagged"
|
|
34
35
|
},
|
|
35
|
-
{ range: "Above
|
|
36
|
+
{ range: "Above 24", label: "Critical \u2014 must be simplified" }
|
|
36
37
|
]
|
|
37
38
|
},
|
|
38
39
|
fr: {
|
|
@@ -41,6 +42,7 @@ const SCORE_CONFIGS = {
|
|
|
41
42
|
direction: "higher_harder",
|
|
42
43
|
bands: { easy: 40, ok: 59 },
|
|
43
44
|
impactThresholds: [50, 60, 70],
|
|
45
|
+
minWords: 5,
|
|
44
46
|
referenceTable: [
|
|
45
47
|
{ range: "Below 25", label: "Very easy (children's books)" },
|
|
46
48
|
{ range: "25\u201340", label: "Easy (simple articles)" },
|
|
@@ -59,6 +61,7 @@ const SCORE_CONFIGS = {
|
|
|
59
61
|
direction: "higher_easier",
|
|
60
62
|
bands: { easy: 80, ok: 60 },
|
|
61
63
|
impactThresholds: [60, 50, 40],
|
|
64
|
+
minWords: 5,
|
|
62
65
|
referenceTable: [
|
|
63
66
|
{ range: "Above 80", label: "Very easy (children's books)" },
|
|
64
67
|
{ range: "60\u201380", label: "Easy (simple articles)" },
|
|
@@ -73,7 +76,6 @@ const SCORE_CONFIGS = {
|
|
|
73
76
|
}
|
|
74
77
|
};
|
|
75
78
|
const SUPPORTED_LANGUAGES = ["en", "de", "fr", "it"];
|
|
76
|
-
const DEFAULT_MIN_WORDS = 5;
|
|
77
79
|
function getConfig(langcode) {
|
|
78
80
|
if (isSupportedLangcode(langcode)) {
|
|
79
81
|
return SCORE_CONFIGS[langcode];
|
|
@@ -153,7 +155,9 @@ export function createBuiltinReadabilityAnalyzer() {
|
|
|
153
155
|
},
|
|
154
156
|
description: "Analyzes text readability using language-specific algorithms (LIX, Wiener Sachtextformel, Gulpease).",
|
|
155
157
|
supportedLanguages: SUPPORTED_LANGUAGES,
|
|
156
|
-
minWordsForConfidence
|
|
158
|
+
get minWordsForConfidence() {
|
|
159
|
+
return getConfig(currentLangcode).minWords;
|
|
160
|
+
},
|
|
157
161
|
get scoreLabel() {
|
|
158
162
|
return getConfig(currentLangcode).label;
|
|
159
163
|
},
|
|
@@ -182,7 +186,7 @@ export function createBuiltinReadabilityAnalyzer() {
|
|
|
182
186
|
const trimmed = text.trim();
|
|
183
187
|
if (!trimmed) return null;
|
|
184
188
|
const words = segmentWords(trimmed);
|
|
185
|
-
if (words.length <
|
|
189
|
+
if (words.length < config.minWords) return null;
|
|
186
190
|
const score = safe(() => config.compute(tr, trimmed));
|
|
187
191
|
return score != null ? round(score) : null;
|
|
188
192
|
});
|
|
@@ -195,6 +199,18 @@ export function createBuiltinReadabilityAnalyzer() {
|
|
|
195
199
|
},
|
|
196
200
|
getAgentContext() {
|
|
197
201
|
return buildAgentContext(getConfig(currentLangcode));
|
|
202
|
+
},
|
|
203
|
+
getScaleInfo(langcode) {
|
|
204
|
+
const config = getConfig(langcode);
|
|
205
|
+
const t1 = Math.min(config.bands.easy, config.bands.ok);
|
|
206
|
+
const t2 = Math.max(config.bands.easy, config.bands.ok);
|
|
207
|
+
const padding = Math.round((t2 - t1) * 0.5);
|
|
208
|
+
return {
|
|
209
|
+
thresholds: [t1, t2],
|
|
210
|
+
direction: config.direction,
|
|
211
|
+
scaleMin: Math.max(0, t1 - padding),
|
|
212
|
+
scaleMax: t2 + padding
|
|
213
|
+
};
|
|
198
214
|
}
|
|
199
215
|
};
|
|
200
216
|
}
|
|
@@ -9,9 +9,9 @@ export type ReadabilityBand = 'easy' | 'ok' | 'hard';
|
|
|
9
9
|
export type ReadabilityChunkResult = {
|
|
10
10
|
text: string;
|
|
11
11
|
html?: string;
|
|
12
|
-
score: number;
|
|
13
|
-
band: ReadabilityBand;
|
|
14
|
-
impact: AnalyzeImpact;
|
|
12
|
+
score: number | null;
|
|
13
|
+
band: ReadabilityBand | null;
|
|
14
|
+
impact: AnalyzeImpact | null;
|
|
15
15
|
description?: string;
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
@@ -69,4 +69,19 @@ export type ReadabilityAnalyzer = {
|
|
|
69
69
|
* Optional display formatting for a score value.
|
|
70
70
|
*/
|
|
71
71
|
formatScore?(value: number): string;
|
|
72
|
+
/**
|
|
73
|
+
* Return scale information for visualizing score bands.
|
|
74
|
+
* Used by the UI to render a score bar with thresholds.
|
|
75
|
+
*
|
|
76
|
+
* - `thresholds`: The two boundary values between easy/ok and ok/hard.
|
|
77
|
+
* Listed in ascending order (lower value first).
|
|
78
|
+
* - `direction`: Whether higher scores mean easier or harder text.
|
|
79
|
+
* - `scaleMin`/`scaleMax`: The visual range of the score bar.
|
|
80
|
+
*/
|
|
81
|
+
getScaleInfo?(langcode: string): {
|
|
82
|
+
thresholds: [number, number];
|
|
83
|
+
direction: 'higher_easier' | 'higher_harder';
|
|
84
|
+
scaleMin: number;
|
|
85
|
+
scaleMax: number;
|
|
86
|
+
};
|
|
72
87
|
};
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
v-show="activeLabel"
|
|
15
15
|
ref="labelEl"
|
|
16
16
|
class="bk bk-dragging-overlay-label"
|
|
17
|
+
:class="labelPosition.className"
|
|
17
18
|
:style="styleLabel"
|
|
18
19
|
>
|
|
19
20
|
<Icon name="bk_mdi_drag_pan" />
|
|
@@ -45,10 +46,12 @@ const props = defineProps({
|
|
|
45
46
|
isTouch: { type: Boolean, required: true },
|
|
46
47
|
color: { type: String, required: false },
|
|
47
48
|
backgroundColor: { type: String, required: false },
|
|
48
|
-
activeLabel: { type: String, required: false }
|
|
49
|
+
activeLabel: { type: String, required: false },
|
|
50
|
+
activeRect: { type: Object, required: false }
|
|
49
51
|
});
|
|
50
52
|
const MAX_WIDTH = 350;
|
|
51
53
|
const MAX_HEIGHT = 200;
|
|
54
|
+
const LABEL_GAP = 20;
|
|
52
55
|
const labelEl = useTemplateRef("labelEl");
|
|
53
56
|
const labelWidth = ref(0);
|
|
54
57
|
const labelHeight = ref(0);
|
|
@@ -107,12 +110,109 @@ const style = computed(() => {
|
|
|
107
110
|
"--bk-active-color": props.color && props.activeLabel ? props.color : "rgba(255,255,255,0)"
|
|
108
111
|
};
|
|
109
112
|
});
|
|
110
|
-
|
|
113
|
+
function rangesOverlap(aStart, aEnd, bStart, bEnd) {
|
|
114
|
+
return aStart < bEnd && aEnd > bStart;
|
|
115
|
+
}
|
|
116
|
+
function resolveVerticalPlacement(activeRect, dragItemsRect, lw, lh, vw, vh, gap) {
|
|
117
|
+
const x = Math.min(
|
|
118
|
+
Math.max(0, activeRect.x + activeRect.width / 2 - lw / 2),
|
|
119
|
+
vw - lw
|
|
120
|
+
);
|
|
121
|
+
const overlapsHorizontally = rangesOverlap(
|
|
122
|
+
x,
|
|
123
|
+
x + lw,
|
|
124
|
+
dragItemsRect.x,
|
|
125
|
+
dragItemsRect.x + dragItemsRect.width
|
|
126
|
+
);
|
|
127
|
+
let topEdge = activeRect.y;
|
|
128
|
+
if (overlapsHorizontally) {
|
|
129
|
+
topEdge = Math.min(topEdge, dragItemsRect.y);
|
|
130
|
+
}
|
|
131
|
+
let y = topEdge - lh - gap;
|
|
132
|
+
let placement = "top";
|
|
133
|
+
if (y < 0) {
|
|
134
|
+
let bottomEdge = activeRect.y + activeRect.height;
|
|
135
|
+
if (overlapsHorizontally) {
|
|
136
|
+
bottomEdge = Math.max(bottomEdge, dragItemsRect.y + dragItemsRect.height);
|
|
137
|
+
}
|
|
138
|
+
y = bottomEdge + gap;
|
|
139
|
+
placement = "bottom";
|
|
140
|
+
}
|
|
141
|
+
y = Math.min(Math.max(0, y), vh - lh);
|
|
142
|
+
return { x, y, placement, className: `bk-is-${placement}` };
|
|
143
|
+
}
|
|
144
|
+
function resolveHorizontalPlacement(activeRect, dragItemsRect, lw, lh, vw, vh, gap) {
|
|
145
|
+
const y = Math.min(
|
|
146
|
+
Math.max(0, activeRect.y + activeRect.height / 2 - lh / 2),
|
|
147
|
+
vh - lh
|
|
148
|
+
);
|
|
149
|
+
const overlapsVertically = rangesOverlap(
|
|
150
|
+
y,
|
|
151
|
+
y + lh,
|
|
152
|
+
dragItemsRect.y,
|
|
153
|
+
dragItemsRect.y + dragItemsRect.height
|
|
154
|
+
);
|
|
155
|
+
let leftEdge = activeRect.x;
|
|
156
|
+
if (overlapsVertically) {
|
|
157
|
+
leftEdge = Math.min(leftEdge, dragItemsRect.x);
|
|
158
|
+
}
|
|
159
|
+
let x = leftEdge - lw - gap;
|
|
160
|
+
let placement = "left";
|
|
161
|
+
if (x < 0) {
|
|
162
|
+
let rightEdge = activeRect.x + activeRect.width;
|
|
163
|
+
if (overlapsVertically) {
|
|
164
|
+
rightEdge = Math.max(rightEdge, dragItemsRect.x + dragItemsRect.width);
|
|
165
|
+
}
|
|
166
|
+
x = rightEdge + gap;
|
|
167
|
+
placement = "right";
|
|
168
|
+
}
|
|
169
|
+
x = Math.min(Math.max(0, x), vw - lw);
|
|
170
|
+
return { x, y, placement, className: `bk-is-${placement}` };
|
|
171
|
+
}
|
|
172
|
+
const labelPosition = computed(() => {
|
|
173
|
+
if (props.activeRect && !props.isTouch) {
|
|
174
|
+
const vw = ui.viewport.value.width;
|
|
175
|
+
const vh = ui.viewport.value.height;
|
|
176
|
+
const lw = labelWidth.value;
|
|
177
|
+
const lh = labelHeight.value;
|
|
178
|
+
const gap = LABEL_GAP;
|
|
179
|
+
const dragItemsRect = {
|
|
180
|
+
x: translateX.value,
|
|
181
|
+
y: translateY.value,
|
|
182
|
+
width: width.value,
|
|
183
|
+
height: height.value
|
|
184
|
+
};
|
|
185
|
+
const useHorizontal = props.activeRect.width >= props.activeRect.height && props.activeRect.width < vw / 2;
|
|
186
|
+
if (useHorizontal) {
|
|
187
|
+
return resolveHorizontalPlacement(
|
|
188
|
+
props.activeRect,
|
|
189
|
+
dragItemsRect,
|
|
190
|
+
lw,
|
|
191
|
+
lh,
|
|
192
|
+
vw,
|
|
193
|
+
vh,
|
|
194
|
+
gap
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
return resolveVerticalPlacement(
|
|
198
|
+
props.activeRect,
|
|
199
|
+
dragItemsRect,
|
|
200
|
+
lw,
|
|
201
|
+
lh,
|
|
202
|
+
vw,
|
|
203
|
+
vh,
|
|
204
|
+
gap
|
|
205
|
+
);
|
|
206
|
+
}
|
|
111
207
|
const x = Math.min(
|
|
112
208
|
Math.max(10, translateX.value - labelWidth.value / 2 + width.value / 2),
|
|
113
209
|
ui.viewport.value.width - labelWidth.value
|
|
114
210
|
);
|
|
115
211
|
const y = Math.max(10, translateY.value - labelHeight.value - 20);
|
|
212
|
+
return { x, y, placement: "top", className: "bk-is-top" };
|
|
213
|
+
});
|
|
214
|
+
const styleLabel = computed(() => {
|
|
215
|
+
const { x, y } = labelPosition.value;
|
|
116
216
|
return {
|
|
117
217
|
transform: `translate(${x}px, ${y}px)`,
|
|
118
218
|
"--bk-active-background-color": props.backgroundColor && props.activeLabel ? props.backgroundColor : "rgba(255,255,255,0)",
|
|
@@ -200,8 +300,13 @@ onMounted(() => {
|
|
|
200
300
|
let boundsX = props.isTouch ? 0 : bounds.x;
|
|
201
301
|
let boundsY = props.isTouch ? translateY.value : bounds.y;
|
|
202
302
|
if (!mouseInsideBound && !props.isTouch) {
|
|
203
|
-
|
|
204
|
-
|
|
303
|
+
if (isExisting.value) {
|
|
304
|
+
boundsX = props.startCoords.x - 20;
|
|
305
|
+
boundsY = props.startCoords.y - 20;
|
|
306
|
+
} else {
|
|
307
|
+
boundsX = props.startCoords.x - bounds.width / 2;
|
|
308
|
+
boundsY = props.startCoords.y - bounds.height / 2;
|
|
309
|
+
}
|
|
205
310
|
}
|
|
206
311
|
offsetX.value = props.startCoords.x - boundsX;
|
|
207
312
|
offsetY.value = props.startCoords.y - boundsY;
|
|
@@ -254,7 +359,7 @@ onMounted(() => {
|
|
|
254
359
|
const borderRadius = isTop ? theme.getDraggableStyle(item.element).radiusMin : 4;
|
|
255
360
|
return {
|
|
256
361
|
isTop,
|
|
257
|
-
from: ui.lowPerformanceMode.value || !mouseInsideBound ? to : from,
|
|
362
|
+
from: ui.lowPerformanceMode.value || !mouseInsideBound && !isExisting.value ? to : from,
|
|
258
363
|
to,
|
|
259
364
|
width: item.element.offsetWidth,
|
|
260
365
|
height: item.element.offsetHeight,
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
:background-color="activeBackgroundColorHex"
|
|
5
5
|
:color="activeColor"
|
|
6
6
|
:label="active?.label"
|
|
7
|
+
:active-rect="activeScreenRect"
|
|
7
8
|
/>
|
|
8
9
|
</Teleport>
|
|
9
10
|
</template>
|
|
@@ -611,7 +612,8 @@ const fieldRenderPalette = computed(() => {
|
|
|
611
612
|
gradEnd: accent[500],
|
|
612
613
|
borderOuter: accent[400],
|
|
613
614
|
borderInner: accent[300],
|
|
614
|
-
color:
|
|
615
|
+
color: [255, 255, 255]
|
|
616
|
+
// color: accent[950],
|
|
615
617
|
},
|
|
616
618
|
"2": {
|
|
617
619
|
gradStart: mono[700],
|
|
@@ -667,6 +669,19 @@ const activeBackgroundColorHex = computed(() => {
|
|
|
667
669
|
}
|
|
668
670
|
return "";
|
|
669
671
|
});
|
|
672
|
+
const activeScreenRect = computed(() => {
|
|
673
|
+
if (!active.value) {
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
const scale = ui.artboardScale.value;
|
|
677
|
+
const offset = ui.artboardOffset.value;
|
|
678
|
+
return {
|
|
679
|
+
x: active.value.x * scale + offset.x,
|
|
680
|
+
y: active.value.y * scale + offset.y,
|
|
681
|
+
width: active.value.width * scale,
|
|
682
|
+
height: active.value.height * scale
|
|
683
|
+
};
|
|
684
|
+
});
|
|
670
685
|
const activeHoverField = ref(null);
|
|
671
686
|
const activeHoverRect = computed(() => {
|
|
672
687
|
if (!activeHoverField.value) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Renderer
|
|
3
3
|
v-if="dragItems.length && isVisible"
|
|
4
|
-
v-slot="{ backgroundColor, color, label }"
|
|
4
|
+
v-slot="{ backgroundColor, color, label, activeRect }"
|
|
5
5
|
:items="dragItems"
|
|
6
6
|
:box="box"
|
|
7
7
|
:mouse-x="mouseX"
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
:background-color
|
|
19
19
|
:color
|
|
20
20
|
:active-label="label"
|
|
21
|
+
:active-rect="activeRect"
|
|
21
22
|
/>
|
|
22
23
|
</Renderer>
|
|
23
24
|
<Teleport to="#bk-canvas-overlay">
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
text: string;
|
|
3
|
+
fieldType: 'plain' | 'markup';
|
|
4
|
+
element: HTMLElement;
|
|
5
|
+
};
|
|
6
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
|
+
declare const _default: typeof __VLS_export;
|
|
8
|
+
export default _default;
|
package/dist/runtime/editor/features/editable-field/Overlay/ReadabilityIndicator/ChunkOverlay.vue
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Teleport to="#bk-canvas-overlay">
|
|
3
|
+
<div
|
|
4
|
+
class="bk bk-readability-chunk-overlay"
|
|
5
|
+
:class="{ 'bk-is-stale': stale }"
|
|
6
|
+
:style="containerStyle"
|
|
7
|
+
>
|
|
8
|
+
<div
|
|
9
|
+
v-for="chunk in visibleChunks"
|
|
10
|
+
:key="chunk.index"
|
|
11
|
+
class="bk-readability-chunk-rect"
|
|
12
|
+
:class="'bk-is-' + chunk.band"
|
|
13
|
+
:style="chunk.style"
|
|
14
|
+
>
|
|
15
|
+
<span class="bk-readability-chunk-badge">
|
|
16
|
+
{{ scoreLabel }} {{ formatScore(chunk.score) }}
|
|
17
|
+
</span>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</Teleport>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script setup>
|
|
24
|
+
import {
|
|
25
|
+
ref,
|
|
26
|
+
computed,
|
|
27
|
+
watch,
|
|
28
|
+
onMounted,
|
|
29
|
+
onBeforeUnmount,
|
|
30
|
+
useBlokkli
|
|
31
|
+
} from "#imports";
|
|
32
|
+
import { onBlokkliEvent } from "#blokkli/editor/composables";
|
|
33
|
+
import { collectTextElements } from "../../../analyze/analyzers/helpers/collectTextElements";
|
|
34
|
+
const props = defineProps({
|
|
35
|
+
text: { type: String, required: true },
|
|
36
|
+
fieldType: { type: String, required: true },
|
|
37
|
+
element: { type: null, required: true }
|
|
38
|
+
});
|
|
39
|
+
const { readability, context, ui } = useBlokkli();
|
|
40
|
+
const chunks = ref([]);
|
|
41
|
+
const stale = ref(false);
|
|
42
|
+
let timeout = null;
|
|
43
|
+
let lastFullUpdate = 0;
|
|
44
|
+
const scoreLabel = computed(() => readability.analyzer.value.scoreLabel);
|
|
45
|
+
function formatScore(value) {
|
|
46
|
+
return readability.formatScore(value);
|
|
47
|
+
}
|
|
48
|
+
const containerStyle = computed(() => {
|
|
49
|
+
const offset = ui.artboardOffset.value;
|
|
50
|
+
return {
|
|
51
|
+
width: ui.artboardSize.value.width + "px",
|
|
52
|
+
height: ui.artboardSize.value.height + "px",
|
|
53
|
+
transform: `translate(${offset.x}px, ${offset.y}px) scale(${ui.artboardScale.value})`
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
const visibleChunks = computed(
|
|
57
|
+
() => chunks.value.filter((c) => c.style.width !== "0px")
|
|
58
|
+
);
|
|
59
|
+
function updatePositions() {
|
|
60
|
+
for (const chunk of chunks.value) {
|
|
61
|
+
const r = ui.getAbsoluteElementRect(chunk.element);
|
|
62
|
+
chunk.style = {
|
|
63
|
+
width: r.width + "px",
|
|
64
|
+
height: r.height + "px",
|
|
65
|
+
transform: `translate(${r.x}px, ${r.y}px)`
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function analyze(text) {
|
|
70
|
+
if (!text.trim() || props.fieldType !== "markup") {
|
|
71
|
+
chunks.value = [];
|
|
72
|
+
stale.value = false;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const chunkResults = await readability.analyzeText(
|
|
76
|
+
text,
|
|
77
|
+
context.value.language,
|
|
78
|
+
props.fieldType
|
|
79
|
+
);
|
|
80
|
+
if (chunkResults.length === 0) {
|
|
81
|
+
chunks.value = [];
|
|
82
|
+
stale.value = false;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
86
|
+
const textElements = collectTextElements(props.element);
|
|
87
|
+
const newChunks = [];
|
|
88
|
+
const count = Math.min(chunkResults.length, textElements.length);
|
|
89
|
+
for (let i = 0; i < count; i++) {
|
|
90
|
+
const result = chunkResults[i];
|
|
91
|
+
if (result.score === null || result.band === null) continue;
|
|
92
|
+
const textEl = textElements[i];
|
|
93
|
+
const r = ui.getAbsoluteElementRect(textEl.element);
|
|
94
|
+
newChunks.push({
|
|
95
|
+
index: i,
|
|
96
|
+
score: result.score,
|
|
97
|
+
band: result.band,
|
|
98
|
+
element: textEl.element,
|
|
99
|
+
style: {
|
|
100
|
+
width: r.width + "px",
|
|
101
|
+
height: r.height + "px",
|
|
102
|
+
transform: `translate(${r.x}px, ${r.y}px)`
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
chunks.value = newChunks;
|
|
107
|
+
stale.value = false;
|
|
108
|
+
}
|
|
109
|
+
watch(
|
|
110
|
+
() => props.text,
|
|
111
|
+
(newText) => {
|
|
112
|
+
if (timeout) {
|
|
113
|
+
window.clearTimeout(timeout);
|
|
114
|
+
}
|
|
115
|
+
stale.value = true;
|
|
116
|
+
timeout = window.setTimeout(() => {
|
|
117
|
+
analyze(newText);
|
|
118
|
+
}, 500);
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
onBlokkliEvent("animationFrame", (ctx) => {
|
|
122
|
+
const forceRefresh = ctx.time - lastFullUpdate > 1e3;
|
|
123
|
+
if (!forceRefresh) return;
|
|
124
|
+
lastFullUpdate = ctx.time;
|
|
125
|
+
updatePositions();
|
|
126
|
+
});
|
|
127
|
+
onMounted(() => {
|
|
128
|
+
analyze(props.text);
|
|
129
|
+
});
|
|
130
|
+
onBeforeUnmount(() => {
|
|
131
|
+
if (timeout) {
|
|
132
|
+
window.clearTimeout(timeout);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
</script>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
text: string;
|
|
3
|
+
fieldType: 'plain' | 'markup';
|
|
4
|
+
element: HTMLElement;
|
|
5
|
+
};
|
|
6
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
|
+
declare const _default: typeof __VLS_export;
|
|
8
|
+
export default _default;
|
package/dist/runtime/editor/features/editable-field/Overlay/ReadabilityIndicator/index.d.vue.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
text: string;
|
|
3
|
+
fieldType: 'plain' | 'markup';
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
6
|
+
declare const _default: typeof __VLS_export;
|
|
7
|
+
export default _default;
|