summaryrefslogtreecommitdiff
path: root/packages/frontend-embed
diff options
context:
space:
mode:
authortaiy <53635909+taiyme@users.noreply.github.com>2025-09-10 09:22:12 +0900
committerGitHub <noreply@github.com>2025-09-10 09:22:12 +0900
commit7673874675630b68678e1d8603d0f08cd0eece31 (patch)
tree4092a1c7e5f98e22b8e71cd72101e0535c2c5ab9 /packages/frontend-embed
parent[skip ci] Update CHANGELOG.md (prepend template) (diff)
downloadmisskey-7673874675630b68678e1d8603d0f08cd0eece31.tar.gz
misskey-7673874675630b68678e1d8603d0f08cd0eece31.tar.bz2
misskey-7673874675630b68678e1d8603d0f08cd0eece31.zip
fix(eslint): add window prefix rules to frontend-embed & frontend-shared (#16531)
Diffstat (limited to 'packages/frontend-embed')
-rw-r--r--packages/frontend-embed/eslint.config.js68
-rw-r--r--packages/frontend-embed/src/boot.ts12
-rw-r--r--packages/frontend-embed/src/components/EmImgWithBlurhash.vue4
-rw-r--r--packages/frontend-embed/src/components/EmInstanceTicker.vue2
-rw-r--r--packages/frontend-embed/src/components/EmMention.vue2
-rw-r--r--packages/frontend-embed/src/components/EmPagination.vue12
-rw-r--r--packages/frontend-embed/src/server-context.ts2
-rw-r--r--packages/frontend-embed/src/server-metadata.ts2
-rw-r--r--packages/frontend-embed/src/theme.ts10
-rw-r--r--packages/frontend-embed/src/ui.vue4
10 files changed, 90 insertions, 28 deletions
diff --git a/packages/frontend-embed/eslint.config.js b/packages/frontend-embed/eslint.config.js
index 179d811e77..46247e40d5 100644
--- a/packages/frontend-embed/eslint.config.js
+++ b/packages/frontend-embed/eslint.config.js
@@ -46,9 +46,71 @@ export default [
allowSingleExtends: true,
}],
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
- // window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため
- // e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため
- 'id-denylist': ['error', 'window', 'e'],
+ // window ... グローバルスコープと衝突し、予期せぬ結果を招くため
+ // e ... error や event など、複数のキーワードの頭文字であり分かりにくいため
+ // close ... window.closeと衝突 or 紛らわしい
+ // open ... window.openと衝突 or 紛らわしい
+ // fetch ... window.fetchと衝突 or 紛らわしい
+ // location ... window.locationと衝突 or 紛らわしい
+ // document ... window.documentと衝突 or 紛らわしい
+ // history ... window.historyと衝突 or 紛らわしい
+ // scroll ... window.scrollと衝突 or 紛らわしい
+ // setTimeout ... window.setTimeoutと衝突 or 紛らわしい
+ // setInterval ... window.setIntervalと衝突 or 紛らわしい
+ // clearTimeout ... window.clearTimeoutと衝突 or 紛らわしい
+ // clearInterval ... window.clearIntervalと衝突 or 紛らわしい
+ 'id-denylist': ['error', 'window', 'e', 'close', 'open', 'fetch', 'location', 'document', 'history', 'scroll', 'setTimeout', 'setInterval', 'clearTimeout', 'clearInterval'],
+ 'no-restricted-globals': [
+ 'error',
+ {
+ 'name': 'open',
+ 'message': 'Use `window.open`.',
+ },
+ {
+ 'name': 'close',
+ 'message': 'Use `window.close`.',
+ },
+ {
+ 'name': 'fetch',
+ 'message': 'Use `window.fetch`.',
+ },
+ {
+ 'name': 'location',
+ 'message': 'Use `window.location`.',
+ },
+ {
+ 'name': 'document',
+ 'message': 'Use `window.document`.',
+ },
+ {
+ 'name': 'history',
+ 'message': 'Use `window.history`.',
+ },
+ {
+ 'name': 'scroll',
+ 'message': 'Use `window.scroll`.',
+ },
+ {
+ 'name': 'setTimeout',
+ 'message': 'Use `window.setTimeout`.',
+ },
+ {
+ 'name': 'setInterval',
+ 'message': 'Use `window.setInterval`.',
+ },
+ {
+ 'name': 'clearTimeout',
+ 'message': 'Use `window.clearTimeout`.',
+ },
+ {
+ 'name': 'clearInterval',
+ 'message': 'Use `window.clearInterval`.',
+ },
+ {
+ 'name': 'name',
+ 'message': 'Use `window.name`. もしくは name という変数名を定義し忘れている',
+ },
+ ],
'no-shadow': ['warn'],
'vue/attributes-order': ['error', {
alphabetical: false,
diff --git a/packages/frontend-embed/src/boot.ts b/packages/frontend-embed/src/boot.ts
index 9d69437c30..961cbcef66 100644
--- a/packages/frontend-embed/src/boot.ts
+++ b/packages/frontend-embed/src/boot.ts
@@ -33,7 +33,7 @@ import type { Theme } from '@/theme.js';
console.log('Misskey Embed');
//#region Embedパラメータの取得・パース
-const params = new URLSearchParams(location.search);
+const params = new URLSearchParams(window.location.search);
const embedParams = parseEmbedParams(params);
if (_DEV_) console.log(embedParams);
//#endregion
@@ -81,7 +81,7 @@ storeBootloaderErrors({ ...i18n.ts._bootErrors, reload: i18n.ts.reload });
//#endregion
// サイズの制限
-document.documentElement.style.maxWidth = '500px';
+window.document.documentElement.style.maxWidth = '500px';
// iframeIdの設定
function setIframeIdHandler(event: MessageEvent) {
@@ -114,16 +114,16 @@ app.provide(DI.embedParams, embedParams);
const rootEl = ((): HTMLElement => {
const MISSKEY_MOUNT_DIV_ID = 'misskey_app';
- const currentRoot = document.getElementById(MISSKEY_MOUNT_DIV_ID);
+ const currentRoot = window.document.getElementById(MISSKEY_MOUNT_DIV_ID);
if (currentRoot) {
console.warn('multiple import detected');
return currentRoot;
}
- const root = document.createElement('div');
+ const root = window.document.createElement('div');
root.id = MISSKEY_MOUNT_DIV_ID;
- document.body.appendChild(root);
+ window.document.body.appendChild(root);
return root;
})();
@@ -159,7 +159,7 @@ console.log(i18n.tsx._selfXssPrevention.description3({ link: 'https://misskey-hu
//#endregion
function removeSplash() {
- const splash = document.getElementById('splash');
+ const splash = window.document.getElementById('splash');
if (splash) {
splash.style.opacity = '0';
splash.style.pointerEvents = 'none';
diff --git a/packages/frontend-embed/src/components/EmImgWithBlurhash.vue b/packages/frontend-embed/src/components/EmImgWithBlurhash.vue
index 0bff048ce4..71f0ee9294 100644
--- a/packages/frontend-embed/src/components/EmImgWithBlurhash.vue
+++ b/packages/frontend-embed/src/components/EmImgWithBlurhash.vue
@@ -19,7 +19,7 @@ import { extractAvgColorFromBlurhash } from '@@/js/extract-avg-color-from-blurha
const canvasPromise = new Promise<WorkerMultiDispatch | HTMLCanvasElement>(resolve => {
// テスト環境で Web Worker インスタンスは作成できない
if (import.meta.env.MODE === 'test') {
- const canvas = document.createElement('canvas');
+ const canvas = window.document.createElement('canvas');
canvas.width = 64;
canvas.height = 64;
resolve(canvas);
@@ -34,7 +34,7 @@ const canvasPromise = new Promise<WorkerMultiDispatch | HTMLCanvasElement>(resol
);
resolve(workers);
} else {
- const canvas = document.createElement('canvas');
+ const canvas = window.document.createElement('canvas');
canvas.width = 64;
canvas.height = 64;
resolve(canvas);
diff --git a/packages/frontend-embed/src/components/EmInstanceTicker.vue b/packages/frontend-embed/src/components/EmInstanceTicker.vue
index 4a116e317a..7add3bb53f 100644
--- a/packages/frontend-embed/src/components/EmInstanceTicker.vue
+++ b/packages/frontend-embed/src/components/EmInstanceTicker.vue
@@ -29,7 +29,7 @@ const props = defineProps<{
// if no instance data is given, this is for the local instance
const instance = props.instance ?? {
name: serverMetadata.name,
- themeColor: (document.querySelector('meta[name="theme-color-orig"]') as HTMLMetaElement)?.content,
+ themeColor: (window.document.querySelector('meta[name="theme-color-orig"]') as HTMLMetaElement)?.content,
};
const faviconUrl = computed(() => props.instance ? mediaProxy.getProxiedImageUrlNullable(props.instance.faviconUrl, 'preview') : mediaProxy.getProxiedImageUrlNullable(serverMetadata.iconUrl, 'preview') ?? '/favicon.ico');
diff --git a/packages/frontend-embed/src/components/EmMention.vue b/packages/frontend-embed/src/components/EmMention.vue
index b5aaa95894..0a8ac9c05a 100644
--- a/packages/frontend-embed/src/components/EmMention.vue
+++ b/packages/frontend-embed/src/components/EmMention.vue
@@ -27,7 +27,7 @@ const canonical = props.host === localHost ? `@${props.username}` : `@${props.us
const url = `/${canonical}`;
-const bg = tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--MI_THEME-mention'));
+const bg = tinycolor(getComputedStyle(window.document.documentElement).getPropertyValue('--MI_THEME-mention'));
bg.setAlpha(0.1);
const bgCss = bg.toRgbString();
</script>
diff --git a/packages/frontend-embed/src/components/EmPagination.vue b/packages/frontend-embed/src/components/EmPagination.vue
index 94a91305f4..bd49d127a9 100644
--- a/packages/frontend-embed/src/components/EmPagination.vue
+++ b/packages/frontend-embed/src/components/EmPagination.vue
@@ -134,7 +134,7 @@ const isBackTop = ref(false);
const empty = computed(() => items.value.size === 0);
const error = ref(false);
-const scrollableElement = computed(() => rootEl.value ? getScrollContainer(rootEl.value) : document.body);
+const scrollableElement = computed(() => rootEl.value ? getScrollContainer(rootEl.value) : window.document.body);
const visibility = useDocumentVisibility();
@@ -353,7 +353,7 @@ watch(visibility, () => {
BACKGROUND_PAUSE_WAIT_SEC * 1000);
} else { // 'visible'
if (timerForSetPause) {
- clearTimeout(timerForSetPause);
+ window.clearTimeout(timerForSetPause);
timerForSetPause = null;
} else {
isPausingUpdate = false;
@@ -447,11 +447,11 @@ onBeforeMount(() => {
init().then(() => {
if (props.pagination.reversed) {
nextTick(() => {
- setTimeout(toBottom, 800);
+ window.setTimeout(toBottom, 800);
// scrollToBottomでmoreFetchingボタンが画面外まで出るまで
// more = trueを遅らせる
- setTimeout(() => {
+ window.setTimeout(() => {
moreFetching.value = false;
}, 2000);
});
@@ -461,11 +461,11 @@ onBeforeMount(() => {
onBeforeUnmount(() => {
if (timerForSetPause) {
- clearTimeout(timerForSetPause);
+ window.clearTimeout(timerForSetPause);
timerForSetPause = null;
}
if (preventAppearFetchMoreTimer.value) {
- clearTimeout(preventAppearFetchMoreTimer.value);
+ window.clearTimeout(preventAppearFetchMoreTimer.value);
preventAppearFetchMoreTimer.value = null;
}
scrollObserver.value?.disconnect();
diff --git a/packages/frontend-embed/src/server-context.ts b/packages/frontend-embed/src/server-context.ts
index a84a1a726a..c061d5a6f1 100644
--- a/packages/frontend-embed/src/server-context.ts
+++ b/packages/frontend-embed/src/server-context.ts
@@ -4,7 +4,7 @@
*/
import * as Misskey from 'misskey-js';
-const providedContextEl = document.getElementById('misskey_embedCtx');
+const providedContextEl = window.document.getElementById('misskey_embedCtx');
export type ServerContext = {
clip?: Misskey.entities.Clip;
diff --git a/packages/frontend-embed/src/server-metadata.ts b/packages/frontend-embed/src/server-metadata.ts
index 6c94aacd48..ad9b5a1a91 100644
--- a/packages/frontend-embed/src/server-metadata.ts
+++ b/packages/frontend-embed/src/server-metadata.ts
@@ -6,7 +6,7 @@
import * as Misskey from 'misskey-js';
import { misskeyApi } from '@/misskey-api.js';
-const providedMetaEl = document.getElementById('misskey_meta');
+const providedMetaEl = window.document.getElementById('misskey_meta');
const _serverMetadata: Misskey.entities.MetaDetailed | null = (providedMetaEl && providedMetaEl.textContent) ? JSON.parse(providedMetaEl.textContent) : null;
diff --git a/packages/frontend-embed/src/theme.ts b/packages/frontend-embed/src/theme.ts
index c9b1c0d0c6..c7bc5df85d 100644
--- a/packages/frontend-embed/src/theme.ts
+++ b/packages/frontend-embed/src/theme.ts
@@ -35,15 +35,15 @@ export function assertIsTheme(theme: Record<string, unknown>): theme is Theme {
export function applyTheme(theme: Theme, persist = true) {
if (timeout) window.clearTimeout(timeout);
- document.documentElement.classList.add('_themeChanging_');
+ window.document.documentElement.classList.add('_themeChanging_');
timeout = window.setTimeout(() => {
- document.documentElement.classList.remove('_themeChanging_');
+ window.document.documentElement.classList.remove('_themeChanging_');
}, 1000);
const colorScheme = theme.base === 'dark' ? 'dark' : 'light';
- document.documentElement.dataset.colorScheme = colorScheme;
+ window.document.documentElement.dataset.colorScheme = colorScheme;
// Deep copy
const _theme = JSON.parse(JSON.stringify(theme));
@@ -55,7 +55,7 @@ export function applyTheme(theme: Theme, persist = true) {
const props = compile(_theme);
- for (const tag of document.head.children) {
+ for (const tag of window.document.head.children) {
if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') {
tag.setAttribute('content', props['htmlThemeColor']);
break;
@@ -63,7 +63,7 @@ export function applyTheme(theme: Theme, persist = true) {
}
for (const [k, v] of Object.entries(props)) {
- document.documentElement.style.setProperty(`--MI_THEME-${k}`, v.toString());
+ window.document.documentElement.style.setProperty(`--MI_THEME-${k}`, v.toString());
}
// iframeを正常に透過させるために、cssのcolor-schemeは `light dark;` 固定にしてある。style.scss参照
diff --git a/packages/frontend-embed/src/ui.vue b/packages/frontend-embed/src/ui.vue
index 4ba5968a91..711d0eae6d 100644
--- a/packages/frontend-embed/src/ui.vue
+++ b/packages/frontend-embed/src/ui.vue
@@ -52,8 +52,8 @@ function safeURIDecode(str: string): string {
}
}
-const page = location.pathname.split('/')[2];
-const contentId = safeURIDecode(location.pathname.split('/')[3]);
+const page = window.location.pathname.split('/')[2];
+const contentId = safeURIDecode(window.location.pathname.split('/')[3]);
if (_DEV_) console.log(page, contentId);
const embedParams = inject(DI.embedParams, defaultEmbedParams);