fix code highlighting on CSP
All checks were successful
Lint / pnpm_install (push) Successful in 2m10s
Publish Docker image / Build (push) Successful in 4m52s
Test (production install and build) / production (20.16.0) (push) Successful in 1m24s
Lint / lint (backend) (push) Successful in 2m26s
Test (backend) / unit (20.16.0) (push) Successful in 9m4s
Lint / lint (frontend) (push) Successful in 2m40s
Lint / lint (frontend-embed) (push) Successful in 2m33s
Lint / lint (frontend-shared) (push) Successful in 2m23s
Lint / lint (misskey-bubble-game) (push) Successful in 2m42s
Test (backend) / e2e (20.16.0) (push) Successful in 12m34s
Lint / lint (misskey-js) (push) Successful in 2m23s
Lint / lint (misskey-reversi) (push) Successful in 2m38s
Lint / lint (sw) (push) Successful in 2m38s
Lint / typecheck (misskey-js) (push) Successful in 1m42s
Lint / typecheck (backend) (push) Successful in 2m41s
Lint / typecheck (sw) (push) Successful in 1m57s

Signed-off-by: eternal-flame-AD <yume@yumechi.jp>
This commit is contained in:
ゆめ 2024-11-11 13:42:09 -06:00
parent b802512469
commit b291a8b5fc
No known key found for this signature in database
7 changed files with 47 additions and 25 deletions

View file

@ -244,7 +244,8 @@ export function loadConfig(): Config {
'.prelude.js', hashResource(htmlScriptPrelude)
],
...['boot.js', 'style.css', 'style.embed.css', 'boot.embed.js',
'bios.css', 'bios.js', 'cli.css', 'cli.js', 'error.css'
'bios.css', 'bios.js', 'cli.css', 'cli.js', 'error.css',
'spinner-bg.svg', 'spinner-fg.svg',
].map((file) => [file, hashSourceFile(`${_dirname}/server/web/${file}`)] as [string, CSPHashed]),
]);

View file

@ -21,14 +21,26 @@ export function generateCSP(hashedMap: Map<string, CSPHashed>, options: {
const styles = keys
.filter(name => name.endsWith('.css'))
.map(name => `'${hashedMap.get(name)!.integrity}'`);
const images = keys
.filter(name =>
name.endsWith('.png') || name.endsWith('.jpg') ||
name.endsWith('.jpeg') ||
name.endsWith('.gif') ||
name.endsWith('.svg') ||
name.endsWith('.webp'))
.map(name => `'${hashedMap.get(name)!.integrity}'`);
return ([
['default-src', ['\'self\'']],
['img-src', ['\'self\'', 'data:', options.mediaProxy].filter(Boolean)],
['img-src', [
'\'self\'', 'data:',
...images,
options.mediaProxy
].filter(Boolean)],
['media-src', ['\'self\'', 'data:', options.mediaProxy].filter(Boolean)],
['font-src', ['\'self\'']],
['style-src', ['\'self\'', ...styles]],
['script-src', ['\'self\'', '\'wasm-unsafe-eval\'', ...scripts]],
['script-src', ['\'self\'', ...scripts]],
['object-src', ['\'none\'']],
['frame-src', ['\'none\'']],
['base-uri', ['\'self\'']],

View file

@ -0,0 +1,3 @@
<g transform="matrix(1,0,0,1,12,12)">
<circle cx="64" cy="64" r="64" style="fill:none;stroke:currentColor;stroke-width:24px;"/>
</g>

View file

@ -0,0 +1,3 @@
<g transform="matrix(1,0,0,1,12,12)">
<path d="M128,64C128,28.654 99.346,0 64,0C99.346,0 128,28.654 128,64Z" style="fill:none;stroke:currentColor;stroke-width:24px;"/>
</g>

View file

@ -2,6 +2,8 @@ block vars
block loadClientEntry
- const entry = config.frontendEntry
- const spinnerFG = config.cspPrerenderedContent['spinner-fg.svg']
- const spinnerBG = config.cspPrerenderedContent['spinner-bg.svg']
- const styleCSS = config.cspPrerenderedContent['style.embed.css']
- const bootJS = config.cspPrerenderedContent['boot.embed.js']
- const jsPrelude = config.cspPrerenderedContent['baseHtmlJSPrelude']
@ -58,14 +60,6 @@ html(class='embed')
div#splash
img#splashIcon(src= icon || '/static-assets/splash.png')
div#splashSpinner
<svg class="spinner bg" viewBox="0 0 152 152" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1,0,0,1,12,12)">
<circle cx="64" cy="64" r="64" style="fill:none;stroke:currentColor;stroke-width:24px;"/>
</g>
</svg>
<svg class="spinner fg" viewBox="0 0 152 152" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1,0,0,1,12,12)">
<path d="M128,64C128,28.654 99.346,0 64,0C99.346,0 128,28.654 128,64Z" style="fill:none;stroke:currentColor;stroke-width:24px;"/>
</g>
</svg>
svg(integrity=spinnerBG.integrity) !{spinnerBG.content}
svg(integrity=spinnerFG.integrity) !{spinnerFG.content}
block content

View file

@ -2,6 +2,8 @@ block vars
block loadClientEntry
- const entry = config.frontendEntry;
- const spinnerFG = config.cspPrerenderedContent.get('spinner-fg.svg')
- const spinnerBG = config.cspPrerenderedContent.get('spinner-bg.svg')
- const styleCSS = config.cspPrerenderedContent.get('style.css');
- const jsPrelude = config.cspPrerenderedContent.get('.prelude.js');
- const bootJS = config.cspPrerenderedContent.get('boot.js');
@ -83,14 +85,6 @@ html
div#splash
img#splashIcon(src= icon || '/static-assets/splash.png')
div#splashSpinner
<svg class="spinner bg" viewBox="0 0 152 152" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1,0,0,1,12,12)">
<circle cx="64" cy="64" r="64" style="fill:none;stroke:currentColor;stroke-width:24px;"/>
</g>
</svg>
<svg class="spinner fg" viewBox="0 0 152 152" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(1,0,0,1,12,12)">
<path d="M128,64C128,28.654 99.346,0 64,0C99.346,0 128,28.654 128,64Z" style="fill:none;stroke:currentColor;stroke-width:24px;"/>
</g>
</svg>
svg(integrity=spinnerBG.integrity) !{spinnerBG.content}
svg(integrity=spinnerFG.integrity) !{spinnerFG.content}
block content

View file

@ -3,7 +3,8 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { createHighlighterCore, loadWasm } from 'shiki/core';
import { createHighlighterCore } from 'shiki/core';
import { createOnigurumaEngine } from 'shiki/engine/oniguruma';
import darkPlus from 'shiki/themes/dark-plus.mjs';
import { bundledThemesInfo } from 'shiki/themes';
import { bundledLanguagesInfo } from 'shiki/langs';
@ -60,7 +61,8 @@ export async function getHighlighter(): Promise<HighlighterCore> {
}
async function initHighlighter() {
await loadWasm(import('shiki/onig.wasm?init'));
// https://vite.dev/guide/features#accessing-the-webassembly-module
const wasmUrl = import('shiki/onig.wasm?url') as unknown as string;
// テーマの重複を消す
const themes = unique([
@ -71,6 +73,19 @@ async function initHighlighter() {
const jsLangInfo = bundledLanguagesInfo.find(t => t.id === 'javascript');
const highlighter = await createHighlighterCore({
themes,
engine: createOnigurumaEngine({
instantiator: async () => {
const resp = await fetch(wasmUrl);
if (!resp.ok) {
throw new Error(`Failed to fetch WASM file: ${resp.status} ${resp.statusText}`);
}
if (!resp.headers.get('content-type')?.startsWith('application/wasm')) {
throw new Error(`Invalid content type: ${resp.headers.get('content-type')}`);
}
const module = await WebAssembly.compileStreaming(resp);
return await WebAssembly.instantiate(module);
}
}),
langs: [
...(jsLangInfo ? [async () => await jsLangInfo.import()] : []),
async () => (await import('aiscript-vscode/aiscript/syntaxes/aiscript.tmLanguage.json')).default as unknown as LanguageRegistration,