+
{{ $t('home.categories.allTools') }}
@@ -81,4 +119,24 @@ const { t } = useI18n();
opacity: 0;
margin-bottom: 0;
}
+
+.ghost-favorites-draggable {
+ opacity: 0.4;
+ background-color: #ccc;
+ border: 2px dashed #666;
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+ transform: scale(1.1);
+ animation: ghost-favorites-draggable-animation 0.2s ease-out;
+}
+
+@keyframes ghost-favorites-draggable-animation {
+ 0% {
+ opacity: 0;
+ transform: scale(0.9);
+ }
+ 100% {
+ opacity: 0.4;
+ transform: scale(1.0);
+ }
+}
diff --git a/src/tools/html-wysiwyg-editor/editor/menu-bar.vue b/src/tools/html-wysiwyg-editor/editor/menu-bar.vue
index d3ad3168..9069673c 100644
--- a/src/tools/html-wysiwyg-editor/editor/menu-bar.vue
+++ b/src/tools/html-wysiwyg-editor/editor/menu-bar.vue
@@ -84,8 +84,8 @@ const items: MenuItem[] = [
type: 'button',
icon: H3,
title: 'Heading 3',
- action: () => editor.value.chain().focus().toggleHeading({ level: 4 }).run(),
- isActive: () => editor.value.isActive('heading', { level: 4 }),
+ action: () => editor.value.chain().focus().toggleHeading({ level: 3 }).run(),
+ isActive: () => editor.value.isActive('heading', { level: 3 }),
},
{
type: 'button',
diff --git a/src/tools/tools.store.ts b/src/tools/tools.store.ts
index d952b7cb..fb12450d 100644
--- a/src/tools/tools.store.ts
+++ b/src/tools/tools.store.ts
@@ -14,6 +14,7 @@ export const useToolStore = defineStore('tools', () => {
return ({
...tool,
+ path: tool.path,
name: t(`tools.${toolI18nKey}.title`, tool.name),
description: t(`tools.${toolI18nKey}.description`, tool.description),
category: t(`tools.categories.${tool.category.toLowerCase()}`, tool.category),
@@ -23,8 +24,9 @@ export const useToolStore = defineStore('tools', () => {
const toolsByCategory = computed(() => {
return _.chain(tools.value)
.groupBy('category')
- .map((components, name) => ({
+ .map((components, name, path) => ({
name,
+ path,
components,
}))
.value();
@@ -32,7 +34,7 @@ export const useToolStore = defineStore('tools', () => {
const favoriteTools = computed(() => {
return favoriteToolsName.value
- .map(favoriteName => tools.value.find(({ name }) => name === favoriteName))
+ .map(favoriteName => tools.value.find(({ name, path }) => name === favoriteName || path === favoriteName))
.filter(Boolean) as ToolWithCategory[]; // cast because .filter(Boolean) does not remove undefined from type
});
@@ -43,15 +45,23 @@ export const useToolStore = defineStore('tools', () => {
newTools: computed(() => tools.value.filter(({ isNew }) => isNew)),
addToolToFavorites({ tool }: { tool: MaybeRef }) {
- favoriteToolsName.value.push(get(tool).name);
+ const toolPath = get(tool).path;
+ if (toolPath) {
+ favoriteToolsName.value.push(toolPath);
+ }
},
removeToolFromFavorites({ tool }: { tool: MaybeRef }) {
- favoriteToolsName.value = favoriteToolsName.value.filter(name => get(tool).name !== name);
+ favoriteToolsName.value = favoriteToolsName.value.filter(name => get(tool).name !== name && get(tool).path !== name);
},
isToolFavorite({ tool }: { tool: MaybeRef }) {
- return favoriteToolsName.value.includes(get(tool).name);
+ return favoriteToolsName.value.includes(get(tool).name)
+ || favoriteToolsName.value.includes(get(tool).path);
+ },
+
+ updateFavoriteTools(newOrder: ToolWithCategory[]) {
+ favoriteToolsName.value = newOrder.map(tool => tool.path);
},
};
});
diff --git a/src/tools/yaml-to-json-converter/yaml-to-json.e2e.spec.ts b/src/tools/yaml-to-json-converter/yaml-to-json.e2e.spec.ts
index 7b2a2d18..d6ed84c3 100644
--- a/src/tools/yaml-to-json-converter/yaml-to-json.e2e.spec.ts
+++ b/src/tools/yaml-to-json-converter/yaml-to-json.e2e.spec.ts
@@ -28,4 +28,53 @@ test.describe('Tool - Yaml to json', () => {
`.trim(),
);
});
+
+ test('Yaml is parsed with merge key and output correct json', async ({ page }) => {
+ await page.getByTestId('input').fill(`
+ default: &default
+ name: ''
+ age: 0
+
+ person:
+ *default
+
+ persons:
+ - <<: *default
+ age: 1
+ - <<: *default
+ name: John
+ - { age: 3, <<: *default }
+
+ `);
+
+ const generatedJson = await page.getByTestId('area-content').innerText();
+
+ expect(generatedJson.trim()).toEqual(
+ `
+{
+ "default": {
+ "name": "",
+ "age": 0
+ },
+ "person": {
+ "name": "",
+ "age": 0
+ },
+ "persons": [
+ {
+ "name": "",
+ "age": 1
+ },
+ {
+ "name": "John",
+ "age": 0
+ },
+ {
+ "age": 3,
+ "name": ""
+ }
+ ]
+}`.trim(),
+ );
+ });
});
diff --git a/src/tools/yaml-to-json-converter/yaml-to-json.vue b/src/tools/yaml-to-json-converter/yaml-to-json.vue
index 39c9297f..72608add 100644
--- a/src/tools/yaml-to-json-converter/yaml-to-json.vue
+++ b/src/tools/yaml-to-json-converter/yaml-to-json.vue
@@ -6,7 +6,7 @@ import { withDefaultOnError } from '@/utils/defaults';
function transformer(value: string) {
return withDefaultOnError(() => {
- const obj = parseYaml(value);
+ const obj = parseYaml(value, { merge: true });
return obj ? JSON.stringify(obj, null, 3) : '';
}, '');
}