Skip to content

Commit

Permalink
chore: uses XI18n component pt1 (#3455)
Browse files Browse the repository at this point in the history
Part of #2813

This PR uses `<XI18n />` (#3420)
throughout the application in place of `v-html`.

I also turned our `vue/no-v-html` to `error` (it only warns by default)

This means we can start using "non-DNS safe" terms/vars for our i18n
texts if we need to do that.

---

I also switched some usages of `innerHTML` to use `textContent` which,
aside from other things, is apparently more performant, so may help
further speed up our CodeBlock component.

Finally, I added `eslint-plugin-no-unsanitized`, i.e. if we are linting
for `v-html` we should also lint for `innerHTML`, can't really depend on
one without the other.

There'll be a separate PR to start using `<XI18n v-slot="{ t }" />`
within non-route component (in the few places where we need that), and
also using `<XI18n v-slot="{ t }" />` within `RouteView` to provide
`RouteView::t`. Once that is done I'd like to somehow restrict usage of
`useI18n()` so that the only way to translate/localize text is via
`<XI18n />`.

---

(sidenote: our RouteAnnouncer functionality has been broken for quite
some time, I'll fix that up in a separate PR)

Signed-off-by: John Cowen <[email protected]>
  • Loading branch information
johncowen authored Jan 23, 2025
1 parent a147c81 commit ab7760e
Show file tree
Hide file tree
Showing 28 changed files with 319 additions and 237 deletions.
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"esbuild": "^0.24.2",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-import-resolver-typescript": "^3.7.0",
"eslint-plugin-no-unsanitized": "^4.1.2",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-json-schema-validator": "^5.3.1",
"eslint-plugin-vue": "^9.32.0",
Expand Down
7 changes: 5 additions & 2 deletions packages/config/src/eslint.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { defineConfig, createConfig: vueTsEslintConfig } = require('@vue/eslint-c
const importPlugin = require('eslint-plugin-import')
const stylistic = require('@stylistic/eslint-plugin')
const eslint = require('@eslint/js')
const nounsanitized = require('eslint-plugin-no-unsanitized')
const jsonSchemaValidatorPlugin = require('eslint-plugin-json-schema-validator')
const globals = require('globals')
const $config = dirname(require.resolve('@kumahq/config'))
Expand Down Expand Up @@ -107,7 +108,8 @@ function createEslintConfig(
schema: packageSchema,
},
],
}]},
}],
},
},
]

Expand Down Expand Up @@ -148,6 +150,7 @@ function createEslintConfig(

return [
eslint.configs.recommended,
nounsanitized.configs.recommended,
...vueTsConfig,
...importConfig,
...jsonSchemaValidatorConfig,
Expand Down Expand Up @@ -228,7 +231,7 @@ function createEslintConfig(
ignoreWhenEmpty: true,
ignores: ['router-link', 'pre', ...INLINE_NON_VOID_ELEMENTS],
}],
'vue/no-v-html': 'off',
'vue/no-v-html': 'error',
// Reason: https://github.com/vuejs/eslint-plugin-vue/issues/2259
'vue/no-setup-props-destructure': 'off',
'vue/comma-dangle': ['error', 'always-multiline'],
Expand Down
4 changes: 3 additions & 1 deletion packages/kuma-gui/.vitepress/theme/components/Story.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
<div class="language-vue vp-adaptive-theme">
<button title="Copy Code" class="copy"></button>
<span class="lang">vue</span>
<!-- eslint-disable vue/no-v-html -->
<div v-html="vueSource"></div>
<!-- eslint-enable -->
</div>
</details>

Expand All @@ -40,7 +42,7 @@ const props = withDefaults(defineProps<{
}>(), {
height: 300
})
const iframe = ref<HTMLIFrameElement>(null)
const iframe = ref<HTMLIFrameElement | null>(null)
const htmlSource = ref<string>('')
const highlighter = ref<Awaited<ReturnType<typeof getHighlighter>> | undefined>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ const routeView = {
addTitle: (item: string, sym: symbol) => {
const $title = title.value
if ($title) {
$title.innerHTML = t('components.route-view.route-announcer', { title: item })
$title.textContent = t('components.route-view.route-announcer', { title: item })
}
titles.set(sym, item)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@
v-for="warning in warnings"
:key="warning.kind"
:data-testid="`warning-${warning.kind}`"
v-html="t(`common.warnings.${warning.kind}`, warning.payload)"
/>
>
<XI18n
:path="`common.warnings.${warning.kind}`"
:params="warning.payload"
/>
</li>
<li
v-if="error"
:data-testid="`warning-stats-loading`"
Expand Down Expand Up @@ -505,8 +509,8 @@
class="mt-4"
variant="warning"
>
<div
v-html="t('data-planes.routes.item.mtls.disabled')"
<XI18n
path="data-planes.routes.item.mtls.disabled"
/>
</XAlert>
</template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
<AppView
:docs="t('data-planes.href.docs.data_plane_proxy')"
>
<div v-html="t('data-planes.routes.items.intro', {}, { defaultMessage: '' })" />
<XI18n
path="data-planes.routes.items.intro"
default-message=""
/>
<XCard>
<search>
<FilterBar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@
</DataCollection>
</template>

<div
v-html="t(`gateways.routes.items.navigation.${route.child()?.name}.description`, {}, { defaultMessage: '' })"
<XI18n
:path="`gateways.routes.items.navigation.${route.child()?.name}.description`"
default-message=""
/>

<RouterView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,102 +18,103 @@
/>
</h1>
</template>
<div class="stack">
<div v-html="t('hostname-generators.routes.items.intro', {}, { defaultMessage: '' })" />
<XCard>
<DataLoader
:src="uri(sources, '/hostname-generators', {}, {
page: route.params.page,
size: route.params.size,
})"
<XI18n
path="hostname-generators.routes.items.intro"
default-message=""
/>
<XCard>
<DataLoader
:src="uri(sources, '/hostname-generators', {}, {
page: route.params.page,
size: route.params.size,
})"
>
<template
#loadable="{ data }"
>
<template
#loadable="{ data }"
<DataCollection
type="hostname-generators"
:items="data?.items ?? [undefined]"
:page="route.params.page"
:page-size="route.params.size"
:total="data?.total"
@change="route.update"
>
<DataCollection
type="hostname-generators"
:items="data?.items ?? [undefined]"
:page="route.params.page"
:page-size="route.params.size"
:total="data?.total"
@change="route.update"
<AppCollection
data-testid="hostname-generator-collection"
:headers="[
{ ...me.get('headers.name'), label: t('hostname-generators.common.name'), key: 'name' },
{ ...me.get('headers.namespace'), label: t('hostname-generators.common.namespace'), key: 'namespace' },
...(can('use zones') ? [{ ...me.get('headers.zone'), label: t('hostname-generators.common.zone'), key: 'zone' }] : []),
{ ...me.get('headers.actions'), label: t('hostname-generators.common.actions'), key: 'actions', hideLabel: true },
]"
:items="data?.items"
:is-selected-row="(item) => item.name === route.params.name"
@resize="me.set"
>
<AppCollection
data-testid="hostname-generator-collection"
:headers="[
{ ...me.get('headers.name'), label: t('hostname-generators.common.name'), key: 'name' },
{ ...me.get('headers.namespace'), label: t('hostname-generators.common.namespace'), key: 'namespace' },
...(can('use zones') ? [{ ...me.get('headers.zone'), label: t('hostname-generators.common.zone'), key: 'zone' }] : []),
{ ...me.get('headers.actions'), label: t('hostname-generators.common.actions'), key: 'actions', hideLabel: true },
]"
:items="data?.items"
:is-selected-row="(item) => item.name === route.params.name"
@resize="me.set"
>
<template #name="{ row: item }">
<XCopyButton
:text="item.name"
<template #name="{ row: item }">
<XCopyButton
:text="item.name"
>
<XAction
data-action
:to="{
name: 'hostname-generator-summary-view',
params: {
name: item.id,
},
query: {
page: route.params.page,
size: route.params.size,
},
}"
>
<XAction
data-action
:to="{
name: 'hostname-generator-summary-view',
params: {
name: item.id,
},
query: {
page: route.params.page,
size: route.params.size,
},
}"
>
{{ item.name }}
</XAction>
</XCopyButton>
</template>
{{ item.name }}
</XAction>
</XCopyButton>
</template>

<template #actions="{ row: item }">
<XActionGroup>
<XAction
:to="{
name: 'hostname-generator-detail-view',
params: {
name: item.id,
},
}"
>
{{ t('common.collection.actions.view') }}
</XAction>
</XActionGroup>
</template>
</AppCollection>
<RouterView
v-if="data?.items && route.params.name"
v-slot="child"
<template #actions="{ row: item }">
<XActionGroup>
<XAction
:to="{
name: 'hostname-generator-detail-view',
params: {
name: item.id,
},
}"
>
{{ t('common.collection.actions.view') }}
</XAction>
</XActionGroup>
</template>
</AppCollection>
<RouterView
v-if="data?.items && route.params.name"
v-slot="child"
>
<SummaryView
@close="route.replace({
name: 'hostname-generator-list-view',
params: {
name: '',
},
query: {
page: route.params.page,
size: route.params.size,
},
})"
>
<SummaryView
@close="route.replace({
name: 'hostname-generator-list-view',
params: {
name: '',
},
query: {
page: route.params.page,
size: route.params.size,
},
})"
>
<component
:is="child.Component"
:items="data?.items"
/>
</SummaryView>
</RouterView>
</DataCollection>
</template>
</DataLoader>
</XCard>
</div>
<component
:is="child.Component"
:items="data?.items"
/>
</SummaryView>
</RouterView>
</DataCollection>
</template>
</DataLoader>
</XCard>
</AppView>
</RouteView>
</template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,11 @@
<ul>
<li
data-testid="warning-GLOBAL_STORE_TYPE_MEMORY"
v-html="t('common.warnings.GLOBAL_STORE_TYPE_MEMORY')"
/>
>
<XI18n
path="common.warnings.GLOBAL_STORE_TYPE_MEMORY"
/>
</li>
</ul>
</XAlert>
</div>
Expand Down
14 changes: 10 additions & 4 deletions packages/kuma-gui/src/app/meshes/views/MeshDetailView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,18 @@
<ul>
<li
v-if="!props.mesh.mtlsBackend"
v-html="t('meshes.routes.item.mtls-warning')"
/>
>
<XI18n
path="meshes.routes.item.mtls-warning"
/>
</li>
<li
v-if="props.mesh.mtlsBackend && missingTLSPolicy"
v-html="t('meshes.routes.item.mtp-warning')"
/>
>
<XI18n
path="meshes.routes.item.mtp-warning"
/>
</li>
</ul>
</template>
<XLayout
Expand Down
5 changes: 3 additions & 2 deletions packages/kuma-gui/src/app/meshes/views/MeshListView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
</h1>
</template>

<div
v-html="t('meshes.routes.items.intro', {}, { defaultMessage: '' })"
<XI18n
path="meshes.routes.items.intro"
default-message=""
/>

<XCard>
Expand Down
Loading

0 comments on commit ab7760e

Please sign in to comment.