fix(eslint): add window prefix rules to frontend-embed & frontend-shared (#16531)
This commit is contained in:
parent
6e3354f95d
commit
7673874675
|
@ -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,
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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参照
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -51,9 +51,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,
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
||||
const address = new URL(document.querySelector<HTMLMetaElement>('meta[property="instance_url"]')?.content || location.href);
|
||||
const siteName = document.querySelector<HTMLMetaElement>('meta[property="og:site_name"]')?.content;
|
||||
const address = new URL(window.document.querySelector<HTMLMetaElement>('meta[property="instance_url"]')?.content || window.location.href);
|
||||
const siteName = window.document.querySelector<HTMLMetaElement>('meta[property="og:site_name"]')?.content;
|
||||
|
||||
export const host = address.host;
|
||||
export const hostname = address.hostname;
|
||||
export const url = address.origin;
|
||||
export const port = address.port;
|
||||
export const apiUrl = location.origin + '/api';
|
||||
export const wsOrigin = location.origin;
|
||||
export const apiUrl = window.location.origin + '/api';
|
||||
export const wsOrigin = window.location.origin;
|
||||
export const lang = localStorage.getItem('lang') ?? 'en-US';
|
||||
export const langs = _LANGS_;
|
||||
export const version = _VERSION_;
|
||||
|
|
|
@ -51,7 +51,7 @@ export function onScrollTop(el: HTMLElement, cb: (topVisible: boolean) => unknow
|
|||
// - toleranceの範囲内に収まる程度の微量なスクロールが発生した
|
||||
let prevTopVisible = firstTopVisible;
|
||||
const onScroll = () => {
|
||||
if (!document.body.contains(el)) return;
|
||||
if (!window.document.body.contains(el)) return;
|
||||
|
||||
const topVisible = isHeadVisible(el, tolerance);
|
||||
if (topVisible !== prevTopVisible) {
|
||||
|
@ -78,7 +78,7 @@ export function onScrollBottom(el: HTMLElement, cb: () => unknown, tolerance = 1
|
|||
|
||||
const containerOrWindow = container ?? window;
|
||||
const onScroll = () => {
|
||||
if (!document.body.contains(el)) return;
|
||||
if (!window.document.body.contains(el)) return;
|
||||
if (isTailVisible(el, 1, container)) {
|
||||
cb();
|
||||
if (once) removeListener();
|
||||
|
@ -145,8 +145,8 @@ export function isTailVisible(el: HTMLElement, tolerance = 1, container = getScr
|
|||
// https://ja.javascript.info/size-and-scroll-window#ref-932
|
||||
export function getBodyScrollHeight() {
|
||||
return Math.max(
|
||||
document.body.scrollHeight, document.documentElement.scrollHeight,
|
||||
document.body.offsetHeight, document.documentElement.offsetHeight,
|
||||
document.body.clientHeight, document.documentElement.clientHeight,
|
||||
window.document.body.scrollHeight, window.document.documentElement.scrollHeight,
|
||||
window.document.body.offsetHeight, window.document.documentElement.offsetHeight,
|
||||
window.document.body.clientHeight, window.document.documentElement.clientHeight,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,18 +7,18 @@ import { onMounted, onUnmounted, ref } from 'vue';
|
|||
import type { Ref } from 'vue';
|
||||
|
||||
export function useDocumentVisibility(): Ref<DocumentVisibilityState> {
|
||||
const visibility = ref(document.visibilityState);
|
||||
const visibility = ref(window.document.visibilityState);
|
||||
|
||||
const onChange = (): void => {
|
||||
visibility.value = document.visibilityState;
|
||||
visibility.value = window.document.visibilityState;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('visibilitychange', onChange);
|
||||
window.document.addEventListener('visibilitychange', onChange);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('visibilitychange', onChange);
|
||||
window.document.removeEventListener('visibilitychange', onChange);
|
||||
});
|
||||
|
||||
return visibility;
|
||||
|
|
Loading…
Reference in New Issue