inline globals

This commit is contained in:
Pig Fang 2023-02-05 11:26:21 +08:00
parent 7aee47ae0e
commit d8c71c616b
No known key found for this signature in database
GPG Key ID: A8198F548DADA9E2
15 changed files with 167 additions and 77 deletions

View File

@ -2,12 +2,12 @@
"preset": "ts-jest", "preset": "ts-jest",
"resetMocks": true, "resetMocks": true,
"timers": "modern", "timers": "modern",
"moduleNameMapper": {
"blessing-skin": "<rootDir>/types.ts"
},
"transform": { "transform": {
"^.+\\.svelte$": "@gplane/svelte-jest", "^.+\\.svelte$": "@gplane/svelte-jest",
"^.+\\.tsx?$": "ts-jest" "^.+\\.tsx?$": "ts-jest"
}, },
"setupFilesAfterEnv": ["@testing-library/jest-dom/extend-expect"] "setupFilesAfterEnv": [
"@testing-library/jest-dom/extend-expect",
"<rootDir>/setup-test.ts"
]
} }

View File

@ -1,6 +1,5 @@
import hljs from 'highlight.js/lib/core' import hljs from 'highlight.js/lib/core'
import json from 'highlight.js/lib/languages/json' import json from 'highlight.js/lib/languages/json'
import { site_name, base_url } from 'blessing-skin'
hljs.registerLanguage('json', json) hljs.registerLanguage('json', json)
@ -10,14 +9,14 @@ document
.querySelector('#download-extra-list') .querySelector('#download-extra-list')
?.addEventListener('click', () => { ?.addEventListener('click', () => {
const content = JSON.stringify({ const content = JSON.stringify({
name: site_name, name: globalThis.blessing.site_name,
type: 'CustomSkinAPI', type: 'CustomSkinAPI',
root: `${base_url}/csl/`, root: `${globalThis.blessing.base_url}/csl/`,
}) })
const a = document.createElement('a') const a = document.createElement('a')
const blob = new Blob([content], { type: 'application/json' }) const blob = new Blob([content], { type: 'application/json' })
a.download = `${site_name}.json` a.download = `${globalThis.blessing.site_name}.json`
a.href = URL.createObjectURL(blob) a.href = URL.createObjectURL(blob)
a.click() a.click()
a.remove() a.remove()

View File

@ -1,9 +1,7 @@
import { base_url, t } from 'blessing-skin'
const button = document.querySelector<HTMLAnchorElement>('.main-button') const button = document.querySelector<HTMLAnchorElement>('.main-button')
if (button && button.href.endsWith('/auth/register')) { if (button && button.href.endsWith('/auth/register')) {
button.textContent = t('auth.login') button.textContent = globalThis.blessing.t('auth.login')
const url = new URL(base_url) const url = new URL(globalThis.blessing.base_url)
url.pathname = '/auth/login' url.pathname = '/auth/login'
button.href = url.toString() button.href = url.toString()
} }

View File

@ -1,10 +1,7 @@
import { fetch, notify } from 'blessing-skin'
document.querySelector('#update-uuid')?.addEventListener('click', async () => { document.querySelector('#update-uuid')?.addEventListener('click', async () => {
const { code, message }: { code: null; message: string } = await fetch.post( const { code, message }: { code: null; message: string } =
'/mojang/update-uuid', await globalThis.blessing.fetch.post('/mojang/update-uuid')
) const { toast } = globalThis.blessing.notify
const { toast } = notify
if (code === 0) { if (code === 0) {
toast.success(message) toast.success(message)
} else { } else {

View File

@ -1,9 +1,10 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte' import { onMount } from 'svelte'
import { nanoid } from 'nanoid' import { nanoid } from 'nanoid'
import { fetch, t, notify } from 'blessing-skin'
import DomainsList from './DomainsList.svelte' import DomainsList from './DomainsList.svelte'
const { fetch, t, notify } = globalThis.blessing
type Item = { id: string; value: string } type Item = { id: string; value: string }
let isLoading = true let isLoading = true
@ -13,12 +14,8 @@
let isDenyListDirty = false let isDenyListDirty = false
onMount(async () => { onMount(async () => {
const { const { allow, deny }: { allow: string[]; deny: string[] } =
allow, await fetch.get('/admin/restricted-email-domains')
deny,
}: { allow: string[]; deny: string[] } = await fetch.get(
'/admin/restricted-email-domains',
)
allowList = allow.map((value) => ({ id: nanoid(), value })) allowList = allow.map((value) => ({ id: nanoid(), value }))
denyList = deny.map((value) => ({ id: nanoid(), value })) denyList = deny.map((value) => ({ id: nanoid(), value }))
isLoading = false isLoading = false
@ -80,7 +77,8 @@
on:edit={() => (isAllowListDirty = true)} on:edit={() => (isAllowListDirty = true)}
on:add={createAllowItem} on:add={createAllowItem}
on:remove={(event) => removeAllowItem(event.detail)} on:remove={(event) => removeAllowItem(event.detail)}
on:save={saveAllowList} /> on:save={saveAllowList}
/>
</div> </div>
<div class="col-lg-6"> <div class="col-lg-6">
<DomainsList <DomainsList
@ -92,6 +90,7 @@
on:edit={() => (isDenyListDirty = true)} on:edit={() => (isDenyListDirty = true)}
on:add={createDenyItem} on:add={createDenyItem}
on:remove={(event) => removeDenyItem(event.detail)} on:remove={(event) => removeDenyItem(event.detail)}
on:save={saveDenyList} /> on:save={saveDenyList}
/>
</div> </div>
</div> </div>

View File

@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import { t } from 'blessing-skin'
const { t } = globalThis.blessing
type Item = { id: string; value: string } type Item = { id: string; value: string }
@ -37,11 +38,13 @@
type="text" type="text"
class="form-control" class="form-control"
bind:value={item.value} bind:value={item.value}
on:input={() => dispath('edit')} /> on:input={() => dispath('edit')}
/>
<div class="input-group-append"> <div class="input-group-append">
<button <button
class="btn btn-secondary" class="btn btn-secondary"
on:click={() => dispath('remove', item.id)}> on:click={() => dispath('remove', item.id)}
>
<i class="fas fa-trash" /> <i class="fas fa-trash" />
</button> </button>
</div> </div>

View File

@ -1,14 +1,15 @@
import { event } from 'blessing-skin' globalThis.blessing.event.on(
'emailDomainsSuggestion',
(domains: Set<string>) => {
const allowListJSON = document.querySelector('#allowed-email-domains')
if (!allowListJSON) {
return
}
event.on('emailDomainsSuggestion', (domains: Set<string>) => { const allowList: string[] = JSON.parse(allowListJSON.textContent ?? '[]')
const allowListJSON = document.querySelector('#allowed-email-domains') if (allowList.length > 0) {
if (!allowListJSON) { domains.clear()
return allowList.forEach((domain) => domains.add(domain))
} }
},
const allowList: string[] = JSON.parse(allowListJSON.textContent ?? '[]') )
if (allowList.length > 0) {
domains.clear()
allowList.forEach((domain) => domains.add(domain))
}
})

View File

@ -1,6 +1,7 @@
import { event } from 'blessing-skin' globalThis.blessing.event.on(
'beforeFetch',
event.on('beforeFetch', (request: { data: Record<string, string> }) => { (request: { data: Record<string, string> }) => {
const search = new URLSearchParams(location.search) const search = new URLSearchParams(location.search)
request.data.share = search.get('share') || '' request.data.share = search.get('share') || ''
}) },
)

View File

@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte' import { onMount } from 'svelte'
import { fetch, t, notify } from 'blessing-skin'
const { fetch, t, notify } = globalThis.blessing
let description = '' let description = ''
let raw = '' let raw = ''
@ -51,23 +52,6 @@
} }
</script> </script>
<style>
description-content :global(h1),
description-content :global(h2) {
padding-bottom: 0.3rem;
border-bottom: 1px solid #eaecef;
}
description-content :global(blockquote) {
color: #aaa;
border-left: 0.3rem solid #aaa;
}
description-content :global(hr) {
border-top-width: 4px;
}
</style>
{#if canEdit || !isEmptyDescription} {#if canEdit || !isEmptyDescription}
<div class="card card-secondary"> <div class="card card-secondary">
<div class="card-header"> <div class="card-header">
@ -77,7 +61,8 @@
<button <button
class="btn btn-secondary btn-sm float-right" class="btn btn-secondary btn-sm float-right"
title={t('texture-description.edit')} title={t('texture-description.edit')}
on:click={editDescription}> on:click={editDescription}
>
<i class="fas fa-edit" /> <i class="fas fa-edit" />
</button> </button>
{/if} {/if}
@ -107,7 +92,8 @@
<button <button
class="btn btn-primary" class="btn btn-primary"
disabled={isSubmitting || isLengthExceeded} disabled={isSubmitting || isLengthExceeded}
on:click={submitDescription}> on:click={submitDescription}
>
{#if isSubmitting} {#if isSubmitting}
<span> <span>
<i class="fas fa-sync fa-spin" /> <i class="fas fa-sync fa-spin" />
@ -117,7 +103,8 @@
<button <button
class="btn btn-secondary" class="btn btn-secondary"
disabled={isSubmitting} disabled={isSubmitting}
on:click={() => (isEditing = false)}> on:click={() => (isEditing = false)}
>
{t('general.cancel')} {t('general.cancel')}
</button> </button>
</div> </div>
@ -125,3 +112,20 @@
{/if} {/if}
</div> </div>
{/if} {/if}
<style>
description-content :global(h1),
description-content :global(h2) {
padding-bottom: 0.3rem;
border-bottom: 1px solid #eaecef;
}
description-content :global(blockquote) {
color: #aaa;
border-left: 0.3rem solid #aaa;
}
description-content :global(hr) {
border-top-width: 4px;
}
</style>

View File

@ -1,8 +1,9 @@
import { render, fireEvent, waitFor } from '@testing-library/svelte' import { render, fireEvent, waitFor } from '@testing-library/svelte'
import { tick } from 'svelte' import { tick } from 'svelte'
import { fetch, t } from 'blessing-skin'
import Description from './Description.svelte' import Description from './Description.svelte'
const { fetch, t } = globalThis.blessing
test('render description', async () => { test('render description', async () => {
const spy = jest.spyOn(fetch, 'get').mockResolvedValue('<div id="md"></div>') const spy = jest.spyOn(fetch, 'get').mockResolvedValue('<div id="md"></div>')
render(Description, { props: { tid: 1 } }) render(Description, { props: { tid: 1 } })

View File

@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import { onMount, onDestroy } from 'svelte' import { onMount, onDestroy } from 'svelte'
import { event, t } from 'blessing-skin'
const { event, t } = globalThis.blessing
let description = '' let description = ''
export let maxLength = Infinity export let maxLength = Infinity
@ -18,7 +19,8 @@
id="description-editor" id="description-editor"
class="form-control" class="form-control"
rows="9" rows="9"
bind:value={description} /> bind:value={description}
/>
{#if description.length > maxLength} {#if description.length > maxLength}
<div class="alert alert-info mt-2"> <div class="alert alert-info mt-2">
{t('texture-description.exceeded', { max: maxLength })} {t('texture-description.exceeded', { max: maxLength })}

View File

@ -1,8 +1,9 @@
import { render, fireEvent } from '@testing-library/svelte' import { render, fireEvent } from '@testing-library/svelte'
import { tick } from 'svelte' import { tick } from 'svelte'
import { event, t } from 'blessing-skin'
import UploadEditor from './UploadEditor.svelte' import UploadEditor from './UploadEditor.svelte'
const { event, t } = globalThis.blessing
test('submit data', () => { test('submit data', () => {
const { getByLabelText } = render(UploadEditor) const { getByLabelText } = render(UploadEditor)
fireEvent.input(getByLabelText(t('texture-description.description')), { fireEvent.input(getByLabelText(t('texture-description.description')), {

View File

@ -1,7 +1,6 @@
import { event } from 'blessing-skin'
import UploadEditor from './UploadEditor.svelte' import UploadEditor from './UploadEditor.svelte'
event.on('mounted', () => { globalThis.blessing.event.on('mounted', () => {
const input = document.querySelector<HTMLInputElement>('#description-limit') const input = document.querySelector<HTMLInputElement>('#description-limit')
const maxLength = Number.parseInt(input?.value ?? '0') || Infinity const maxLength = Number.parseInt(input?.value ?? '0') || Infinity

85
setup-test.ts Normal file
View File

@ -0,0 +1,85 @@
import { EventEmitter } from 'events'
class Toast {
success(message: string): void {
message
}
info(message: string): void {
message
}
warning(message: string): void {
message
}
error(message: string): void {
message
}
}
const base_url = '/'
const locale = 'en'
const site_name = 'Blessing Skin'
function t(key: string, params?: object): string {
const data = params ? `(${JSON.stringify(params)})` : ''
return key + data
}
const fetch = {
async get<T = any>(url: string, params?: Record<string, any>): Promise<T> {
url
params
return {} as T
},
async post<T = any>(url: string, data?: any): Promise<T> {
url
data
return {} as T
},
async put<T = any>(url: string, data?: any): Promise<T> {
url
data
return {} as T
},
async del<T = any>(url: string, data?: any): Promise<T> {
url
data
return {} as T
},
}
const emitter = new EventEmitter()
const event = {
on(
eventName: string | symbol,
listener: (...args: any[]) => any,
): () => void {
emitter.on(eventName, listener)
return () => {
emitter.off(eventName, listener)
}
},
emit(eventName: string | symbol, payload?: object): void {
emitter.emit(eventName, payload)
},
}
const notify = {
showModal(options?: object): Promise<{ value: string }> {
return Promise.resolve({ value: JSON.stringify(options) })
},
toast: new Toast(),
}
Object.assign(globalThis, {
blessing: {
base_url,
locale,
site_name,
t,
fetch,
event,
notify,
},
})

View File

@ -11,5 +11,5 @@
}, },
"types": ["svelte", "jest", "node", "@testing-library/jest-dom"] "types": ["svelte", "jest", "node", "@testing-library/jest-dom"]
}, },
"include": ["plugins/*/assets", "types.ts"] "include": ["plugins/*/assets", "types.ts", "globals.d.ts"]
} }