Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions eslint.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const polarConfig = defineConfig({
},
],
'local/import-style': 'error',
'local/no-literal-ns-in-t': 'error',
},
})

Expand Down
2 changes: 2 additions & 0 deletions eslintRules/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import importStyle from './import-style.js'
import noLiteralNsInT from './no-literal-ns-in-t.js'

export default {
rules: {
/* eslint-disable @typescript-eslint/naming-convention */
'import-style': importStyle,
'no-literal-ns-in-t': noLiteralNsInT,
/* eslint-enable @typescript-eslint/naming-convention */
},
}
63 changes: 63 additions & 0 deletions eslintRules/no-literal-ns-in-t.ts

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be made auto-fixable? I'm sure @warm-coolguy would really enjoy that!

Also, if I add a literal in a template, this rule does not raise an issue.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I would really enjoy that, I don't think it's plausible to invest that amount of time. Also confirming it doesn't work in templates and there's a lot of templates with the issue present.

Suggestion: We drop the extra rule and just search for ns: ' and replace it in every file and call it a day.

Pro: Saves time and we have another nice thing to nag about in future PRs.
Con: There is none and it won't stop anybody from just declaring the string locally anyway. I'll just find creative ways to annoy you if you proceed.

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import type { Rule } from 'eslint'

/**
* Enforces that the `ns` option in `t`/`$t` calls uses a constant identifier
* (e.g. `PluginId` or `CoreId`) instead of a hard-coded string literal.
*
* Bad: `t(($) => $.key, { ns: 'filter' })`
* Good: `t(($) => $.key, { ns: PluginId })`
*/
const noLiteralNsInT: Rule.RuleModule = {
meta: {
type: 'suggestion',
docs: {
description:
'Enforce using `PluginId`/`CoreId` identifier instead of a string literal for the `ns` option in `t`/`$t` calls',
},
messages: {
useLiteralId:
'Use the `PluginId` (or `CoreId`) constant instead of the string literal "{{ ns }}" as the `ns` option.',
},
schema: [],
},
create(context) {
return {
/* eslint-disable @typescript-eslint/naming-convention */
CallExpression(node) {
const { callee } = node
if (
callee.type !== 'Identifier' ||
(callee.name !== 't' && callee.name !== '$t')
) {
return
}

for (const arg of node.arguments) {
if (arg.type !== 'ObjectExpression') {
continue
}

for (const prop of arg.properties) {
if (
prop.type === 'Property' &&
!prop.computed &&
((prop.key.type === 'Identifier' && prop.key.name === 'ns') ||
(prop.key.type === 'Literal' && prop.key.value === 'ns')) &&
prop.value.type === 'Literal' &&
typeof prop.value.value === 'string'
) {
context.report({
node: prop.value,
messageId: 'useLiteralId',
data: { ns: prop.value.value },
})
}
}
}
},
/* eslint-enable @typescript-eslint/naming-convention */
}
},
}

export default noLiteralNsInT
7 changes: 4 additions & 3 deletions src/core/components/PolarContainer.ce.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import { loadKern } from '../utils/loadKern'
import { teardownMarkers } from '../utils/map/setupMarkers'
import { mapZoomOffset } from '../utils/mapZoomOffset'
import { CoreId } from '../vuePlugins/i18next'
import MoveHandle from './MoveHandle.ce.vue'
import PolarMap from './PolarMap.ce.vue'
import PolarMapOverlay from './PolarMapOverlay.ce.vue'
Expand All @@ -76,10 +77,10 @@

const isMacOS = navigator.userAgent.indexOf('Mac') !== -1
const noCommandOnZoom = useT(() =>
t(($) => $.overlay.noCommandOnZoom, { ns: 'core' })
t(($) => $.overlay.noCommandOnZoom, { ns: CoreId })
)
const noControlOnZoom = useT(() =>
t(($) => $.overlay.noControlOnZoom, { ns: 'core' })
t(($) => $.overlay.noControlOnZoom, { ns: CoreId })
)

function wheelEffect(event: WheelEvent) {
Expand All @@ -95,7 +96,7 @@
}

const oneFingerPan = useT(() =>
t(($) => $.overlay.oneFingerPan, { ns: 'core' })
t(($) => $.overlay.oneFingerPan, { ns: CoreId })
)
let hammer: { destroy: () => void } | null = null
function updateListeners() {
Expand Down Expand Up @@ -204,7 +205,7 @@
resizeObserver.observe(polarWrapper.value as Element)
updateClientDimensions()

// FIXME: Improve types for lightElement

Check warning on line 208 in src/core/components/PolarContainer.ce.vue

View workflow job for this annotation

GitHub Actions / Linting

Unexpected 'fixme' comment: 'FIXME: Improve types for lightElement'
// This is necessary for making `getStore` work
;(mainStore.lightElement as { store?: unknown }).store = useCoreStore()
})
Expand Down
4 changes: 3 additions & 1 deletion src/core/utils/checkServiceAvailability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import type {
ServiceAvailabilityCheck,
} from '../types'

import { CoreId } from '../vuePlugins/i18next'

export function checkServiceAvailability(
configuration: MapConfiguration,
register: MasterportalApiServiceRegister
Expand Down Expand Up @@ -44,7 +46,7 @@ export function checkServiceAvailability(
if (statusCode !== 200) {
notifyUser('warning', () =>
t(($) => $.error.serviceUnavailable, {
ns: 'core',
ns: CoreId,
serviceId,
serviceName,
})
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/export/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { notifyUser } from '@/lib/notifyUser'

import type { ExportFormat } from './types'

import { EXPORT_FORMATS } from './types'
import { EXPORT_FORMATS, PluginId } from './types'
import { convertToPdf } from './utils/convertToPdf'
import { CrossOriginMonkey } from './utils/CrossOriginMonkey'
import { downloadAsImage } from './utils/downloadAsImage'
Expand Down Expand Up @@ -103,7 +103,7 @@ export const useExportStore = defineStore('plugins/export', () => {
console.error(error)
notifyUser('error', () =>
t(($) => $.error, {
ns: 'export',
ns: PluginId,
})
)
throw error
Expand Down
13 changes: 8 additions & 5 deletions src/plugins/geoLocation/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ import { notifyUser } from '@/lib/notifyUser'
import { passesBoundaryCheck } from '@/lib/passesBoundaryCheck'
import { getTooltip } from '@/lib/tooltip'

import type { PluginState, GeoLocationPluginOptions } from './types'

import {
type PluginState,
type GeoLocationPluginOptions,
PluginId,
} from './types'
import { detectDeniedGeolocationEarly } from './utils/detectDeniedGeolocationEarly'
import { getGeoLocationStyle } from './utils/olStyle'
import { positionChanged } from './utils/positionChanged'
Expand Down Expand Up @@ -184,7 +187,7 @@ export const useGeoLocationStore = defineStore('plugins/geoLocation', () => {
notifyUser(
'error',
t(($) => $.button.locationAccessDenied, {
ns: 'geoLocation',
ns: PluginId,
})
)
console.error(error.message)
Expand Down Expand Up @@ -282,13 +285,13 @@ export const useGeoLocationStore = defineStore('plugins/geoLocation', () => {

function printPositioningFailed(boundaryErrorOccurred: boolean) {
if (boundaryErrorOccurred) {
const msg = t(($) => $.toast.boundaryError, { ns: 'geoLocation' })
const msg = t(($) => $.toast.boundaryError, { ns: PluginId })
notifyUser('error', msg)
console.error(msg)
return
}
const msg = t(($) => $.toast.notInBoundary, {
ns: 'geoLocation',
ns: PluginId,
})
notifyUser('info', msg, { timeout: 10000 })
// eslint-disable-next-line no-console
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/iconMenu/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { type Component, computed, markRaw, ref } from 'vue'

import { useCoreStore } from '@/core/stores'

import type { Menu } from './types'
import { PluginId, type Menu } from './types'

/* eslint-disable tsdoc/syntax */
/**
Expand Down Expand Up @@ -147,11 +147,11 @@ export const useIconMenuStore = defineStore('plugins/iconMenu', () => {
open.value = null
},
closeLabel: t(($) => $.mobileCloseButton, {
ns: 'iconMenu',
plugin: t(($) => $.hints[menu.plugin.id], { ns: 'iconMenu' }),
ns: PluginId,
plugin: t(($) => $.hints[menu.plugin.id], { ns: PluginId }),
}),
component: menu.plugin.component,
plugin: 'iconMenu',
plugin: PluginId,
})
}

Expand Down
6 changes: 4 additions & 2 deletions src/plugins/pins/utils/isCoordinateInBoundaryLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import type { BoundaryOptions } from '@/core'
import { notifyUser } from '@/lib/notifyUser'
import { passesBoundaryCheck } from '@/lib/passesBoundaryCheck'

import { PluginId } from '../types'

/**
* Checks if boundary layer conditions are met; returns false if not and
* toasts to the user about why the action was blocked, if `toastAction` is
Expand Down Expand Up @@ -35,10 +37,10 @@ export async function isCoordinateInBoundaryLayer(
}

if (typeof boundaryCheckResult === 'symbol') {
notifyUser('error', () => t(($) => $.boundaryError, { ns: 'pins' }))
notifyUser('error', () => t(($) => $.boundaryError, { ns: PluginId }))
console.error('Checking boundary layer failed.')
} else {
notifyUser('info', () => t(($) => $.notInBoundary, { ns: 'pins' }))
notifyUser('info', () => t(($) => $.notInBoundary, { ns: PluginId }))
// eslint-disable-next-line no-console
console.info('Pin position outside of boundary layer:', coordinate)
}
Expand Down
Loading