サーバーサイドのbootも分けるように
This commit is contained in:
		
							
								
								
									
										230
									
								
								packages/backend/src/server/web/boot.embed.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								packages/backend/src/server/web/boot.embed.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,230 @@ | ||||
| /* | ||||
|  * SPDX-FileCopyrightText: syuilo and misskey-project | ||||
|  * SPDX-License-Identifier: AGPL-3.0-only | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * BOOT LOADER FOR EMBED PAGE | ||||
|  * サーバーからレスポンスされるHTMLに埋め込まれるスクリプトで、以下の役割を持ちます。 | ||||
|  * - 翻訳ファイルをフェッチする。 | ||||
|  * - バージョンに基づいて適切なメインスクリプトを読み込む。 | ||||
|  * - キャッシュされたコンパイル済みテーマを適用する。 | ||||
|  * - クライアントの設定値に基づいて対応するHTMLクラス等を設定する。 | ||||
|  * テーマをこの段階で設定するのは、メインスクリプトが読み込まれる間もテーマを適用したいためです。 | ||||
|  * 注: webpackは介さないため、このファイルではrequireやimportは使えません。 | ||||
|  */ | ||||
|  | ||||
| 'use strict'; | ||||
|  | ||||
| // ブロックの中に入れないと、定義した変数がブラウザのグローバルスコープに登録されてしまい邪魔なので | ||||
| (async () => { | ||||
| 	window.onerror = (e) => { | ||||
| 		console.error(e); | ||||
| 		renderError('SOMETHING_HAPPENED'); | ||||
| 	}; | ||||
| 	window.onunhandledrejection = (e) => { | ||||
| 		console.error(e); | ||||
| 		renderError('SOMETHING_HAPPENED_IN_PROMISE'); | ||||
| 	}; | ||||
|  | ||||
| 	let forceError = localStorage.getItem('forceError'); | ||||
| 	if (forceError != null) { | ||||
| 		renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.') | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	// パラメータに応じてsplashのスタイルを変更 | ||||
| 	const params = new URLSearchParams(location.search); | ||||
| 	if (params.has('rounded') && params.get('rounded') === 'false') { | ||||
| 		document.documentElement.classList.add('norounded'); | ||||
| 	} | ||||
| 	if (params.has('border') && params.get('border') === 'false') { | ||||
| 		document.documentElement.classList.add('noborder'); | ||||
| 	} | ||||
|  | ||||
| 	//#region Detect language & fetch translations | ||||
| 	if (!localStorage.hasOwnProperty('locale')) { | ||||
| 		const supportedLangs = LANGS; | ||||
| 		let lang = localStorage.getItem('lang'); | ||||
| 		if (lang == null || !supportedLangs.includes(lang)) { | ||||
| 			if (supportedLangs.includes(navigator.language)) { | ||||
| 				lang = navigator.language; | ||||
| 			} else { | ||||
| 				lang = supportedLangs.find(x => x.split('-')[0] === navigator.language); | ||||
|  | ||||
| 				// Fallback | ||||
| 				if (lang == null) lang = 'en-US'; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		const metaRes = await window.fetch('/api/meta', { | ||||
| 			method: 'POST', | ||||
| 			body: JSON.stringify({}), | ||||
| 			credentials: 'omit', | ||||
| 			cache: 'no-cache', | ||||
| 			headers: { | ||||
| 				'Content-Type': 'application/json', | ||||
| 			}, | ||||
| 		}); | ||||
| 		if (metaRes.status !== 200) { | ||||
| 			renderError('META_FETCH'); | ||||
| 			return; | ||||
| 		} | ||||
| 		const meta = await metaRes.json(); | ||||
| 		const v = meta.version; | ||||
| 		if (v == null) { | ||||
| 			renderError('META_FETCH_V'); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		// for https://github.com/misskey-dev/misskey/issues/10202 | ||||
| 		if (lang == null || lang.toString == null || lang.toString() === 'null') { | ||||
| 			console.error('invalid lang value detected!!!', typeof lang, lang); | ||||
| 			lang = 'en-US'; | ||||
| 		} | ||||
|  | ||||
| 		const localRes = await window.fetch(`/assets/locales/${lang}.${v}.json`); | ||||
| 		if (localRes.status === 200) { | ||||
| 			localStorage.setItem('lang', lang); | ||||
| 			localStorage.setItem('locale', await localRes.text()); | ||||
| 			localStorage.setItem('localeVersion', v); | ||||
| 		} else { | ||||
| 			renderError('LOCALE_FETCH'); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 	//#endregion | ||||
|  | ||||
| 	//#region Script | ||||
| 	async function importAppScript() { | ||||
| 		await import(`/vite/${CLIENT_ENTRY}`) | ||||
| 			.catch(async e => { | ||||
| 				console.error(e); | ||||
| 				renderError('APP_IMPORT'); | ||||
| 			}); | ||||
| 	} | ||||
|  | ||||
| 	// タイミングによっては、この時点でDOMの構築が済んでいる場合とそうでない場合とがある | ||||
| 	if (document.readyState !== 'loading') { | ||||
| 		importAppScript(); | ||||
| 	} else { | ||||
| 		window.addEventListener('DOMContentLoaded', () => { | ||||
| 			importAppScript(); | ||||
| 		}); | ||||
| 	} | ||||
| 	//#endregion | ||||
|  | ||||
| 	async function addStyle(styleText) { | ||||
| 		let css = document.createElement('style'); | ||||
| 		css.appendChild(document.createTextNode(styleText)); | ||||
| 		document.head.appendChild(css); | ||||
| 	} | ||||
|  | ||||
| 	async function renderError(code) { | ||||
| 		// Cannot set property 'innerHTML' of null を回避 | ||||
| 		if (document.readyState === 'loading') { | ||||
| 			await new Promise(resolve => window.addEventListener('DOMContentLoaded', resolve)); | ||||
| 		} | ||||
| 		document.body.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" /><path d="M12 9v4" /><path d="M12 16v.01" /></svg> | ||||
| 		<div class="message">読み込みに失敗しました</div> | ||||
| 		<div class="submessage">Failed to initialize Misskey</div> | ||||
| 		<div class="submessage">Error Code: ${code}</div> | ||||
| 		<button onclick="location.reload(!0)"> | ||||
| 			<div>リロード</div> | ||||
| 			<div><small>Reload</small></div> | ||||
| 		</button>`; | ||||
| 		addStyle(` | ||||
| 		#misskey_app, | ||||
| 		#splash { | ||||
| 			display: none !important; | ||||
| 		} | ||||
|  | ||||
| 		html, | ||||
| 		body { | ||||
| 			margin: 0; | ||||
| 		} | ||||
|  | ||||
| 		body { | ||||
| 			position: relative; | ||||
| 			color: #dee7e4; | ||||
| 			font-family: Hiragino Maru Gothic Pro, BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif; | ||||
| 			line-height: 1.35; | ||||
| 			display: flex; | ||||
| 			flex-direction: column; | ||||
| 			align-items: center; | ||||
| 			justify-content: center; | ||||
| 			min-height: 100vh; | ||||
| 			margin: 0; | ||||
| 			padding: 24px; | ||||
| 			box-sizing: border-box; | ||||
| 			overflow: hidden; | ||||
|  | ||||
| 			border-radius: var(--radius, 12px); | ||||
| 			border: 1px solid rgba(231, 255, 251, 0.14); | ||||
| 		} | ||||
|  | ||||
| 		body::before { | ||||
| 			content: ''; | ||||
| 			position: fixed; | ||||
| 			top: 0; | ||||
| 			left: 0; | ||||
| 			width: 100%; | ||||
| 			height: 100%; | ||||
| 			background: #192320; | ||||
| 			border-radius: var(--radius, 12px); | ||||
| 			z-index: -1; | ||||
| 		} | ||||
|  | ||||
| 		html.embed.norounded body, | ||||
| 		html.embed.norounded body::before { | ||||
| 			border-radius: 0; | ||||
| 		} | ||||
|  | ||||
| 		html.embed.noborder body { | ||||
| 			border: none; | ||||
| 		} | ||||
|  | ||||
| 		.icon { | ||||
| 			max-width: 60px; | ||||
| 			width: 100%; | ||||
| 			height: auto; | ||||
| 			margin-bottom: 20px; | ||||
| 			color: #dec340; | ||||
| 		} | ||||
|  | ||||
| 		.message { | ||||
| 			text-align: center; | ||||
| 			font-size: 20px; | ||||
| 			font-weight: 700; | ||||
| 			margin-bottom: 20px; | ||||
| 		} | ||||
|  | ||||
| 		.submessage { | ||||
| 			text-align: center; | ||||
| 			font-size: 90%; | ||||
| 			margin-bottom: 7.5px; | ||||
| 		} | ||||
|  | ||||
| 		.submessage:last-of-type { | ||||
| 			margin-bottom: 20px; | ||||
| 		} | ||||
|  | ||||
| 		button { | ||||
| 			padding: 7px 14px; | ||||
| 			min-width: 100px; | ||||
| 			font-weight: 700; | ||||
| 			font-family: Hiragino Maru Gothic Pro, BIZ UDGothic, Roboto, HelveticaNeue, Arial, sans-serif; | ||||
| 			line-height: 1.35; | ||||
| 			border-radius: 99rem; | ||||
| 			background-color: #b4e900; | ||||
| 			color: #192320; | ||||
| 			border: none; | ||||
| 			cursor: pointer; | ||||
| 			-webkit-tap-highlight-color: transparent; | ||||
| 		} | ||||
|  | ||||
| 		button:hover { | ||||
| 			background-color: #c6ff03; | ||||
| 		}`); | ||||
| 	} | ||||
| })(); | ||||
| @@ -32,18 +32,6 @@ | ||||
| 		renderError('FORCED_ERROR', 'This error is forced by having forceError in local storage.') | ||||
| 	} | ||||
|  | ||||
| 	const isEmbedPage = document.documentElement.classList.contains('embed'); | ||||
|  | ||||
| 	if (isEmbedPage) { | ||||
| 		const params = new URLSearchParams(location.search); | ||||
| 		if (params.has('rounded') && params.get('rounded') === 'false') { | ||||
| 			document.documentElement.classList.add('norounded'); | ||||
| 		} | ||||
| 		if (params.has('border') && params.get('border') === 'false') { | ||||
| 			document.documentElement.classList.add('noborder'); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//#region Detect language & fetch translations | ||||
| 	if (!localStorage.hasOwnProperty('locale')) { | ||||
| 		const supportedLangs = LANGS; | ||||
| @@ -116,51 +104,49 @@ | ||||
| 	} | ||||
| 	//#endregion | ||||
|  | ||||
| 	if (!isEmbedPage) { | ||||
| 		//#region Theme | ||||
| 		const theme = localStorage.getItem('theme'); | ||||
| 		if (theme) { | ||||
| 			for (const [k, v] of Object.entries(JSON.parse(theme))) { | ||||
| 				document.documentElement.style.setProperty(`--${k}`, v.toString()); | ||||
| 	//#region Theme | ||||
| 	const theme = localStorage.getItem('theme'); | ||||
| 	if (theme) { | ||||
| 		for (const [k, v] of Object.entries(JSON.parse(theme))) { | ||||
| 			document.documentElement.style.setProperty(`--${k}`, v.toString()); | ||||
|  | ||||
| 				// HTMLの theme-color 適用 | ||||
| 				if (k === 'htmlThemeColor') { | ||||
| 					for (const tag of document.head.children) { | ||||
| 						if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') { | ||||
| 							tag.setAttribute('content', v); | ||||
| 							break; | ||||
| 						} | ||||
| 			// HTMLの theme-color 適用 | ||||
| 			if (k === 'htmlThemeColor') { | ||||
| 				for (const tag of document.head.children) { | ||||
| 					if (tag.tagName === 'META' && tag.getAttribute('name') === 'theme-color') { | ||||
| 						tag.setAttribute('content', v); | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		const colorScheme = localStorage.getItem('colorScheme'); | ||||
| 		if (colorScheme) { | ||||
| 			document.documentElement.style.setProperty('color-scheme', colorScheme); | ||||
| 		} | ||||
| 		//#endregion | ||||
| 	} | ||||
| 	const colorScheme = localStorage.getItem('colorScheme'); | ||||
| 	if (colorScheme) { | ||||
| 		document.documentElement.style.setProperty('color-scheme', colorScheme); | ||||
| 	} | ||||
| 	//#endregion | ||||
|  | ||||
| 		const fontSize = localStorage.getItem('fontSize'); | ||||
| 		if (fontSize) { | ||||
| 			document.documentElement.classList.add('f-' + fontSize); | ||||
| 		} | ||||
| 	const fontSize = localStorage.getItem('fontSize'); | ||||
| 	if (fontSize) { | ||||
| 		document.documentElement.classList.add('f-' + fontSize); | ||||
| 	} | ||||
|  | ||||
| 		const useSystemFont = localStorage.getItem('useSystemFont'); | ||||
| 		if (useSystemFont) { | ||||
| 			document.documentElement.classList.add('useSystemFont'); | ||||
| 		} | ||||
| 	const useSystemFont = localStorage.getItem('useSystemFont'); | ||||
| 	if (useSystemFont) { | ||||
| 		document.documentElement.classList.add('useSystemFont'); | ||||
| 	} | ||||
|  | ||||
| 		const wallpaper = localStorage.getItem('wallpaper'); | ||||
| 		if (wallpaper) { | ||||
| 			document.documentElement.style.backgroundImage = `url(${wallpaper})`; | ||||
| 		} | ||||
| 	const wallpaper = localStorage.getItem('wallpaper'); | ||||
| 	if (wallpaper) { | ||||
| 		document.documentElement.style.backgroundImage = `url(${wallpaper})`; | ||||
| 	} | ||||
|  | ||||
| 		const customCss = localStorage.getItem('customCss'); | ||||
| 		if (customCss && customCss.length > 0) { | ||||
| 			const style = document.createElement('style'); | ||||
| 			style.innerHTML = customCss; | ||||
| 			document.head.appendChild(style); | ||||
| 		} | ||||
| 	const customCss = localStorage.getItem('customCss'); | ||||
| 	if (customCss && customCss.length > 0) { | ||||
| 		const style = document.createElement('style'); | ||||
| 		style.innerHTML = customCss; | ||||
| 		document.head.appendChild(style); | ||||
| 	} | ||||
|  | ||||
| 	async function addStyle(styleText) { | ||||
| @@ -188,7 +174,7 @@ | ||||
| 			<p>Update your os and browser / ブラウザおよびOSを最新バージョンに更新する</p> | ||||
| 			<p>Disable an adblocker / アドブロッカーを無効にする</p> | ||||
| 	 		<p>(Tor Browser) Set dom.webaudio.enabled to true / dom.webaudio.enabledをtrueに設定する</p> | ||||
| 			<details class="hide-when-embed" style="color: #86b300;"> | ||||
| 			<details style="color: #86b300;"> | ||||
| 				<summary>Other options / その他のオプション</summary> | ||||
| 				<a href="/flush"> | ||||
| 					<button class="button-small"> | ||||
| @@ -242,10 +228,6 @@ | ||||
| 			text-align: center; | ||||
| 		} | ||||
|  | ||||
| 		html.embed .hide-when-embed { | ||||
| 			display: none; | ||||
| 		} | ||||
|  | ||||
| 		button { | ||||
| 			border-radius: 999px; | ||||
| 			padding: 0px 12px 0px 12px; | ||||
| @@ -332,6 +314,6 @@ | ||||
| 			#errorInfo { | ||||
| 				width: 50%; | ||||
| 			} | ||||
| 		`) | ||||
| 		}`) | ||||
| 	} | ||||
| })(); | ||||
|   | ||||
| @@ -74,8 +74,12 @@ html(class=embed && 'embed') | ||||
| 		script(type='application/json' id='misskey_meta' data-generated-at=now) | ||||
| 			!= metaJson | ||||
|  | ||||
| 		script | ||||
| 			include ../boot.js | ||||
| 		if embed | ||||
| 			script | ||||
| 				include ../boot.embed.js | ||||
| 		else | ||||
| 			script | ||||
| 				include ../boot.js | ||||
|  | ||||
| 	body | ||||
| 		noscript: p | ||||
|   | ||||
| @@ -57,7 +57,8 @@ async function buildBackendScript() { | ||||
|   await fs.mkdir('./packages/backend/built/server/web', { recursive: true }); | ||||
|  | ||||
|   for (const file of [ | ||||
|     './packages/backend/src/server/web/boot.js', | ||||
| 		'./packages/backend/src/server/web/boot.js', | ||||
| 		'./packages/backend/src/server/web/boot.embed.js', | ||||
|     './packages/backend/src/server/web/bios.js', | ||||
|     './packages/backend/src/server/web/cli.js' | ||||
|   ]) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 kakkokari-gtyih
					kakkokari-gtyih