ref: format

This commit is contained in:
alikia2x (寒寒) 2024-09-21 21:31:08 +08:00
parent 35f90b42d9
commit d97e678206
Signed by: alikia2x
GPG Key ID: 56209E0CCD8420C6
72 changed files with 2240 additions and 2190 deletions

View File

@ -1,5 +1,5 @@
{
"useTabs": false,
"useTabs": true,
"tabWidth": 4,
"trailingComma": "none",
"singleQuote": false,

View File

@ -2,10 +2,10 @@ import { Express } from "express";
import { completeGoogle } from "search-engine-autocomplete";
export function configureBackendRoutes(app: Express) {
app.get('/api/v1/suggestion', async (req, res) => {
app.get("/api/v1/suggestion", async (req, res) => {
const query = req.query.q as string;
const t = parseInt(req.query.t as string || "0") || null;
let language = req.query.l as string || 'en-US';
const t = parseInt((req.query.t as string) || "0") || null;
let language = (req.query.l as string) || "en-US";
try {
const data = await completeGoogle(query, language);
@ -13,10 +13,10 @@ export function configureBackendRoutes(app: Express) {
res.json({ ...data, time: t });
} catch (error) {
//logger.error({ type: "onesearch_search_autocomplete_error", error: error.message });
res.status(500).json({ error: 'Internal Server Error' });
res.status(500).json({ error: "Internal Server Error" });
}
});
app.get("/api/v1/ping", async (_, res) => {
res.status(200).json({message: "pong"});
})
res.status(200).json({ message: "pong" });
});
}

BIN
bun.lockb

Binary file not shown.

View File

@ -11,9 +11,19 @@ export default function Background() {
return (
<div>
{darkMode ? (
<BackgroundContainer src="rgb(23,25,29)" isFocus={isFocus} onClick={() => setFocus(false)} darkMode={darkMode}/>
<BackgroundContainer
src="rgb(23,25,29)"
isFocus={isFocus}
onClick={() => setFocus(false)}
darkMode={darkMode}
/>
) : (
<BackgroundContainer src="white" isFocus={isFocus} onClick={() => setFocus(false)} darkMode={darkMode}/>
<BackgroundContainer
src="white"
isFocus={isFocus}
onClick={() => setFocus(false)}
darkMode={darkMode}
/>
)}
</div>
);

View File

@ -24,7 +24,11 @@ export default function BackgroundContainer(props: {
src={props.src}
className={
"w-full h-full fixed object-cover inset-0 duration-200 z-0 " +
(props.isFocus ? (settings.bgBlur ? "blur-lg scale-110" : "brightness-50 scale-105") : "")
(props.isFocus
? settings.bgBlur
? "blur-lg scale-110"
: "brightness-50 scale-105"
: "")
}
alt="background"
onClick={props.onClick}

View File

@ -6,16 +6,14 @@ import { WMOCodeTable } from "lib/weather/wmocode";
type UpdateSuggestionFunction = (data: suggestionItem[]) => void;
export function handleNLUResult(result: any, updateSuggestion: UpdateSuggestionFunction){
export function handleNLUResult(result: any, updateSuggestion: UpdateSuggestionFunction) {
if (result.intent == "weather.summary") {
getLocationNative((data: GeolocationCoordinates | GeolocationPositionError) => {
console.log(data);
if (data instanceof GeolocationCoordinates) {
getWeather(data.latitude, data.longitude).then((weather) => {
console.log(weather["hourly"]);
let hourIndex = findClosestDateIndex(
weather["hourly"]["time"]
);
let hourIndex = findClosestDateIndex(weather["hourly"]["time"]);
let temp = weather["hourly"]["apparent_temperature"][hourIndex];
let weatherCode = weather["hourly"]["weather_code"][hourIndex];
console.log(temp, weatherCode, hourIndex);

View File

@ -2,7 +2,11 @@ import { useAtomValue } from "jotai";
import search from "lib/search";
import { settingsAtom } from "lib/state/settings";
export default function PlainSearch(props: { children: React.ReactNode; query: string; selected: boolean }) {
export default function PlainSearch(props: {
children: React.ReactNode;
query: string;
selected: boolean;
}) {
const settings = useAtomValue(settingsAtom);
const engine = settings.searchEngines[settings.currentSearchEngine];
const newTab = settings.searchInNewTab;
@ -18,8 +22,7 @@ export default function PlainSearch(props: { children: React.ReactNode; query: s
{props.children}
</div>
);
}
else {
} else {
return (
<div
className={`relative w-full h-10 leading-10 bg-zinc-100 hover:bg-zinc-300

View File

@ -1,6 +1,8 @@
export default function Suggestion(props: { children: React.ReactNode }) {
return (
<div dangerouslySetInnerHTML={{ __html: `<p>${props.children}</p>` as string }} className={`relative w-full h-10 leading-10 bg-zinc-100 hover:bg-zinc-300 dark:bg-zinc-800 hover:dark:bg-zinc-700 px-5 z-10 cursor-pointer duration-100`}>
</div>
<div
dangerouslySetInnerHTML={{ __html: `<p>${props.children}</p>` as string }}
className={`relative w-full h-10 leading-10 bg-zinc-100 hover:bg-zinc-300 dark:bg-zinc-800 hover:dark:bg-zinc-700 px-5 z-10 cursor-pointer duration-100`}
></div>
);
}

View File

@ -142,7 +142,12 @@ const PickerList = React.forwardRef<HTMLDivElement, PickerListProps>((props, ref
const { selected, selectionOnChange, selectionItems, toggleDisplay } = props;
return createPortal(
<div className="absolute w-screen h-screen" onClick={()=>{toggleDisplay(false)}}>
<div
className="absolute w-screen h-screen"
onClick={() => {
toggleDisplay(false);
}}
>
<div
ref={ref}
className="overflow-y-auto fixed w-fit text-black dark:text-white opacity-0 duration-200

View File

@ -3,10 +3,10 @@ import { selectionType } from "./picker";
export type selectedOnChange = (target: selectionType) => void;
export default function SelectionItem(props: {key: selectionType, children: ReactNode, onChange: selectedOnChange}){
return (
<div onClick={() => props.onChange(props.key)}>
{props.children}
</div>
)
export default function SelectionItem(props: {
key: selectionType;
children: ReactNode;
onChange: selectedOnChange;
}) {
return <div onClick={() => props.onChange(props.key)}>{props.children}</div>;
}

View File

@ -2,9 +2,7 @@
import { useState, useEffect } from "react";
export default function Time(props: {
showSecond: boolean
}) {
export default function Time(props: { showSecond: boolean }) {
const [currentTime, setCurrentTime] = useState(new Date());
useEffect(() => {

48
global.d.ts vendored
View File

@ -1,31 +1,31 @@
import { Suggestion } from "search-engine-autocomplete";
interface settingsType extends object{
"version": number,
"elementBackdrop": boolean,
"bgBlur": boolean,
"timeShowSecond": boolean,
"currentSearchEngine": string,
"searchInNewTab": boolean,
"searchEngines": {
[key: string]: string
},
interface settingsType extends object {
version: number;
elementBackdrop: boolean;
bgBlur: boolean;
timeShowSecond: boolean;
currentSearchEngine: string;
searchInNewTab: boolean;
searchEngines: {
[key: string]: string;
};
}
interface suggestionsResponse extends object{
suggestions: Suggestion[],
query: string,
verbatimRelevance: number,
time: number
interface suggestionsResponse extends object {
suggestions: Suggestion[];
query: string;
verbatimRelevance: number;
time: number;
}
type suggestionItem = {
suggestion: string,
type: string,
relativeRelevance?: number,
relevance: number,
prompt?: string | React.ReactElement,
intention?: string | null,
probability?: number,
confidence?: number,
}
suggestion: string;
type: string;
relativeRelevance?: number;
relevance: number;
prompt?: string | React.ReactElement;
intention?: string | null;
probability?: number;
confidence?: number;
};

View File

@ -1,5 +1,5 @@
{
"search" : {
"placeholder" : "ابحث أو اكتب عنوان URL"
"search": {
"placeholder": "ابحث أو اكتب عنوان URL"
}
}

View File

@ -1,5 +1,5 @@
{
"search" : {
"placeholder" : "Suche oder gib eine URL ein"
"search": {
"placeholder": "Suche oder gib eine URL ein"
}
}

View File

@ -1,5 +1,5 @@
{
"search" : {
"placeholder" : "Buscar o escribir una URL"
"search": {
"placeholder": "Buscar o escribir una URL"
}
}

View File

@ -1,5 +1,5 @@
{
"search" : {
"placeholder" : "Rechercher ou saisir une URL"
"search": {
"placeholder": "Rechercher ou saisir une URL"
}
}

View File

@ -1,5 +1,5 @@
{
"search" : {
"placeholder" : "Cerca o digita un URL"
"search": {
"placeholder": "Cerca o digita un URL"
}
}

View File

@ -1,5 +1,5 @@
{
"search" : {
"placeholder" : "검색 또는 URL 입력"
"search": {
"placeholder": "검색 또는 URL 입력"
}
}

View File

@ -1,5 +1,5 @@
{
"search" : {
"placeholder" : "Pesquisar ou digitar uma URL"
"search": {
"placeholder": "Pesquisar ou digitar uma URL"
}
}

View File

@ -1,5 +1,5 @@
{
"search" : {
"placeholder" : "Искать или ввести URL"
"search": {
"placeholder": "Искать или ввести URL"
}
}

View File

@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />

View File

@ -1,4 +1,4 @@
export default function copyToClipboard(value: string){
export default function copyToClipboard(value: string) {
const textarea = document.createElement("textarea");
textarea.value = value;
document.body.appendChild(textarea);

View File

@ -137,11 +137,5 @@
"Which framework do you think is the most suitable for performance sensitive projects?"
],
"None": [
"free weather api",
"js get timezone",
"how",
"how's",
"how's the"
]
"None": ["free weather api", "js get timezone", "how", "how's", "how's the"]
}

View File

@ -117,11 +117,5 @@
"HTML实体转文本%s"
],
"None": [
"你好",
"为什么计算机使用二进制",
"什么是",
"热",
"怎么"
]
"None": ["你好", "为什么计算机使用二进制", "什么是", "热", "怎么"]
}

View File

@ -8,7 +8,7 @@ import { NluManager, NluNeural } from "@nlpjs/nlu";
import { LangEn } from "@nlpjs/lang-en-min";
// @ts-ignore
import { LangZh } from "@nlpjs/lang-zh";
import * as fflate from 'fflate';
import * as fflate from "fflate";
export interface NLUType {
manager: any;
@ -18,7 +18,6 @@ export interface NLUType {
process(lang: string, text: string): Promise<any>;
}
export class NLU {
manager: any;
inited: boolean = false;

View File

@ -9,7 +9,7 @@ import { LangEn } from "@nlpjs/lang-en-min";
// @ts-ignore
import { LangZh } from "@nlpjs/lang-zh";
import fs from "node:fs";
import * as fflate from 'fflate';
import * as fflate from "fflate";
let zh: TrainData = {};
let en: TrainData = {};
@ -61,7 +61,7 @@ export async function trainIntentionModel() {
const buf = fflate.strToU8(JSON.stringify(resultModel));
const gzipped = fflate.gzipSync(buf, {
filename: 'model.json',
filename: "model.json",
mtime: new Date().getTime()
});

View File

@ -4,7 +4,7 @@ import { settingsType } from "global";
import { useAtomValue } from "jotai";
import { useTranslation } from "react-i18next";
export default function(){
export default function () {
const settings: settingsType = useAtomValue(settingsAtom);
const currentEngine = settings.currentSearchEngine;
const displayEngine = getName(currentEngine);

View File

@ -21,7 +21,7 @@ export function keywordSuggestion(query: string) {
prompt: keyword,
relevance: 3000
};
return result
return result;
}
}
for (const keyword in dict_en) {
@ -32,7 +32,7 @@ export function keywordSuggestion(query: string) {
prompt: keyword,
relevance: 3000
};
return result
return result;
}
}
return null;

View File

@ -1 +1,9 @@
export const engineTranslation = ["google", "bing", "baidu", "duckduckgo", "yandex", "ecosia", "yahoo"];
export const engineTranslation = [
"google",
"bing",
"baidu",
"duckduckgo",
"yandex",
"ecosia",
"yahoo"
];

View File

@ -1,4 +1,4 @@
export default function(query: string, engine: string, newTab: boolean = true) {
if(newTab) window.open(engine.replace("%s", query));
export default function (query: string, engine: string, newTab: boolean = true) {
if (newTab) window.open(engine.replace("%s", query));
else window.location.href = engine.replace("%s", query);
}

View File

@ -1,24 +1,24 @@
import { settingsType } from "global";
import { atomWithStorage } from 'jotai/utils'
import { atomWithStorage } from "jotai/utils";
const defaultSettings: settingsType = {
"version": 2,
"elementBackdrop": true,
"bgBlur": true,
"timeShowSecond": false,
"currentSearchEngine": "google",
"searchInNewTab": true,
"searchEngines": {
"google": "https://www.google.com/search?q=%s",
"bing": "https://www.bing.com/search?q=%s",
"baidu": "https://www.baidu.com/s?wd=%s",
"duckduckgo": "https://duckduckgo.com/?q=%s",
"yandex": "https://yandex.com/search/?text=%s",
"yahoo": "https://search.yahoo.com/search?p=%s",
"ecosia": "https://www.ecosia.org/search?q=%s"
version: 2,
elementBackdrop: true,
bgBlur: true,
timeShowSecond: false,
currentSearchEngine: "google",
searchInNewTab: true,
searchEngines: {
google: "https://www.google.com/search?q=%s",
bing: "https://www.bing.com/search?q=%s",
baidu: "https://www.baidu.com/s?wd=%s",
duckduckgo: "https://duckduckgo.com/?q=%s",
yandex: "https://yandex.com/search/?text=%s",
yahoo: "https://search.yahoo.com/search?p=%s",
ecosia: "https://www.ecosia.org/search?q=%s"
}
};
const settingsAtom = atomWithStorage('settings', defaultSettings);
const settingsAtom = atomWithStorage("settings", defaultSettings);
export { settingsAtom };

View File

@ -1,4 +1,4 @@
import pjson from "package.json"
import pjson from "package.json";
const CLIENT_VERSION = pjson.version;
@ -11,11 +11,11 @@ export function sendError(error: Error) {
body: JSON.stringify({
message: error.message,
name: error.name,
time: new Date().getTime()/1000,
time: new Date().getTime() / 1000,
version: CLIENT_VERSION,
ua: navigator.userAgent,
cause: error.cause,
stack: error.stack
})
})
});
}

View File

@ -1,5 +1,5 @@
import TLDtxt from "./tlds.txt?raw"
import TLDtxt from "./tlds.txt?raw";
export function getTLD(){
return TLDtxt.split("\n").filter((line) => line[0] !== "#")
export function getTLD() {
return TLDtxt.split("\n").filter((line) => line[0] !== "#");
}

View File

@ -1,6 +1,6 @@
import * as pjson from "package.json";
export default function getVersion(){
export default function getVersion() {
return pjson.version;
}

View File

@ -4,9 +4,9 @@ export function getClosestHourTimestamp(): string {
// 获取本地时间的年份、月份、日期、小时
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从0开始
const day = String(now.getDate()).padStart(2, '0');
const hour = String(now.getHours()).padStart(2, '0');
const month = String(now.getMonth() + 1).padStart(2, "0"); // 月份从0开始
const day = String(now.getDate()).padStart(2, "0");
const hour = String(now.getHours()).padStart(2, "0");
// 拼接成所需的格式
const localHourTimestamp = `${year}-${month}-${day}T${hour}:00`;

View File

@ -3,15 +3,16 @@ export async function getWeather(lat: number, lon: number) {
const cacheKey = `weather-cache-${lat.toFixed(2)}-${lon.toFixed(2)}-${timezone}`;
const localData = localStorage.getItem(cacheKey);
if (localData != null) {
console.log('Using cache');
console.log("Using cache");
const parsedLocalData = JSON.parse(localData);
if (parsedLocalData["hourly"]["time"][0] != undefined &&
new Date().getTime() - new Date(parsedLocalData["hourly"]["time"][0]).getTime() < 86400 * 1000
if (
parsedLocalData["hourly"]["time"][0] != undefined &&
new Date().getTime() - new Date(parsedLocalData["hourly"]["time"][0]).getTime() <
86400 * 1000
) {
return parsedLocalData;
}
else {
console.log('Cache expired');
} else {
console.log("Cache expired");
localStorage.removeItem(cacheKey);
}
}

View File

@ -8,7 +8,8 @@
"build": "bun license-gen && tsc -b && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "NODE_ENV=production bun server.ts",
"license-gen": "bunx generate-license-file --input package.json --output lib/license.txt --overwrite"
"license-gen": "bunx generate-license-file --input package.json --output lib/license.txt --overwrite",
"format": "prettier --write ."
},
"dependencies": {
"@iconify/react": "^5.0.1",
@ -51,6 +52,7 @@
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"postcss": "^8.4.38",
"prettier": "^3.3.3",
"tailwindcss": "^3.4.4",
"typescript": "^5.2.2",
"vite": "^5.3.1",

View File

@ -9,7 +9,10 @@ export default function NotFound() {
<div className="relative h-20 mx-4 w-[0.15rem] bg-black dark:bg-white"></div>
<div className="flex flex-col">
<div className="uppercase text-3xl font-light">{t("notfound.title")}</div>
<div className="text-sm" dangerouslySetInnerHTML={{__html:t("notfound.desc")}}></div>
<div
className="text-sm"
dangerouslySetInnerHTML={{ __html: t("notfound.desc") }}
></div>
</div>
</div>
</div>

View File

@ -1,8 +1,10 @@
export default function AboutLayout({ children }: { children: React.ReactNode }) {
return (
<div className="h-screen w-screen overflow-x-hidden bg-white dark:bg-[rgb(23,25,29)]">
<main className="relative h-full w-full md:w-3/4 lg:w-1/2 left-0 md:left-[12.5%] lg:left-1/4
pt-12 px-3 md:px-0">
<main
className="relative h-full w-full md:w-3/4 lg:w-1/2 left-0 md:left-[12.5%] lg:left-1/4
pt-12 px-3 md:px-0"
>
{children}
</main>
</div>

View File

@ -8,9 +8,7 @@ export default function LicensePage() {
pt-12"
>
<h1 className="text-4xl font-bold mb-6">LICENSE</h1>
<div className="font-mono text-justify whitespace-break-spaces">
{LICENSE}
</div>
<div className="font-mono text-justify whitespace-break-spaces">{LICENSE}</div>
</main>
</div>
);

View File

@ -6,7 +6,6 @@ import { networkInterfaces } from "os";
import cac from "cac";
import { configureBackendRoutes } from "./backend/route";
async function helloMessage() {
const { base } = await ViteExpress.getViteConfig();
const timeCost = new Date().getTime() - start.getTime();
@ -19,13 +18,29 @@ async function helloMessage() {
`${Math.round(timeCost)} ms`
);
console.log("");
console.log(" ", chalk.redBright("➜ "), "Local:\t", chalk.cyan(`http://${host}:${port}${base}`));
console.log(
" ",
chalk.redBright("➜ "),
"Local:\t",
chalk.cyan(`http://${host}:${port}${base}`)
);
if (host !== "localhost") {
for (const ip of ips) {
console.log(" ", chalk.redBright("➜ "), "Network:\t", chalk.cyan(`http://${ip}:${port}${base}`));
console.log(
" ",
chalk.redBright("➜ "),
"Network:\t",
chalk.cyan(`http://${ip}:${port}${base}`)
);
}
}
console.log(" ", chalk.red("➜ "), chalk.whiteBright("press"), "h + enter", chalk.whiteBright("to show help"))
console.log(
" ",
chalk.red("➜ "),
chalk.whiteBright("press"),
"h + enter",
chalk.whiteBright("to show help")
);
}
async function handleInput() {
@ -33,14 +48,24 @@ async function handleInput() {
switch (line) {
case "h":
console.log(" Shortcuts");
console.log(" ", chalk.whiteBright("press"), "c + enter ", chalk.whiteBright("to clear console"));
console.log(" ", chalk.whiteBright("press"), "q + enter ", chalk.whiteBright("to quit"));
console.log(
" ",
chalk.whiteBright("press"),
"c + enter ",
chalk.whiteBright("to clear console")
);
console.log(
" ",
chalk.whiteBright("press"),
"q + enter ",
chalk.whiteBright("to quit")
);
break;
case "c":
console.clear();
break;
case "q":
server.on("vite:close", ()=>{});
server.on("vite:close", () => {});
server.close();
return;
default:
@ -71,11 +96,15 @@ const app = express();
const port = 3000;
let host = "localhost";
cli.option("--host [host]", "Sepcify host name")
cli.help()
cli.option("--host [host]", "Sepcify host name");
cli.help();
cli.version(pjson.version);
const parsed = cli.parse();
if (parsed.options.host!==undefined && typeof parsed.options.host == "boolean" && parsed.options.host) {
if (
parsed.options.host !== undefined &&
typeof parsed.options.host == "boolean" &&
parsed.options.host
) {
host = "0.0.0.0";
}

View File

@ -1,18 +1,18 @@
import * as en from "i18n/en.json"
import * as zh from "i18n/zh.json"
import * as ja from "i18n/ja.json"
import * as ar from "i18n/ar.json"
import * as de from "i18n/de.json"
import * as es from "i18n/es.json"
import * as fr from "i18n/fr.json"
import * as it from "i18n/it.json"
import * as ko from "i18n/ko.json"
import * as pt from "i18n/pt.json"
import * as ru from "i18n/ru.json"
import * as en from "i18n/en.json";
import * as zh from "i18n/zh.json";
import * as ja from "i18n/ja.json";
import * as ar from "i18n/ar.json";
import * as de from "i18n/de.json";
import * as es from "i18n/es.json";
import * as fr from "i18n/fr.json";
import * as it from "i18n/it.json";
import * as ko from "i18n/ko.json";
import * as pt from "i18n/pt.json";
import * as ru from "i18n/ru.json";
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from 'i18next-browser-languagedetector';
import ICU from 'i18next-icu';
import LanguageDetector from "i18next-browser-languagedetector";
import ICU from "i18next-icu";
i18n.use(initReactI18next) // passes i18n down to react-i18next
.use(LanguageDetector)
.use(ICU)
@ -59,7 +59,7 @@ i18n.use(initReactI18next) // passes i18n down to react-i18next
},
detection: {
order: ['navigator'],
order: ["navigator"],
caches: []
}
});

View File

@ -8,9 +8,13 @@ describe("Check if a string is an accessible domain/URL/IP", () => {
// With https and path
expect(validLink("https://jestjs.io/docs/getting-started/")).toBe(true);
// With anchor
expect(validLink("https://difftastic.wilfred.me.uk/zh-CN/git.html#git-difftool")).toBe(true);
expect(validLink("https://difftastic.wilfred.me.uk/zh-CN/git.html#git-difftool")).toBe(
true
);
// With params
expect(validLink("https://www.bilibili.com/list/ml2252204359?oid=990610203&bvid=BV1sx4y1g7Hh")).toBe(true);
expect(
validLink("https://www.bilibili.com/list/ml2252204359?oid=990610203&bvid=BV1sx4y1g7Hh")
).toBe(true);
});
test("Punycode URL", () => {
expect(validLink("https://原神大学.com/")).toBe(true);
@ -48,7 +52,7 @@ describe("Check if the given TLD exist and assigned.", () => {
// they really exist!
expect(validTLD("example.foo")).toBe(true);
expect(validTLD("example.bar")).toBe(true);
expect(validTLD('example.zip')).toBe(true);
expect(validTLD("example.zip")).toBe(true);
});
test("Exist but not assigned TLD", () => {
expect(validTLD("example.active")).toBe(false);

View File

@ -1,13 +1,9 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import tsconfigPaths from 'vite-tsconfig-paths';
import { chunkSplitPlugin } from 'vite-plugin-chunk-split';
import tsconfigPaths from "vite-tsconfig-paths";
import { chunkSplitPlugin } from "vite-plugin-chunk-split";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(),
tsconfigPaths(),
chunkSplitPlugin()
]
plugins: [react(), tsconfigPaths(), chunkSplitPlugin()]
});