(wip) ssr using pug
This commit is contained in:
parent
ae22b5b5da
commit
73d552814a
13
gulpfile.js
13
gulpfile.js
|
@ -36,7 +36,11 @@ gulp.task('copy:frontend:locales', cb => {
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('build:backend:script', () => {
|
gulp.task('build:backend:script', () => {
|
||||||
return gulp.src(['./packages/backend/src/server/web/boot.js', './packages/backend/src/server/web/bios.js', './packages/backend/src/server/web/cli.js'])
|
return gulp.src([
|
||||||
|
'./packages/backend/src/server/web/boot.js',
|
||||||
|
'./packages/backend/src/server/web/bios.js',
|
||||||
|
'./packages/backend/src/server/web/cli.js',
|
||||||
|
])
|
||||||
.pipe(replace('LANGS', JSON.stringify(Object.keys(locales))))
|
.pipe(replace('LANGS', JSON.stringify(Object.keys(locales))))
|
||||||
.pipe(terser({
|
.pipe(terser({
|
||||||
toplevel: true
|
toplevel: true
|
||||||
|
@ -45,7 +49,12 @@ gulp.task('build:backend:script', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('build:backend:style', () => {
|
gulp.task('build:backend:style', () => {
|
||||||
return gulp.src(['./packages/backend/src/server/web/style.css', './packages/backend/src/server/web/bios.css', './packages/backend/src/server/web/cli.css'])
|
return gulp.src([
|
||||||
|
'./packages/backend/src/server/web/style.css',
|
||||||
|
'./packages/backend/src/server/web/bios.css',
|
||||||
|
'./packages/backend/src/server/web/cli.css',
|
||||||
|
'./packages/backend/src/server/web/embed.css'
|
||||||
|
])
|
||||||
.pipe(cssnano({
|
.pipe(cssnano({
|
||||||
zindex: false
|
zindex: false
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -4,13 +4,14 @@
|
||||||
"codename": "nasubi",
|
"codename": "nasubi",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/misskey-dev/misskey.git"
|
"url": "https://github.com/kakkokari-gtyih/misskey.git"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@8.1.1",
|
"packageManager": "pnpm@8.1.1",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/frontend",
|
"packages/frontend",
|
||||||
"packages/backend",
|
"packages/backend",
|
||||||
"packages/sw"
|
"packages/sw",
|
||||||
|
"packages/misskey-js"
|
||||||
],
|
],
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -66,4 +67,4 @@
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@tensorflow/tfjs-core": "4.2.0"
|
"@tensorflow/tfjs-core": "4.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -103,6 +103,7 @@ export type Mixin = {
|
||||||
driveUrl: string;
|
driveUrl: string;
|
||||||
userAgent: string;
|
userAgent: string;
|
||||||
clientEntry: string;
|
clientEntry: string;
|
||||||
|
clientEmbedEntry: string;
|
||||||
clientManifestExists: boolean;
|
clientManifestExists: boolean;
|
||||||
mediaProxy: string;
|
mediaProxy: string;
|
||||||
externalMediaProxyEnabled: boolean;
|
externalMediaProxyEnabled: boolean;
|
||||||
|
@ -133,7 +134,10 @@ export function loadConfig() {
|
||||||
const clientManifestExists = fs.existsSync(_dirname + '/../../../built/_vite_/manifest.json');
|
const clientManifestExists = fs.existsSync(_dirname + '/../../../built/_vite_/manifest.json');
|
||||||
const clientManifest = clientManifestExists ?
|
const clientManifest = clientManifestExists ?
|
||||||
JSON.parse(fs.readFileSync(`${_dirname}/../../../built/_vite_/manifest.json`, 'utf-8'))
|
JSON.parse(fs.readFileSync(`${_dirname}/../../../built/_vite_/manifest.json`, 'utf-8'))
|
||||||
: { 'src/init.ts': { file: 'src/init.ts' } };
|
: {
|
||||||
|
'src/init.ts': { file: 'src/init.ts' },
|
||||||
|
'src/embed/init.ts': { file: 'src/embed/init.ts' },
|
||||||
|
};
|
||||||
const config = yaml.load(fs.readFileSync(path, 'utf-8')) as Source;
|
const config = yaml.load(fs.readFileSync(path, 'utf-8')) as Source;
|
||||||
|
|
||||||
const mixin = {} as Mixin;
|
const mixin = {} as Mixin;
|
||||||
|
@ -155,6 +159,7 @@ export function loadConfig() {
|
||||||
mixin.driveUrl = `${mixin.scheme}://${mixin.host}/files`;
|
mixin.driveUrl = `${mixin.scheme}://${mixin.host}/files`;
|
||||||
mixin.userAgent = `Misskey/${meta.version} (${config.url})`;
|
mixin.userAgent = `Misskey/${meta.version} (${config.url})`;
|
||||||
mixin.clientEntry = clientManifest['src/init.ts'];
|
mixin.clientEntry = clientManifest['src/init.ts'];
|
||||||
|
mixin.clientEmbedEntry = clientManifest['src/embed/init.ts'];
|
||||||
mixin.clientManifestExists = clientManifestExists;
|
mixin.clientManifestExists = clientManifestExists;
|
||||||
|
|
||||||
const externalMediaProxy = config.mediaProxy ?
|
const externalMediaProxy = config.mediaProxy ?
|
||||||
|
|
|
@ -344,6 +344,17 @@ export class ClientServerService {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const renderEmbed404 = async (reply: FastifyReply) => {
|
||||||
|
reply.status(404);
|
||||||
|
const meta = await this.metaService.fetch();
|
||||||
|
|
||||||
|
return await reply.view('embed/404', {
|
||||||
|
instanceName: meta.name ?? 'Misskey',
|
||||||
|
icon: meta.iconUrl,
|
||||||
|
url: this.config.url,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// URL preview endpoint
|
// URL preview endpoint
|
||||||
fastify.get<{ Querystring: { url: string; lang: string; } }>('/url', (request, reply) => this.urlPreviewService.handle(request, reply));
|
fastify.get<{ Querystring: { url: string; lang: string; } }>('/url', (request, reply) => this.urlPreviewService.handle(request, reply));
|
||||||
|
|
||||||
|
@ -469,13 +480,42 @@ export class ClientServerService {
|
||||||
summary: getNoteSummary(_note),
|
summary: getNoteSummary(_note),
|
||||||
instanceName: meta.name ?? 'Misskey',
|
instanceName: meta.name ?? 'Misskey',
|
||||||
icon: meta.iconUrl,
|
icon: meta.iconUrl,
|
||||||
themeColor: meta.themeColor,
|
themeColor: meta.themeColor
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return await renderBase(reply);
|
return await renderBase(reply);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Note Embed
|
||||||
|
fastify.get<{ Params: { note: string; } }>('/notes/:note/embed', async (request, reply) => {
|
||||||
|
vary(reply.raw, 'Accept');
|
||||||
|
|
||||||
|
const note = await this.notesRepository.findOneBy({
|
||||||
|
id: request.params.note,
|
||||||
|
visibility: In(['public', 'home']),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (note) {
|
||||||
|
const _note = await this.noteEntityService.pack(note);
|
||||||
|
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: note.userId });
|
||||||
|
const meta = await this.metaService.fetch();
|
||||||
|
reply.header('Cache-Control', 'public, max-age=15');
|
||||||
|
return await reply.view('embed/note', {
|
||||||
|
note: _note,
|
||||||
|
profile,
|
||||||
|
avatarUrl: _note.user.avatarUrl,
|
||||||
|
// TODO: Let locale changeable by instance setting
|
||||||
|
summary: getNoteSummary(_note),
|
||||||
|
instanceName: meta.name ?? 'Misskey',
|
||||||
|
icon: meta.iconUrl,
|
||||||
|
themeColor: meta.themeColor,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return await renderEmbed404(reply);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Page
|
// Page
|
||||||
fastify.get<{ Params: { user: string; page: string; } }>('/@:user/pages/:page', async (request, reply) => {
|
fastify.get<{ Params: { user: string; page: string; } }>('/@:user/pages/:page', async (request, reply) => {
|
||||||
const { username, host } = Acct.parse(request.params.user);
|
const { username, host } = Acct.parse(request.params.user);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
html,body {
|
||||||
|
max-width: 650px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#splash {
|
||||||
|
max-width: 650px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
extends ./base
|
||||||
|
|
||||||
|
block style
|
||||||
|
style.
|
||||||
|
|
||||||
|
block content
|
||||||
|
div#error
|
||||||
|
div
|
||||||
|
div#instance-info
|
||||||
|
a.click-anime(href=url target='_blank')
|
||||||
|
img(src= icon || '/static-assets/splash.png')
|
||||||
|
span.sr-only(data-mi-i18n='aboutX' data-mi-i18n-ctx=`{"x": "${instanceName}"}`)
|
||||||
|
|
||||||
|
img.main(src='https://xn--931a.moe/assets/not-found.jpg')
|
||||||
|
h2(data-mi-i18n='notFound')
|
||||||
|
p(data-mi-i18n='notFoundDescription')
|
|
@ -0,0 +1,98 @@
|
||||||
|
block vars
|
||||||
|
|
||||||
|
block loadClientEntry
|
||||||
|
- const clientEntry = config.clientEmbedEntry;
|
||||||
|
|
||||||
|
doctype html
|
||||||
|
|
||||||
|
//
|
||||||
|
-
|
||||||
|
_____ _ _
|
||||||
|
| |_|___ ___| |_ ___ _ _
|
||||||
|
| | | | |_ -|_ -| '_| -_| | |
|
||||||
|
|_|_|_|_|___|___|_,_|___|_ |
|
||||||
|
|___|
|
||||||
|
Thank you for using Misskey!
|
||||||
|
If you are reading this message... how about joining the development?
|
||||||
|
https://github.com/misskey-dev/misskey
|
||||||
|
|
||||||
|
|
||||||
|
html
|
||||||
|
|
||||||
|
head
|
||||||
|
meta(charset='utf-8')
|
||||||
|
meta(name='application-name' content='Misskey')
|
||||||
|
meta(name='referrer' content='origin')
|
||||||
|
meta(name='theme-color' content= themeColor || '#86b300')
|
||||||
|
meta(name='theme-color-orig' content= themeColor || '#86b300')
|
||||||
|
meta(property='twitter:card' content='summary')
|
||||||
|
meta(property='og:site_name' content= instanceName || 'Misskey')
|
||||||
|
meta(name='viewport' content='width=device-width, initial-scale=1')
|
||||||
|
link(rel='icon' href= icon || '/favicon.ico')
|
||||||
|
link(rel='apple-touch-icon' href= icon || '/apple-touch-icon.png')
|
||||||
|
link(rel='manifest' href='/manifest.json')
|
||||||
|
link(rel='search' type='application/opensearchdescription+xml' title=(title || "Misskey") href=`${url}/opensearch.xml`)
|
||||||
|
link(rel='prefetch' href='https://xn--931a.moe/assets/info.jpg')
|
||||||
|
link(rel='prefetch' href='https://xn--931a.moe/assets/not-found.jpg')
|
||||||
|
link(rel='prefetch' href='https://xn--931a.moe/assets/error.jpg')
|
||||||
|
//- https://github.com/misskey-dev/misskey/issues/9842
|
||||||
|
link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v2.12.0')
|
||||||
|
link(rel='modulepreload' href=`/vite/${clientEntry.file}`)
|
||||||
|
|
||||||
|
if !config.clientManifestExists
|
||||||
|
script(type="module" src="/vite/@vite/client")
|
||||||
|
|
||||||
|
if Array.isArray(clientEntry.css)
|
||||||
|
each href in clientEntry.css
|
||||||
|
link(rel='stylesheet' href=`/vite/${href}`)
|
||||||
|
|
||||||
|
title
|
||||||
|
block title
|
||||||
|
= title || 'Misskey'
|
||||||
|
|
||||||
|
block desc
|
||||||
|
meta(name='description' content= desc || '✨🌎✨ A interplanetary communication platform ✨🚀✨')
|
||||||
|
|
||||||
|
block meta
|
||||||
|
|
||||||
|
block og
|
||||||
|
meta(property='og:title' content= title || 'Misskey')
|
||||||
|
meta(property='og:description' content= desc || '✨🌎✨ A interplanetary communication platform ✨🚀✨')
|
||||||
|
meta(property='og:image' content= img)
|
||||||
|
|
||||||
|
style
|
||||||
|
include ../../style.css
|
||||||
|
include ../../embed.css
|
||||||
|
|
||||||
|
block style
|
||||||
|
|
||||||
|
script.
|
||||||
|
var VERSION = "#{version}";
|
||||||
|
var CLIENT_ENTRY = "#{clientEntry.file}";
|
||||||
|
var EMBED = true;
|
||||||
|
|
||||||
|
script
|
||||||
|
include ../../boot.js
|
||||||
|
|
||||||
|
body
|
||||||
|
noscript: p
|
||||||
|
| JavaScriptを有効にしてください
|
||||||
|
br
|
||||||
|
| Please turn on your JavaScript
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
||||||
|
div#container
|
||||||
|
block content
|
|
@ -0,0 +1,53 @@
|
||||||
|
extends ./base
|
||||||
|
|
||||||
|
block vars
|
||||||
|
- const user = note.user;
|
||||||
|
- const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`;
|
||||||
|
- const url = `${config.url}/notes/${note.id}`;
|
||||||
|
- const isRenote = note.renote && note.text == null && note.fileIds.length == 0 && note.poll == null;
|
||||||
|
- const displayUser = isRenote ? note.renote.user: note.user;
|
||||||
|
|
||||||
|
block meta
|
||||||
|
if !user.host
|
||||||
|
link(rel='alternate' href=url type='application/activity+json')
|
||||||
|
if note.uri
|
||||||
|
link(rel='alternate' href=note.uri type='application/activity+json')
|
||||||
|
|
||||||
|
script(type='application/json') !{JSON.stringify(note)}
|
||||||
|
|
||||||
|
block content
|
||||||
|
div#note
|
||||||
|
|
||||||
|
header
|
||||||
|
div.wrapper
|
||||||
|
if isRenote
|
||||||
|
div#renote
|
||||||
|
a.avatar(href=`${config.url}/@${note.user.username}` target="_blank" rel="noopener noreferrer")
|
||||||
|
img(src=note.user.avatarUrl)
|
||||||
|
|
||||||
|
i.ti.ti-repeat
|
||||||
|
|
||||||
|
span(data-mi-i18n='renotedBy' data-mi-i18n-ctx=`{"user": "${note.user.name || note.user.username}"}`)
|
||||||
|
a(href=`${config.url}/@${note.user.username}` target="_blank" rel="noopener noreferrer")
|
||||||
|
b(data-mi-i18n-target='user')
|
||||||
|
|
||||||
|
div.author
|
||||||
|
a.avatar(href=`${config.url}/@${displayUser.username}` target="_blank" rel="noopener noreferrer")
|
||||||
|
img(src=displayUser.avatarUrl)
|
||||||
|
|
||||||
|
div.user-info
|
||||||
|
a.user-name(href=`${config.url}/@${displayUser.username}` target="_blank" rel="noopener noreferrer") #{displayUser.name || displayUser.username}
|
||||||
|
div.user-id @#{displayUser.username}
|
||||||
|
|
||||||
|
div#instance-info
|
||||||
|
a.click-anime(href=config.url target='_blank')
|
||||||
|
img(src= icon || '/static-assets/splash.png')
|
||||||
|
span.sr-only(data-mi-i18n='aboutX' data-mi-i18n-ctx=`{"x": "${instanceName}"}`)
|
||||||
|
|
||||||
|
main
|
||||||
|
div.mfm !{isRenote ? note.renote.text : note.text}
|
||||||
|
if (!isRenote && note.renote)
|
||||||
|
div#quote.mfm !{note.renote.text}
|
||||||
|
|
||||||
|
hr
|
||||||
|
pre(style='white-space: pre-wrap;') !{JSON.stringify(note, null, 2)}
|
|
@ -39,6 +39,7 @@
|
||||||
"eventemitter3": "5.0.0",
|
"eventemitter3": "5.0.0",
|
||||||
"gsap": "3.11.5",
|
"gsap": "3.11.5",
|
||||||
"idb-keyval": "6.2.0",
|
"idb-keyval": "6.2.0",
|
||||||
|
"iframe-resizer": "^4.3.6",
|
||||||
"insert-text-at-cursor": "0.3.0",
|
"insert-text-at-cursor": "0.3.0",
|
||||||
"is-file-animated": "1.0.2",
|
"is-file-animated": "1.0.2",
|
||||||
"json5": "2.2.3",
|
"json5": "2.2.3",
|
||||||
|
@ -97,6 +98,7 @@
|
||||||
"@types/estree": "1.0.0",
|
"@types/estree": "1.0.0",
|
||||||
"@types/gulp": "4.0.10",
|
"@types/gulp": "4.0.10",
|
||||||
"@types/gulp-rename": "2.0.1",
|
"@types/gulp-rename": "2.0.1",
|
||||||
|
"@types/iframe-resizer": "^3.5.9",
|
||||||
"@types/matter-js": "0.18.2",
|
"@types/matter-js": "0.18.2",
|
||||||
"@types/micromatch": "3.1.1",
|
"@types/micromatch": "3.1.1",
|
||||||
"@types/node": "18.15.11",
|
"@types/node": "18.15.11",
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}:where([hidden]:not([hidden='until-found'])){display:none!important}
|
||||||
|
|
||||||
|
html,body {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
padding: 1.5rem 2rem;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
border: 1px solid var(--divider);
|
||||||
|
background: var(--bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#instance-info img {
|
||||||
|
height: 2.5rem;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-emoji {
|
||||||
|
height: 2em;
|
||||||
|
width: auto;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: center;
|
||||||
|
transition: transform .2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#error {
|
||||||
|
padding: 0 0 3.5rem;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
#instance-info {
|
||||||
|
text-align: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.main {
|
||||||
|
max-width: 128px;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 16px;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#note {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
#renote {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: .5rem;
|
||||||
|
color: var(--renote);
|
||||||
|
|
||||||
|
>.avatar {
|
||||||
|
display: block;
|
||||||
|
margin-right: 1rem;
|
||||||
|
|
||||||
|
>img {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.author {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
>.avatar {
|
||||||
|
display: block;
|
||||||
|
margin-right: 1rem;
|
||||||
|
|
||||||
|
>img {
|
||||||
|
width: 54px;
|
||||||
|
height: 54px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>.user-info {
|
||||||
|
>.user-name {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#instance-info {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
font-size: 1.05rem;
|
||||||
|
|
||||||
|
#quote {
|
||||||
|
font-size: .95rem;
|
||||||
|
padding: .75rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
border: dashed 1px var(--renote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
import { miLocalStorage } from '@/local-storage';
|
||||||
|
import { version, lang, updateLocale } from '@/config';
|
||||||
|
import { updateI18n } from '@/i18n';
|
||||||
|
import { embedInitI18n } from './scripts/embed-i18n';
|
||||||
|
import '@/style.scss';
|
||||||
|
import './embed.scss';
|
||||||
|
import 'iframe-resizer/js/iframeResizer.contentWindow';
|
||||||
|
import { embedInitLinkAnime } from './scripts/link-anime';
|
||||||
|
import { parseMfm } from './scripts/parse-mfm';
|
||||||
|
|
||||||
|
console.info(`Misskey (Embed Sandbox) v${version}`);
|
||||||
|
|
||||||
|
if (_DEV_) {
|
||||||
|
console.warn('Development mode!!!');
|
||||||
|
|
||||||
|
window.addEventListener('error', event => {
|
||||||
|
console.error(event);
|
||||||
|
/*
|
||||||
|
alert({
|
||||||
|
type: 'error',
|
||||||
|
title: 'DEV: Unhandled error',
|
||||||
|
text: event.message
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('unhandledrejection', event => {
|
||||||
|
console.error(event);
|
||||||
|
/*
|
||||||
|
alert({
|
||||||
|
type: 'error',
|
||||||
|
title: 'DEV: Unhandled promise rejection',
|
||||||
|
text: event.reason
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//#region Detect language & fetch translations
|
||||||
|
const localeVersion = miLocalStorage.getItem('localeVersion');
|
||||||
|
const localeOutdated = (localeVersion == null || localeVersion !== version);
|
||||||
|
if (localeOutdated) {
|
||||||
|
const res = await window.fetch(`/assets/locales/${lang}.${version}.json`);
|
||||||
|
if (res.status === 200) {
|
||||||
|
const newLocale = await res.text();
|
||||||
|
const parsedNewLocale = JSON.parse(newLocale);
|
||||||
|
miLocalStorage.setItem('locale', newLocale);
|
||||||
|
miLocalStorage.setItem('localeVersion', version);
|
||||||
|
updateLocale(parsedNewLocale);
|
||||||
|
updateI18n(parsedNewLocale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
// タッチデバイスでCSSの:hoverを機能させる
|
||||||
|
document.addEventListener('touchend', () => {}, { passive: true });
|
||||||
|
|
||||||
|
//#region Set lang attr
|
||||||
|
const html = document.documentElement;
|
||||||
|
html.setAttribute('lang', lang);
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
embedInitI18n();
|
||||||
|
|
||||||
|
document.querySelectorAll(".mfm").forEach((e) => {
|
||||||
|
e.innerHTML = parseMfm(e.innerHTML).outerHTML;
|
||||||
|
});
|
||||||
|
|
||||||
|
//#region ロード画面解除
|
||||||
|
const splash = document.getElementById('splash');
|
||||||
|
// 念のためnullチェック(HTMLが古い場合があるため(そのうち消す))
|
||||||
|
if (splash) splash.addEventListener('transitionend', () => {
|
||||||
|
splash.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (splash) {
|
||||||
|
splash.style.opacity = '0';
|
||||||
|
splash.style.pointerEvents = 'none';
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
embedInitLinkAnime();
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { i18n } from "@/i18n";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 非vueページ向け翻訳適用関数
|
||||||
|
*
|
||||||
|
* キー指定例:
|
||||||
|
* ```html
|
||||||
|
* <span data-mi-i18n="翻訳key(必須)" data-mi-i18n-ctx=" *JSON Objectで動的な値を指定(任意)* "></span>
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export function embedInitI18n() {
|
||||||
|
const els: NodeListOf<HTMLElement> = document.querySelectorAll("[data-mi-i18n]");
|
||||||
|
els.forEach((tag: HTMLElement) => {
|
||||||
|
const key: string[] | null = tag.dataset.miI18n?.split('.') || null;
|
||||||
|
const translationContext: Record<string, string | number> | null = JSON.parse(tag.dataset.miI18nCtx ?? 'null');
|
||||||
|
if (!key) {
|
||||||
|
console.warn("[i18n] Key doesn't exist!", tag);
|
||||||
|
} else if (translationContext) {
|
||||||
|
let hasTranslationTarget: boolean = false;
|
||||||
|
let output: string = key.reduce((o, i) => o[i], i18n.ts);
|
||||||
|
Object.keys(translationContext).forEach((item) => {
|
||||||
|
const templateTag: NodeListOf<HTMLElement> = tag.querySelectorAll(`[data-mi-i18n-target="${item}"]`);
|
||||||
|
if (templateTag.length > 0) {
|
||||||
|
hasTranslationTarget = true;
|
||||||
|
templateTag.forEach((target: HTMLElement) => {
|
||||||
|
target.innerText = translationContext[item].toString();
|
||||||
|
let parent: HTMLElement = target;
|
||||||
|
while (parent.parentElement != null && parent.parentElement !== tag) {
|
||||||
|
if (parent.parentElement != null) {
|
||||||
|
parent = parent.parentElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output = output.replace(new RegExp(`{\s*${item}\s*}`), parent.outerHTML);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!hasTranslationTarget) {
|
||||||
|
tag.innerText = i18n.t(key.join('.'), translationContext);
|
||||||
|
} else {
|
||||||
|
tag.innerHTML = output;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tag.innerText = key.reduce((o, i) => o[i], i18n.ts);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
export function embedInitLinkAnime() {
|
||||||
|
const animeEl: NodeListOf<HTMLElement> = document.querySelectorAll("a.click-anime,button.click-anime");
|
||||||
|
if (animeEl.length > 0) {
|
||||||
|
animeEl.forEach((el: HTMLElement) => {
|
||||||
|
const target = el.children[0];
|
||||||
|
|
||||||
|
if (target == null) return;
|
||||||
|
|
||||||
|
target.classList.add('_anime_bounce_standBy');
|
||||||
|
|
||||||
|
el.addEventListener('mousedown', () => {
|
||||||
|
target.classList.remove('_anime_bounce');
|
||||||
|
|
||||||
|
target.classList.add('_anime_bounce_standBy');
|
||||||
|
target.classList.add('_anime_bounce_ready');
|
||||||
|
|
||||||
|
target.addEventListener('mouseleave', () => {
|
||||||
|
target.classList.remove('_anime_bounce_ready');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
el.addEventListener('click', () => {
|
||||||
|
target.classList.add('_anime_bounce');
|
||||||
|
target.classList.remove('_anime_bounce_ready');
|
||||||
|
});
|
||||||
|
|
||||||
|
el.addEventListener('animationend', () => {
|
||||||
|
target.classList.remove('_anime_bounce');
|
||||||
|
target.classList.add('_anime_bounce_standBy');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,329 @@
|
||||||
|
import * as mfm from 'mfm-js';
|
||||||
|
import { toUnicode } from 'punycode';
|
||||||
|
import { host as localHost } from '@/config';
|
||||||
|
|
||||||
|
const QUOTE_STYLE = `
|
||||||
|
display: block;
|
||||||
|
margin: 8px;
|
||||||
|
padding: 6px 0 6px 12px;
|
||||||
|
color: var(--fg);
|
||||||
|
border-left: solid 3px var(--fg);
|
||||||
|
opacity: 0.7;
|
||||||
|
`.split('\n').join(' ');
|
||||||
|
|
||||||
|
interface MfmFn extends mfm.MfmFn {
|
||||||
|
props: {
|
||||||
|
name: string;
|
||||||
|
args: Record<string, any>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parseMfm(text: string): HTMLDivElement {
|
||||||
|
const ast = mfm.parse(text);
|
||||||
|
|
||||||
|
const el = document.createElement("div");
|
||||||
|
|
||||||
|
function genEl(ast: (MfmFn | mfm.MfmNode)[]) {
|
||||||
|
return ast.map((token: (MfmFn | mfm.MfmNode)) => {
|
||||||
|
switch (token.type) {
|
||||||
|
case 'text': {
|
||||||
|
const text = token.props.text.replace(/(\r\n|\n|\r)/g, '\n');
|
||||||
|
|
||||||
|
const res: HTMLElement[] = [];
|
||||||
|
for (const t of text.split('\n')) {
|
||||||
|
res.push(document.createElement('br'));
|
||||||
|
const el = document.createElement('span');
|
||||||
|
el.innerText = t;
|
||||||
|
res.push(el);
|
||||||
|
}
|
||||||
|
res.shift();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'bold': {
|
||||||
|
const el = document.createElement("b");
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
});
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'strike': {
|
||||||
|
const el = document.createElement("del");
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
});
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'italic': {
|
||||||
|
const el = document.createElement("i");
|
||||||
|
el.style.fontStyle = 'oblique';
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
});
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'fn': {
|
||||||
|
// TODO: CSSを文字列で組み立てていくと token.props.args.~~~ 経由でCSSインジェクションできるのでよしなにやる
|
||||||
|
let style;
|
||||||
|
switch (token.props.name) {
|
||||||
|
case 'flip': {
|
||||||
|
const transform =
|
||||||
|
(token.props.args.h && token.props.args.v) ? 'scale(-1, -1)' :
|
||||||
|
token.props.args.v ? 'scaleY(-1)' :
|
||||||
|
'scaleX(-1)';
|
||||||
|
style = `transform: ${transform};`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'x2': {
|
||||||
|
const el = document.createElement("span");
|
||||||
|
el.classList.add('mfm-x2');
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
})
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
case 'x3': {
|
||||||
|
const el = document.createElement("span");
|
||||||
|
el.classList.add('mfm-x3');
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
})
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
case 'x4': {
|
||||||
|
const el = document.createElement("span");
|
||||||
|
el.classList.add('mfm-x4');
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
})
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
case 'font': {
|
||||||
|
const family =
|
||||||
|
token.props.args.serif ? 'serif' :
|
||||||
|
token.props.args.monospace ? 'monospace' :
|
||||||
|
token.props.args.cursive ? 'cursive' :
|
||||||
|
token.props.args.fantasy ? 'fantasy' :
|
||||||
|
token.props.args.emoji ? 'emoji' :
|
||||||
|
token.props.args.math ? 'math' :
|
||||||
|
null;
|
||||||
|
|
||||||
|
if (family) style = `font-family: ${family};`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'blur': {
|
||||||
|
const el = document.createElement("span");
|
||||||
|
el.classList.add('_mfm_blur_');
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
})
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
case 'rotate': {
|
||||||
|
const degrees = parseFloat(token.props.args.deg ?? '90');
|
||||||
|
style = `transform: rotate(${degrees}deg); transform-origin: center center;`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'position': {
|
||||||
|
const x = parseFloat(token.props.args.x ?? '0');
|
||||||
|
const y = parseFloat(token.props.args.y ?? '0');
|
||||||
|
style = `transform: translateX(${x}em) translateY(${y}em);`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'scale': {
|
||||||
|
const x = Math.min(parseFloat(token.props.args.x ?? '1'), 5);
|
||||||
|
const y = Math.min(parseFloat(token.props.args.y ?? '1'), 5);
|
||||||
|
style = `transform: scale(${x}, ${y});`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'fg': {
|
||||||
|
let color = token.props.args.color;
|
||||||
|
if (!/^[0-9a-f]{3,6}$/i.test(color)) color = 'f00';
|
||||||
|
style = `color: #${color};`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'bg': {
|
||||||
|
let color = token.props.args.color;
|
||||||
|
if (!/^[0-9a-f]{3,6}$/i.test(color)) color = 'f00';
|
||||||
|
style = `background-color: #${color};`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (style == null) {
|
||||||
|
const el = document.createElement("span");
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
});
|
||||||
|
el.innerHTML = `$[${token.props.name} ${el.innerHTML}]`;
|
||||||
|
return [el];
|
||||||
|
} else {
|
||||||
|
const el = document.createElement("span");
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
});
|
||||||
|
el.setAttribute('style', `display: inline-block; ${style}`);
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'small': {
|
||||||
|
const el = document.createElement("small");
|
||||||
|
el.style.opacity = '.7';
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
});
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'center': {
|
||||||
|
const el = document.createElement("div");
|
||||||
|
el.style.textAlign = "center";
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
});
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'url': {
|
||||||
|
const el = document.createElement("a");
|
||||||
|
el.href = token.props.url;
|
||||||
|
el.target = '_blank';
|
||||||
|
el.rel = 'nofollow noopener';
|
||||||
|
|
||||||
|
el.innerText = token.props.url;
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'link': {
|
||||||
|
const el = document.createElement("a");
|
||||||
|
el.href = token.props.url;
|
||||||
|
el.target = '_blank';
|
||||||
|
el.rel = 'nofollow noopener';
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
});
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'mention': {
|
||||||
|
const el = document.createElement("a");
|
||||||
|
const canonical = token.props.host === localHost ? `@${token.props.username}` : `@${token.props.username}@${toUnicode(token.props.host ?? '')}`;
|
||||||
|
el.href = `/${canonical}`;
|
||||||
|
el.target = '_blank';
|
||||||
|
el.rel = 'nofollow noopener';
|
||||||
|
el.style.display = 'inline-block';
|
||||||
|
el.style.padding = '4px 8px 4px 4px';
|
||||||
|
el.style.borderRadius = '999px';
|
||||||
|
el.style.color = 'var(--mention)';
|
||||||
|
el.style.fontWeight = '700';
|
||||||
|
|
||||||
|
el.innerText = `@${canonical}`;
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'hashtag': {
|
||||||
|
const el = document.createElement("a");
|
||||||
|
el.href = `/tags/${encodeURIComponent(token.props.hashtag)}`;
|
||||||
|
el.target = '_blank';
|
||||||
|
el.rel = 'nofollow noopener';
|
||||||
|
el.style.color = 'var(--hashtag)';
|
||||||
|
|
||||||
|
el.innerText = `#${token.props.hashtag}`;
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'blockCode': {
|
||||||
|
const el = document.createElement('pre');
|
||||||
|
el.style.overflowX = 'scroll';
|
||||||
|
el.style.width = '100%';
|
||||||
|
const elc = document.createElement('code');
|
||||||
|
elc.innerText = token.props.code;
|
||||||
|
el.appendChild(elc);
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'inlineCode': {
|
||||||
|
const el = document.createElement('code');
|
||||||
|
el.innerText = token.props.code;
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'quote': {
|
||||||
|
const el = document.createElement('div');
|
||||||
|
el.setAttribute('style', QUOTE_STYLE);
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
});
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'emojiCode': {
|
||||||
|
const el = document.createElement('span');
|
||||||
|
el.classList.add('custom-emoji', 'needs-replacing');
|
||||||
|
el.innerText = `:${token.props.name}:`;
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'unicodeEmoji': {
|
||||||
|
const el = document.createElement('span');
|
||||||
|
el.classList.add('emoji');
|
||||||
|
el.innerText = token.props.emoji;
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'mathInline': {
|
||||||
|
const el = document.createElement('code');
|
||||||
|
el.innerText = token.props.formula;
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'mathBlock': {
|
||||||
|
const el = document.createElement('code');
|
||||||
|
el.innerText = token.props.formula;
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
case 'search': {
|
||||||
|
const el = document.createElement('form');
|
||||||
|
el.action = 'https://www.google.com/search';
|
||||||
|
el.method = 'GET';
|
||||||
|
|
||||||
|
const text = document.createElement('input');
|
||||||
|
text.type = 'search';
|
||||||
|
text.value = token.props.query;
|
||||||
|
el.appendChild(text);
|
||||||
|
|
||||||
|
const submit = document.createElement('button');
|
||||||
|
submit.type = 'submit';
|
||||||
|
submit.innerHTML = '<i class="ti ti-search"></i><span data-mi-i18n-';
|
||||||
|
el.appendChild(submit);
|
||||||
|
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'plain': {
|
||||||
|
const el = document.createElement('span');
|
||||||
|
genEl(token.children).forEach((e) => {
|
||||||
|
el.appendChild(e as HTMLElement);
|
||||||
|
});
|
||||||
|
return [el];
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
console.error('unrecognized ast type:', (token as any).type);
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).flat(Infinity);
|
||||||
|
}
|
||||||
|
|
||||||
|
genEl(ast).forEach((element) => {
|
||||||
|
el.appendChild(element as HTMLElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
return el;
|
||||||
|
}
|
|
@ -43,7 +43,7 @@
|
||||||
".eslintrc.js",
|
".eslintrc.js",
|
||||||
"./**/*.ts",
|
"./**/*.ts",
|
||||||
"./**/*.vue"
|
"./**/*.vue"
|
||||||
],
|
, "src/embed/scripts/parse-mfm.ts" ],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
".storybook/**/*",
|
".storybook/**/*",
|
||||||
]
|
]
|
||||||
|
|
|
@ -100,6 +100,7 @@ export function getConfig(): UserConfig {
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
input: {
|
input: {
|
||||||
app: './src/init.ts',
|
app: './src/init.ts',
|
||||||
|
embed: './src/embed/init.ts'
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
manualChunks: {
|
manualChunks: {
|
||||||
|
|
|
@ -663,6 +663,9 @@ importers:
|
||||||
idb-keyval:
|
idb-keyval:
|
||||||
specifier: 6.2.0
|
specifier: 6.2.0
|
||||||
version: 6.2.0
|
version: 6.2.0
|
||||||
|
iframe-resizer:
|
||||||
|
specifier: ^4.3.6
|
||||||
|
version: 4.3.6
|
||||||
insert-text-at-cursor:
|
insert-text-at-cursor:
|
||||||
specifier: 0.3.0
|
specifier: 0.3.0
|
||||||
version: 0.3.0
|
version: 0.3.0
|
||||||
|
@ -832,6 +835,9 @@ importers:
|
||||||
'@types/gulp-rename':
|
'@types/gulp-rename':
|
||||||
specifier: 2.0.1
|
specifier: 2.0.1
|
||||||
version: 2.0.1
|
version: 2.0.1
|
||||||
|
'@types/iframe-resizer':
|
||||||
|
specifier: ^3.5.9
|
||||||
|
version: 3.5.9
|
||||||
'@types/matter-js':
|
'@types/matter-js':
|
||||||
specifier: 0.18.2
|
specifier: 0.18.2
|
||||||
version: 0.18.2
|
version: 0.18.2
|
||||||
|
@ -6593,6 +6599,10 @@ packages:
|
||||||
/@types/http-cache-semantics@4.0.1:
|
/@types/http-cache-semantics@4.0.1:
|
||||||
resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==}
|
resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==}
|
||||||
|
|
||||||
|
/@types/iframe-resizer@3.5.9:
|
||||||
|
resolution: {integrity: sha512-RQUBI75F+uXruB95BFpC/8V8lPgJg4MQ6HxOCtAZYBB/h0FNCfrFfb4I+u2pZJIV7sKeszZbFqy1UnGeBMrvsA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/ioredis@4.28.10:
|
/@types/ioredis@4.28.10:
|
||||||
resolution: {integrity: sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==}
|
resolution: {integrity: sha512-69LyhUgrXdgcNDv7ogs1qXZomnfOEnSmrmMFqKgt1XMJxmoOSG/u3wYy13yACIfKuMJ8IhKgHafDO3sx19zVQQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -12526,6 +12536,11 @@ packages:
|
||||||
/ieee754@1.2.1:
|
/ieee754@1.2.1:
|
||||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||||
|
|
||||||
|
/iframe-resizer@4.3.6:
|
||||||
|
resolution: {integrity: sha512-wz0WodRIF6eP0oGQa5NIP1yrITAZ59ZJvVaVJqJRjaeCtfm461vy2C3us6CKx0e7pooqpIGLpVMSTzrfAjX9Sg==}
|
||||||
|
engines: {node: '>=0.8.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/ignore@5.2.4:
|
/ignore@5.2.4:
|
||||||
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
|
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
|
|
Loading…
Reference in New Issue