feat(editor): Harmonize rendering of new-lines in RunData (#9614)

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: Giulio Andreini <g.andreini@gmail.com>
This commit is contained in:
oleg 2024-06-10 15:24:17 +02:00 committed by GitHub
parent 22bdb0568e
commit bc3dcf706f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 311 additions and 68 deletions

View file

@ -126,6 +126,8 @@
--color-code-gutterBackground: var(--prim-gray-670); --color-code-gutterBackground: var(--prim-gray-670);
--color-code-gutterForeground: var(--prim-gray-320); --color-code-gutterForeground: var(--prim-gray-320);
--color-code-tags-comment: var(--prim-gray-200); --color-code-tags-comment: var(--prim-gray-200);
--color-line-break: var(--prim-gray-420);
--color-code-line-break: var(--prim-color-secondary-tint-100);
// Variables // Variables
--color-variables-usage-font: var(--prim-color-alt-a-tint-300); --color-variables-usage-font: var(--prim-color-alt-a-tint-300);

View file

@ -163,6 +163,8 @@
--color-code-gutterBackground: var(--prim-gray-0); --color-code-gutterBackground: var(--prim-gray-0);
--color-code-gutterForeground: var(--prim-gray-320); --color-code-gutterForeground: var(--prim-gray-320);
--color-code-tags-comment: var(--prim-gray-420); --color-code-tags-comment: var(--prim-gray-420);
--color-line-break: var(--prim-gray-320);
--color-code-line-break: var(--prim-color-secondary-tint-200);
// Variables // Variables
--color-variables-usage-font: var(--color-success); --color-variables-usage-font: var(--color-success);

View file

@ -264,6 +264,7 @@ export default defineComponent({
<style lang="scss"> <style lang="scss">
.vjs-tree { .vjs-tree {
color: var(--color-json-default); color: var(--color-json-default);
--color-line-break: var(--color-code-line-break);
} }
.vjs-tree-node { .vjs-tree-node {

View file

@ -38,6 +38,7 @@ const key = computed((): string | undefined => {
const schemaName = computed(() => const schemaName = computed(() =>
isSchemaParentTypeArray.value ? `${props.schema.type}[${props.schema.key}]` : props.schema.key, isSchemaParentTypeArray.value ? `${props.schema.type}[${props.schema.key}]` : props.schema.key,
); );
const text = computed(() => const text = computed(() =>
Array.isArray(props.schema.value) ? '' : shorten(props.schema.value, 600, 0), Array.isArray(props.schema.value) ? '' : shorten(props.schema.value, 600, 0),
); );
@ -114,7 +115,11 @@ const getIconBySchemaType = (type: Schema['type']): string => {
/> />
</span> </span>
</div> </div>
<span v-if="text" :class="$style.text">{{ text }}</span> <span v-if="text" :class="$style.text">
<template v-for="(line, index) in text.split('\n')" :key="`line-${index}`">
<span v-if="index > 0" :class="$style.newLine">\n</span>{{ line }}
</template>
</span>
<input v-if="level > 0 && isSchemaValueArray" :id="subKey" type="checkbox" checked /> <input v-if="level > 0 && isSchemaValueArray" :id="subKey" type="checkbox" checked />
<label v-if="level > 0 && isSchemaValueArray" :class="$style.toggle" :for="subKey"> <label v-if="level > 0 && isSchemaValueArray" :class="$style.toggle" :for="subKey">
<font-awesome-icon icon="angle-up" /> <font-awesome-icon icon="angle-up" />
@ -286,6 +291,12 @@ const getIconBySchemaType = (type: Schema['type']): string => {
font-size: var(--font-size-2xs); font-size: var(--font-size-2xs);
overflow: hidden; overflow: hidden;
word-break: break-word; word-break: break-word;
.newLine {
font-family: var(--font-family-monospace);
color: var(--color-line-break);
padding-right: 2px;
}
} }
.toggle { .toggle {

View file

@ -388,7 +388,7 @@ export default defineComponent({
return this.$locale.baseText('runData.emptyString'); return this.$locale.baseText('runData.emptyString');
} }
if (typeof value === 'string') { if (typeof value === 'string') {
return value.replaceAll('\n', '\\n'); return value;
} }
if (Array.isArray(value) && value.length === 0) { if (Array.isArray(value) && value.length === 0) {
return this.$locale.baseText('runData.emptyArray'); return this.$locale.baseText('runData.emptyArray');

View file

@ -48,5 +48,20 @@ const parts = computed(() => {
<span v-else-if="part.content" :key="`span-${index}`">{{ part.content }}</span> <span v-else-if="part.content" :key="`span-${index}`">{{ part.content }}</span>
</template> </template>
</span> </span>
<span v-else>{{ props.content }}</span> <span v-else :class="$style.content">
<template v-if="typeof props.content === 'string'">
<span v-for="(line, index) in props.content.split('\n')" :key="`line-${index}`">
<span v-if="index > 0" :class="$style.newLine">\n</span>{{ line }}
</span>
</template>
<span v-else v-text="props.content" />
</span>
</template> </template>
<style lang="scss" module>
:root .content .newLine {
font-family: var(--font-family-monospace);
color: var(--color-line-break);
padding-right: 2px;
}
</style>

View file

@ -21,7 +21,9 @@ describe('TextWithHighlights', () => {
}, },
}); });
expect(wrapper.html()).toEqual('<span>Test content</span>'); expect(wrapper.html()).toEqual(
'<span class="content"><span><!--v-if-->Test content</span></span>',
);
expect(wrapper.html()).not.toContain('<mark>'); expect(wrapper.html()).not.toContain('<mark>');
}); });
@ -32,18 +34,19 @@ describe('TextWithHighlights', () => {
}, },
}); });
expect(wrapper.html()).toEqual('<span>1</span>'); expect(wrapper.html()).toEqual('<span class="content"><span>1</span></span>');
expect(wrapper.html()).not.toContain('<mark>'); expect(wrapper.html()).not.toContain('<mark>');
}); });
it('renders correctly objects when search is not set', () => { it('renders correctly objects when search is not set', async () => {
const wrapper = shallowMount(TextWithHighlights, { const wrapper = shallowMount(TextWithHighlights, {
props: { props: {
content: { hello: 'world' }, content: { hello: 'world' },
}, },
}); });
expect(wrapper.html()).toEqual(
expect(wrapper.html()).toEqual('<span>{\n "hello": "world"\n}</span>'); '<span class="content"><span>{\n "hello": "world"\n}</span></span>',
);
expect(wrapper.html()).not.toContain('<mark>'); expect(wrapper.html()).not.toContain('<mark>');
}); });
@ -55,7 +58,9 @@ describe('TextWithHighlights', () => {
}, },
}); });
expect(wrapper.html()).toEqual('<span>{\n "hello": "world"\n}</span>'); expect(wrapper.html()).toEqual(
'<span class="content"><span>{\n "hello": "world"\n}</span></span>',
);
expect(wrapper.html()).not.toContain('<mark>'); expect(wrapper.html()).not.toContain('<mark>');
}); });
@ -100,4 +105,16 @@ describe('TextWithHighlights', () => {
'<span><span>Test content </span><mark>()^${}[]</mark><span> world</span></span>', '<span><span>Test content </span><mark>()^${}[]</mark><span> world</span></span>',
); );
}); });
it('renders new lines in the content correctly', () => {
const wrapper = shallowMount(TextWithHighlights, {
props: {
content: 'Line 1\n Line 2\nLine 3',
},
});
expect(wrapper.html()).toContain(
'<span class="content"><span><!--v-if-->Line 1</span><span><span class="newLine">\\n</span> Line 2</span><span><span class="newLine">\\n</span>Line 3</span></span>',
);
});
}); });

View file

@ -86,14 +86,19 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
> >
<span <span
class="mappable" class="content mappable"
data-depth="2" data-depth="2"
data-name="list" data-name="list"
data-path="[0].list" data-path="[0].list"
data-target="mappable" data-target="mappable"
data-value="{{ $('Set').item.json.list }}" data-value="{{ $('Set').item.json.list }}"
> >
"list"
<span>
<!--v-if-->
"list"
</span>
</span> </span>
<span <span
@ -140,14 +145,19 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
> >
<span <span
class="mappable ph-no-capture" class="content mappable ph-no-capture"
data-depth="3" data-depth="3"
data-name="list[0]" data-name="list[0]"
data-path="[0].list[0]" data-path="[0].list[0]"
data-target="mappable" data-target="mappable"
data-value="{{ $('Set').item.json.list[0] }}" data-value="{{ $('Set').item.json.list[0] }}"
> >
1
<span>
<!--v-if-->
1
</span>
</span> </span>
</span> </span>
@ -185,14 +195,19 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
> >
<span <span
class="mappable ph-no-capture" class="content mappable ph-no-capture"
data-depth="3" data-depth="3"
data-name="list[1]" data-name="list[1]"
data-path="[0].list[1]" data-path="[0].list[1]"
data-target="mappable" data-target="mappable"
data-value="{{ $('Set').item.json.list[1] }}" data-value="{{ $('Set').item.json.list[1] }}"
> >
2
<span>
<!--v-if-->
2
</span>
</span> </span>
</span> </span>
@ -230,14 +245,19 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
> >
<span <span
class="mappable ph-no-capture" class="content mappable ph-no-capture"
data-depth="3" data-depth="3"
data-name="list[2]" data-name="list[2]"
data-path="[0].list[2]" data-path="[0].list[2]"
data-target="mappable" data-target="mappable"
data-value="{{ $('Set').item.json.list[2] }}" data-value="{{ $('Set').item.json.list[2] }}"
> >
3
<span>
<!--v-if-->
3
</span>
</span> </span>
</span> </span>
@ -299,14 +319,19 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
> >
<span <span
class="mappable" class="content mappable"
data-depth="2" data-depth="2"
data-name="record" data-name="record"
data-path="[0].record" data-path="[0].record"
data-target="mappable" data-target="mappable"
data-value="{{ $('Set').item.json.record }}" data-value="{{ $('Set').item.json.record }}"
> >
"record"
<span>
<!--v-if-->
"record"
</span>
</span> </span>
<span <span
@ -351,14 +376,19 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
> >
<span <span
class="mappable" class="content mappable"
data-depth="3" data-depth="3"
data-name="name" data-name="name"
data-path="[0].record.name" data-path="[0].record.name"
data-target="mappable" data-target="mappable"
data-value="{{ $('Set').item.json.record.name }}" data-value="{{ $('Set').item.json.record.name }}"
> >
"name"
<span>
<!--v-if-->
"name"
</span>
</span> </span>
<span <span
@ -372,8 +402,15 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
class="vjs-value vjs-value-string" class="vjs-value vjs-value-string"
> >
<span> <span
"Joe" class="content"
>
<span>
<!--v-if-->
"Joe"
</span>
</span> </span>
</span> </span>
@ -435,14 +472,19 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
> >
<span <span
class="mappable" class="content mappable"
data-depth="2" data-depth="2"
data-name="myNumber" data-name="myNumber"
data-path="[0].myNumber" data-path="[0].myNumber"
data-target="mappable" data-target="mappable"
data-value="{{ $('Set').item.json.myNumber }}" data-value="{{ $('Set').item.json.myNumber }}"
> >
"myNumber"
<span>
<!--v-if-->
"myNumber"
</span>
</span> </span>
<span <span
@ -456,8 +498,15 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
class="vjs-value vjs-value-number" class="vjs-value vjs-value-number"
> >
<span> <span
123 class="content"
>
<span>
<!--v-if-->
123
</span>
</span> </span>
</span> </span>
@ -490,14 +539,19 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
> >
<span <span
class="mappable" class="content mappable"
data-depth="2" data-depth="2"
data-name="myStringNumber" data-name="myStringNumber"
data-path="[0].myStringNumber" data-path="[0].myStringNumber"
data-target="mappable" data-target="mappable"
data-value="{{ $('Set').item.json.myStringNumber }}" data-value="{{ $('Set').item.json.myStringNumber }}"
> >
"myStringNumber"
<span>
<!--v-if-->
"myStringNumber"
</span>
</span> </span>
<span <span
@ -511,8 +565,15 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
class="vjs-value vjs-value-string" class="vjs-value vjs-value-string"
> >
<span> <span
"456" class="content"
>
<span>
<!--v-if-->
"456"
</span>
</span> </span>
</span> </span>
@ -545,14 +606,19 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
> >
<span <span
class="mappable" class="content mappable"
data-depth="2" data-depth="2"
data-name="myStringText" data-name="myStringText"
data-path="[0].myStringText" data-path="[0].myStringText"
data-target="mappable" data-target="mappable"
data-value="{{ $('Set').item.json.myStringText }}" data-value="{{ $('Set').item.json.myStringText }}"
> >
"myStringText"
<span>
<!--v-if-->
"myStringText"
</span>
</span> </span>
<span <span
@ -566,8 +632,15 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
class="vjs-value vjs-value-string" class="vjs-value vjs-value-string"
> >
<span> <span
"abc" class="content"
>
<span>
<!--v-if-->
"abc"
</span>
</span> </span>
</span> </span>
@ -600,14 +673,19 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
> >
<span <span
class="mappable" class="content mappable"
data-depth="2" data-depth="2"
data-name="nil" data-name="nil"
data-path="[0].nil" data-path="[0].nil"
data-target="mappable" data-target="mappable"
data-value="{{ $('Set').item.json.nil }}" data-value="{{ $('Set').item.json.nil }}"
> >
"nil"
<span>
<!--v-if-->
"nil"
</span>
</span> </span>
<span <span
@ -621,8 +699,15 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
class="vjs-value vjs-value-null" class="vjs-value vjs-value-null"
> >
<span> <span
null class="content"
>
<span>
<!--v-if-->
null
</span>
</span> </span>
</span> </span>
@ -655,14 +740,19 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
> >
<span <span
class="mappable" class="content mappable"
data-depth="2" data-depth="2"
data-name="d" data-name="d"
data-path="[0].d" data-path="[0].d"
data-target="mappable" data-target="mappable"
data-value="{{ $('Set').item.json.d }}" data-value="{{ $('Set').item.json.d }}"
> >
"d"
<span>
<!--v-if-->
"d"
</span>
</span> </span>
<span <span
@ -676,7 +766,11 @@ exports[`RunDataJson.vue > renders json values properly 1`] = `
class="vjs-value vjs-value-undefined" class="vjs-value vjs-value-undefined"
> >
<span /> <span
class="content"
>
<span />
</span>
</span> </span>
<!----> <!---->

View file

@ -59,16 +59,26 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
</svg> </svg>
<!--v-if--> <!--v-if-->
<span <span
class="" class="content"
> >
name
<span>
<!--v-if-->
name
</span>
</span> </span>
</span> </span>
</div> </div>
<span <span
class="text" class="text"
> >
<!--v-if-->
John John
</span> </span>
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
@ -109,16 +119,26 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
</svg> </svg>
<!--v-if--> <!--v-if-->
<span <span
class="" class="content"
> >
age
<span>
<!--v-if-->
age
</span>
</span> </span>
</span> </span>
</div> </div>
<span <span
class="text" class="text"
> >
<!--v-if-->
22 22
</span> </span>
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
@ -159,9 +179,14 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
</svg> </svg>
<!--v-if--> <!--v-if-->
<span <span
class="" class="content"
> >
hobbies
<span>
<!--v-if-->
hobbies
</span>
</span> </span>
</span> </span>
</div> </div>
@ -228,20 +253,37 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
fill="currentColor" fill="currentColor"
/> />
</svg> </svg>
<span> <span
hobbies class="content"
>
<span>
<!--v-if-->
hobbies
</span>
</span> </span>
<span <span
class="arrayIndex" class="content arrayIndex"
> >
[0]
<span>
<!--v-if-->
[0]
</span>
</span> </span>
</span> </span>
</div> </div>
<span <span
class="text" class="text"
> >
<!--v-if-->
surfing surfing
</span> </span>
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
@ -280,20 +322,37 @@ exports[`RunDataJsonSchema.vue > renders schema for data 1`] = `
fill="currentColor" fill="currentColor"
/> />
</svg> </svg>
<span> <span
hobbies class="content"
>
<span>
<!--v-if-->
hobbies
</span>
</span> </span>
<span <span
class="arrayIndex" class="content arrayIndex"
> >
[1]
<span>
<!--v-if-->
[1]
</span>
</span> </span>
</span> </span>
</div> </div>
<span <span
class="text" class="text"
> >
<!--v-if-->
traveling traveling
</span> </span>
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
@ -417,9 +476,14 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
</svg> </svg>
<!--v-if--> <!--v-if-->
<span <span
class="" class="content"
> >
hello world
<span>
<!--v-if-->
hello world
</span>
</span> </span>
</span> </span>
</div> </div>
@ -486,13 +550,25 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
fill="currentColor" fill="currentColor"
/> />
</svg> </svg>
<span> <span
hello world class="content"
>
<span>
<!--v-if-->
hello world
</span>
</span> </span>
<span <span
class="arrayIndex" class="content arrayIndex"
> >
[0]
<span>
<!--v-if-->
[0]
</span>
</span> </span>
</span> </span>
</div> </div>
@ -561,9 +637,14 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
</svg> </svg>
<!--v-if--> <!--v-if-->
<span <span
class="" class="content"
> >
test
<span>
<!--v-if-->
test
</span>
</span> </span>
</span> </span>
</div> </div>
@ -632,16 +713,26 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
</svg> </svg>
<!--v-if--> <!--v-if-->
<span <span
class="" class="content"
> >
more to think about
<span>
<!--v-if-->
more to think about
</span>
</span> </span>
</span> </span>
</div> </div>
<span <span
class="text" class="text"
> >
<!--v-if-->
1 1
</span> </span>
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->
@ -685,16 +776,26 @@ exports[`RunDataJsonSchema.vue > renders schema with spaces and dots 1`] = `
</svg> </svg>
<!--v-if--> <!--v-if-->
<span <span
class="" class="content"
> >
test.how
<span>
<!--v-if-->
test.how
</span>
</span> </span>
</span> </span>
</div> </div>
<span <span
class="text" class="text"
> >
<!--v-if-->
ignore ignore
</span> </span>
<!--v-if--> <!--v-if-->
<!--v-if--> <!--v-if-->