diff --git a/packages/userscript/src/constants.ts b/packages/userscript/src/constants.ts index ce692cb..fea7d65 100644 --- a/packages/userscript/src/constants.ts +++ b/packages/userscript/src/constants.ts @@ -2,5 +2,7 @@ export const baseUrl = 'https://chat.openai.com' export const LEGACY_KEY_FILENAME_FORMAT = 'exporter-format' export const KEY_FILENAME_FORMAT = 'exporter:filename_format' +export const KEY_TIMESTAMP_ENABLED = 'exporter:enable_timestamp' +export const KEY_TIMESTAMP_24H = 'exporter:timestamp_24h' export const KEY_META_ENABLED = 'exporter:enable_meta' export const KEY_META_LIST = 'exporter:meta_list' diff --git a/packages/userscript/src/exporter/html.ts b/packages/userscript/src/exporter/html.ts index 4bb15b2..d6f0e7c 100644 --- a/packages/userscript/src/exporter/html.ts +++ b/packages/userscript/src/exporter/html.ts @@ -1,14 +1,15 @@ import JSZip from 'jszip' import { fetchConversation, getCurrentChatId, processConversation } from '../api' -import { baseUrl } from '../constants' +import { KEY_TIMESTAMP_24H, KEY_TIMESTAMP_ENABLED, baseUrl } from '../constants' import { checkIfConversationStarted, getConversationChoice, getUserAvatar } from '../page' import templateHtml from '../template.html?raw' import { downloadFile, getFileNameWithFormat } from '../utils/download' import { fromMarkdown, toHtml } from '../utils/markdown' +import { ScriptStorage } from '../utils/storage' import { standardizeLineBreaks } from '../utils/text' import { dateStr, getColorScheme, timestamp } from '../utils/utils' import type { ApiConversationWithId, ConversationResult } from '../api' -import type { ExportMeta } from '../ui/MetaContext' +import type { ExportMeta } from '../ui/SettingContext' export async function exportToHtml(fileNameFormat: string, metaList: ExportMeta[]) { if (!checkIfConversationStarted()) { @@ -71,17 +72,22 @@ function conversationToHtml(conversation: ConversationResult, avatar: string, me conversationContent = `

${escapeHtml(content)}

` } + const enableTimestamp = ScriptStorage.get(KEY_TIMESTAMP_ENABLED) ?? false + const timeStamp24H = ScriptStorage.get(KEY_TIMESTAMP_24H) ?? false const timestamp = item.message?.create_time ?? '' + const showTimestamp = enableTimestamp && timestamp let conversationDate = '' let conversationTime = '' - if (timestamp) { + if (showTimestamp) { const date = new Date(timestamp * 1000) const isoStr = date.toISOString() // format: 2022-01-01 10:12:00 UTC conversationDate = `${isoStr.split('T')[0]} ${isoStr.split('T')[1].split('.')[0]} UTC` - // format: 10:12 AM - conversationTime = date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }) + // format: 20:12 / 08:12 PM + conversationTime = timeStamp24H + ? date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }) + : date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }) } return ` @@ -94,7 +100,7 @@ function conversationToHtml(conversation: ConversationResult, avatar: string, me ${conversationContent} - ${timestamp ? `
${conversationTime}
` : ''} + ${showTimestamp ? `
${conversationTime}
` : ''} ` }).join('\n\n') diff --git a/packages/userscript/src/exporter/markdown.ts b/packages/userscript/src/exporter/markdown.ts index 2084268..befb77c 100644 --- a/packages/userscript/src/exporter/markdown.ts +++ b/packages/userscript/src/exporter/markdown.ts @@ -7,7 +7,7 @@ import { fromMarkdown, toMarkdown } from '../utils/markdown' import { standardizeLineBreaks } from '../utils/text' import { dateStr, timestamp } from '../utils/utils' import type { ApiConversationWithId, ConversationResult } from '../api' -import type { ExportMeta } from '../ui/MetaContext' +import type { ExportMeta } from '../ui/SettingContext' export async function exportToMarkdown(fileNameFormat: string, metaList: ExportMeta[]) { if (!checkIfConversationStarted()) { diff --git a/packages/userscript/src/main.tsx b/packages/userscript/src/main.tsx index 358f405..6b46af3 100644 --- a/packages/userscript/src/main.tsx +++ b/packages/userscript/src/main.tsx @@ -1,7 +1,9 @@ import { render } from 'preact' import sentinel from 'sentinel-js' import { GM_deleteValue, GM_getValue, GM_setValue } from 'vite-plugin-monkey/dist/client' +import { fetchConversation, processConversation } from './api' import { KEY_FILENAME_FORMAT, LEGACY_KEY_FILENAME_FORMAT } from './constants' +import { getChatIdFromUrl, getConversationChoice } from './page' import { Menu } from './ui/Menu' import { SecondaryToolbar } from './ui/SecondaryToolbar' import { onloadSafe } from './utils/utils' @@ -67,7 +69,7 @@ function main() { }) /** Insert copy button to the next of feedback buttons */ - sentinel.on('.flex.justify-between', (node) => { + sentinel.on('main .flex.justify-between', (node) => { if (!node.querySelector('button')) return // ignore codeblock if (node.closest('pre')) return @@ -79,5 +81,40 @@ function main() { render(, secondaryToolbar) node.append(secondaryToolbar) }) + + /** Insert timestamp to the bottom right of each message */ + let chatId = '' + sentinel.on('main .group', async () => { + const threadContents = Array.from(document.querySelectorAll('main .group > .text-base > .relative:nth-child(2)')) + + const currentChatId = getChatIdFromUrl() + if (!currentChatId || currentChatId === chatId) return + chatId = currentChatId + + const rawConversation = await fetchConversation(chatId) + const conversationChoices = getConversationChoice() + const { conversationNodes } = processConversation(rawConversation, conversationChoices) + + threadContents.forEach((thread, index) => { + const createTime = conversationNodes[index].message?.create_time + if (!createTime) return + + const date = new Date(createTime * 1000) + + const timestamp = document.createElement('time') + timestamp.className = 'text-gray-500 dark:text-gray-400 text-sm text-right' + timestamp.dateTime = date.toISOString() + timestamp.title = date.toLocaleString() + + const hour12 = document.createElement('span') + hour12.setAttribute('data-time-format', '12') + hour12.textContent = date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }) + const hour24 = document.createElement('span') + hour24.setAttribute('data-time-format', '24') + hour24.textContent = date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false }) + timestamp.append(hour12, hour24) + thread.append(timestamp) + }) + }) }) } diff --git a/packages/userscript/src/style.css b/packages/userscript/src/style.css index 71636fe..57aefed 100644 --- a/packages/userscript/src/style.css +++ b/packages/userscript/src/style.css @@ -7,6 +7,18 @@ p > img[src*="https://images.unsplash.com/"] { animation: fadeIn .3s; } +span[data-time-format] { + display: none; +} + +body[data-time-format="12"] span[data-time-format="12"] { + display: inline; +} + +body[data-time-format="24"] span[data-time-format="24"] { + display: inline; +} + .Select { padding: 0 0 0 0.5rem; width: 7.5rem; diff --git a/packages/userscript/src/styles/missing-tailwind.css b/packages/userscript/src/styles/missing-tailwind.css index 7c55514..f38f637 100644 --- a/packages/userscript/src/styles/missing-tailwind.css +++ b/packages/userscript/src/styles/missing-tailwind.css @@ -1,3 +1,62 @@ +.after\:content-\[\'\'\]:after { + --tw-content: ""; + content: var(--tw-content); +} + +.after\:transition-all:after { + content: var(--tw-content); + transition-duration: .15s; + transition-property: all; + transition-timing-function: cubic-bezier(.4,0,.2,1); +} + +.after\:bg-white:after { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255/var(--tw-bg-opacity)); + content: var(--tw-content); +} + +.after\:border-gray-300:after { + --tw-border-opacity: 1; + border-color: rgb(209 213 219/var(--tw-border-opacity)); + content: var(--tw-content); +} + +.after\:border:after { + border-width: 1px; + content: var(--tw-content); +} + +.after\:rounded-full:after { + border-radius: 9999px; + + content: var(--tw-content); +} +.after\:w-4:after { + content: var(--tw-content); + width: 1rem +} + +.after\:h-4:after { + content: var(--tw-content); + height: 1rem; +} + +.after\:top-\[2px\]:after { + content: var(--tw-content); + top: 2px; +} + +.after\:left-\[2px\]:after { + content: var(--tw-content); + left: 2px; +} + +.after\:absolute:after { + content: var(--tw-content); + position: absolute; +} + .animate-fadeIn { animation: fadeIn .3s; } @@ -6,11 +65,6 @@ animation: slideUp .3s; } -.bg-gray-200 { - --tw-bg-opacity: 1; - background-color: rgb(229 231 235/var(--tw-bg-opacity)); -} - .bg-blue-600 { --tw-bg-opacity: 1; background-color: rgb(28 100 242/var(--tw-bg-opacity)); @@ -24,13 +78,22 @@ cursor: help; } +.dark .dark\:bg-white\/5 { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / 5%); +} + .dark .dark\:border-gray-\[\#86858d\] { border-color: #86858d; } -.dark .dark\:hover\:bg-gray-700:hover { - --tw-bg-opacity: 1; - background-color: rgb(55 65 81/var(--tw-bg-opacity)); +.dark .dark\:border-gray-600 { + --tw-border-opacity: 1; + border-color: rgb(75 85 99/var(--tw-border-opacity)); +} + +.empty\:hidden:empty { + display: none; } .fill-current { @@ -45,6 +108,14 @@ height: 0.625rem; } +.h-4 { + height: 1rem; +} + +.h-5 { + height: 1.25rem; +} + .mr-8 { margin-right: 2rem; } @@ -53,6 +124,26 @@ padding-bottom: 0; } +.peer:checked~.peer-checked\:bg-blue-600 { + --tw-bg-opacity: 1; + background-color: rgb(28 100 242/var(--tw-bg-opacity)); +} + +.peer:checked~.peer-checked\:after\:border-white:after { + --tw-border-opacity: 1; + border-color: rgb(255 255 255/var(--tw-border-opacity)); + content: var(--tw-content); +} +.peer:checked~.peer-checked\:after\:translate-x-full:after { + --tw-translate-x: 100%; + content: var(--tw-content); + transform: translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.pl-4 { + padding-left: 1rem; +} + .pr-8 { padding-right: 2rem; } @@ -77,6 +168,10 @@ white-space: nowrap; } +.w-9 { + width: 2.25rem; +} + .whitespace-nowrap { white-space: nowrap; } diff --git a/packages/userscript/src/ui/Dialog.css b/packages/userscript/src/ui/Dialog.css index 152d908..5c2a4e8 100644 --- a/packages/userscript/src/ui/Dialog.css +++ b/packages/userscript/src/ui/Dialog.css @@ -7,7 +7,7 @@ } .DialogContent { - background-color: white; + background-color: #f3f3f3; border-radius: 6px; box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px; position: fixed; @@ -15,7 +15,7 @@ left: 50%; transform: translate(-50%, -50%); width: 90vw; - max-width: 450px; + max-width: 560px; max-height: 85vh; overflow-x: hidden; overflow-y: auto; diff --git a/packages/userscript/src/ui/ExportDialog.tsx b/packages/userscript/src/ui/ExportDialog.tsx index 48f60e4..1ff2bf6 100644 --- a/packages/userscript/src/ui/ExportDialog.tsx +++ b/packages/userscript/src/ui/ExportDialog.tsx @@ -7,7 +7,7 @@ import { exportAllToMarkdown } from '../exporter/markdown' import { RequestQueue } from '../utils/queue' import { CheckBox } from './CheckBox' import { IconCross } from './Icons' -import { useMetaDataContext } from './MetaContext' +import { useSettingContext } from './SettingContext' import type { ApiConversationItem, ApiConversationWithId } from '../api' import type { FC } from '../type' @@ -76,7 +76,7 @@ interface ExportDialogProps { } export const ExportDialog: FC = ({ format, open, onOpenChange, children }) => { - const { enableMeta, exportMetaList } = useMetaDataContext() + const { enableMeta, exportMetaList } = useSettingContext() const metaList = useMemo(() => enableMeta ? exportMetaList : [], [enableMeta, exportMetaList]) const [conversations, setConversations] = useState([]) diff --git a/packages/userscript/src/ui/FormatContext.tsx b/packages/userscript/src/ui/FormatContext.tsx deleted file mode 100644 index 5abf28a..0000000 --- a/packages/userscript/src/ui/FormatContext.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { createContext, useContext } from 'preact/compat' -import { KEY_FILENAME_FORMAT } from '../constants' -import { useGMStorage } from '../hooks/useGMStorage' -import type { FC } from 'preact/compat' - -const defaultFormat = 'ChatGPT-{title}' - -const FormatContext = createContext({ - format: defaultFormat, - setFormat: (_: string) => {}, -}) - -export const FormatProvider: FC = ({ children }) => { - const [format, setFormat] = useGMStorage(KEY_FILENAME_FORMAT, defaultFormat) - - return ( - - {children} - - ) -} - -export const useFormatContext = () => useContext(FormatContext) diff --git a/packages/userscript/src/ui/Menu.tsx b/packages/userscript/src/ui/Menu.tsx index 50422c7..809a968 100644 --- a/packages/userscript/src/ui/Menu.tsx +++ b/packages/userscript/src/ui/Menu.tsx @@ -1,5 +1,5 @@ import * as HoverCard from '@radix-ui/react-hover-card' -import { useCallback, useMemo, useState } from 'preact/hooks' +import { useCallback, useEffect, useMemo, useState } from 'preact/hooks' import { exportToHtml } from '../exporter/html' import { exportToPng } from '../exporter/image' import { exportToJson } from '../exporter/json' @@ -8,10 +8,9 @@ import { exportToText } from '../exporter/text' import { getHistoryDisabled } from '../page' import { Divider } from './Divider' import { ExportDialog } from './ExportDialog' -import { FormatProvider, useFormatContext } from './FormatContext' import { FileCode, IconArrowRightFromBracket, IconCamera, IconCopy, IconJSON, IconMarkdown, IconSetting, IconZip } from './Icons' import { MenuItem } from './MenuItem' -import { MetaDataProvider, useMetaDataContext } from './MetaContext' +import { SettingProvider, useSettingContext } from './SettingContext' import { SettingDialog } from './SettingDialog' import '../style.css' @@ -28,8 +27,24 @@ function MenuInner({ container }: { container: HTMLDivElement }) { const [exportOpen, setExportOpen] = useState(false) const [settingOpen, setSettingOpen] = useState(false) - const { format } = useFormatContext() - const { enableMeta, exportMetaList } = useMetaDataContext() + const { + format, + enableTimestamp, + timeStamp24H, + enableMeta, + exportMetaList, + } = useSettingContext() + + useEffect(() => { + console.log('enableTimestamp', enableTimestamp, 'timeStamp24H', timeStamp24H) + if (enableTimestamp) { + document.body.setAttribute('data-time-format', timeStamp24H ? '24' : '12') + } + else { + document.body.removeAttribute('data-time-format') + } + }, [enableTimestamp, timeStamp24H]) + const metaList = useMemo(() => enableMeta ? exportMetaList : [], [enableMeta, exportMetaList]) const onClickText = useCallback(() => exportToText(), []) @@ -161,10 +176,8 @@ function MenuInner({ container }: { container: HTMLDivElement }) { export function Menu({ container }: { container: HTMLDivElement }) { return ( - - - - - + + + ) } diff --git a/packages/userscript/src/ui/MetaContext.tsx b/packages/userscript/src/ui/MetaContext.tsx deleted file mode 100644 index e4d6aaf..0000000 --- a/packages/userscript/src/ui/MetaContext.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { createContext, useContext } from 'preact/compat' -import { KEY_META_ENABLED, KEY_META_LIST } from '../constants' -import { useGMStorage } from '../hooks/useGMStorage' -import type { FC } from 'preact/compat' - -export interface ExportMeta { - name: string - value: string -} - -const defaultExportMetaList: ExportMeta[] = [ - { name: 'title', value: '{title}' }, - { name: 'source', value: '{source}' }, -] - -const MetaContext = createContext({ - enableMeta: false, - setEnableMeta: (_: boolean) => {}, - exportMetaList: defaultExportMetaList, - setExportMetaList: (_: ExportMeta[]) => {}, -}) - -export const MetaDataProvider: FC = ({ children }) => { - const [enableMeta, setEnableMeta] = useGMStorage(KEY_META_ENABLED, false) - const [exportMetaList, setExportMetaList] = useGMStorage(KEY_META_LIST, defaultExportMetaList) - - return ( - - {children} - - ) -} - -export const useMetaDataContext = () => useContext(MetaContext) diff --git a/packages/userscript/src/ui/SettingContext.tsx b/packages/userscript/src/ui/SettingContext.tsx new file mode 100644 index 0000000..7a15dab --- /dev/null +++ b/packages/userscript/src/ui/SettingContext.tsx @@ -0,0 +1,76 @@ +import { createContext, useContext } from 'preact/compat' +import { useCallback } from 'preact/hooks' +import { KEY_FILENAME_FORMAT, KEY_META_ENABLED, KEY_META_LIST, KEY_TIMESTAMP_24H, KEY_TIMESTAMP_ENABLED } from '../constants' +import { useGMStorage } from '../hooks/useGMStorage' +import type { FC } from 'preact/compat' + +const defaultFormat = 'ChatGPT-{title}' + +export interface ExportMeta { + name: string + value: string +} + +const defaultExportMetaList: ExportMeta[] = [ + { name: 'title', value: '{title}' }, + { name: 'source', value: '{source}' }, +] + +const SettingContext = createContext({ + format: defaultFormat, + setFormat: (_: string) => {}, + + enableTimestamp: false, + setEnableTimestamp: (_: boolean) => {}, + timeStamp24H: false, + setTimeStamp24H: (_: boolean) => {}, + + enableMeta: false, + setEnableMeta: (_: boolean) => {}, + exportMetaList: defaultExportMetaList, + setExportMetaList: (_: ExportMeta[]) => {}, + + resetDefault: () => {}, +}) + +export const SettingProvider: FC = ({ children }) => { + const [format, setFormat] = useGMStorage(KEY_FILENAME_FORMAT, defaultFormat) + + const [enableTimestamp, setEnableTimestamp] = useGMStorage(KEY_TIMESTAMP_ENABLED, false) + const [timeStamp24H, setTimeStamp24H] = useGMStorage(KEY_TIMESTAMP_24H, false) + + const [enableMeta, setEnableMeta] = useGMStorage(KEY_META_ENABLED, false) + + const [exportMetaList, setExportMetaList] = useGMStorage(KEY_META_LIST, defaultExportMetaList) + + const resetDefault = useCallback(() => { + setFormat(defaultFormat) + setEnableMeta(false) + setExportMetaList(defaultExportMetaList) + }, [setFormat, setEnableMeta, setExportMetaList]) + + return ( + + {children} + + ) +} + +export const useSettingContext = () => useContext(SettingContext) diff --git a/packages/userscript/src/ui/SettingDialog.tsx b/packages/userscript/src/ui/SettingDialog.tsx index 027e696..fa50b58 100644 --- a/packages/userscript/src/ui/SettingDialog.tsx +++ b/packages/userscript/src/ui/SettingDialog.tsx @@ -5,10 +5,9 @@ import { useTitle } from '../hooks/useTitle' import { getChatIdFromUrl } from '../page' import { getFileNameWithFormat } from '../utils/download' import { timestamp as _timestamp, dateStr } from '../utils/utils' -import { CheckBox } from './CheckBox' -import { useFormatContext } from './FormatContext' import { IconCross, IconTrash } from './Icons' -import { useMetaDataContext } from './MetaContext' +import { useSettingContext } from './SettingContext' +import { Toggle } from './Toggle' import type { FC } from '../type' const Variable = ({ name, title }: { name: string; title: string }) => ( @@ -25,9 +24,13 @@ export const SettingDialog: FC = ({ onOpenChange, children, }) => { - const { format, setFormat } = useFormatContext() - const { enableMeta, setEnableMeta, exportMetaList, setExportMetaList } = useMetaDataContext() - + const { + format, setFormat, + enableTimestamp, setEnableTimestamp, + timeStamp24H, setTimeStamp24H, + enableMeta, setEnableMeta, + exportMetaList, setExportMetaList, + } = useSettingContext() const _title = useTitle() const date = dateStr() const timestamp = _timestamp() @@ -51,101 +54,122 @@ export const SettingDialog: FC = ({ Exporter Setting
-
-
-
File Name - -
-
-

- Available variables:  - - ,  - - ,  - - ,  - -

- setFormat(e.currentTarget.value)} /> -

- Preview:  - {preview} -

-
+ +
+

+ Available variables:{' '} + + ,{' '} + + ,{' '} + + ,{' '} + +

+ setFormat(e.currentTarget.value)} /> +

+ Preview:{' '} + {preview} +

+
+
+ +
+
+
+ Conversation Timestamp +
+
+ Will show on the page and HTML files. + {enableTimestamp && ( +
+ +
+ )} +
+
+
+ +
-
-
-
+
+
+
Export Metadata -
-

+ +

Add metadata to exported Markdown and HTML files. -

- -
- - {enableMeta && ( - <> -

- Available variables:  - - ,  - - ,  - - ,  - - ,  -
- - ,  - -

- {exportMetaList.map((meta, i) => ( -
- { - const list = [...exportMetaList] - list[i] = { ...list[i], name: e.currentTarget.value } - setExportMetaList(list) - }} - /> - - { - const list = [...exportMetaList] - list[i] = { ...list[i], value: e.currentTarget.value } - setExportMetaList(list) - }} - /> + {enableMeta && ( + <> +

+ Available variables:{' '} + + ,{' '} + + ,{' '} + + ,{' '} + + ,{' '} + + ,{' '} + +

+ {exportMetaList.map((meta, i) => ( +
+ { + const list = [...exportMetaList] + list[i] = { ...list[i], name: e.currentTarget.value } + setExportMetaList(list) + }} + /> + + { + const list = [...exportMetaList] + list[i] = { ...list[i], value: e.currentTarget.value } + setExportMetaList(list) + }} + /> + +
+ ))} +
- ))} -
- -
- - )} -
+ + )} + + +
+ +
diff --git a/packages/userscript/src/ui/Toggle.tsx b/packages/userscript/src/ui/Toggle.tsx new file mode 100644 index 0000000..478be20 --- /dev/null +++ b/packages/userscript/src/ui/Toggle.tsx @@ -0,0 +1,25 @@ +interface ToggleProps { + label?: string + checked?: boolean + onCheckedUpdate?: (checked: boolean) => void +} + +export const Toggle = (props: ToggleProps) => { + const { label = '', checked = true, onCheckedUpdate } = props + const handleChange = (e: React.ChangeEvent) => { + if (!e.target || !onCheckedUpdate) return + onCheckedUpdate((e.target as HTMLInputElement).checked) + } + return ( + + ) +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 57a44b9..3697794 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,7 +28,7 @@ importers: cpy-cli: 4.2.0 eslint: 8.37.0 husky: 8.0.3 - lint-staged: 13.2.0 + lint-staged: 13.2.1 rimraf: 4.4.1 turbo: 1.8.8 typescript: 5.0.3 @@ -86,12 +86,12 @@ importers: packages: - /@ampproject/remapping/2.2.0: - resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} + /@ampproject/remapping/2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} engines: {node: '>=6.0.0'} dependencies: - '@jridgewell/gen-mapping': 0.1.1 - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 dev: true /@babel/code-frame/7.21.4: @@ -110,7 +110,7 @@ packages: resolution: {integrity: sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==} engines: {node: '>=6.9.0'} dependencies: - '@ampproject/remapping': 2.2.0 + '@ampproject/remapping': 2.2.1 '@babel/code-frame': 7.21.4 '@babel/generator': 7.21.4 '@babel/helper-compilation-targets': 7.21.4_@babel+core@7.21.4 @@ -134,8 +134,8 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/types': 7.21.4 - '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 jsesc: 2.5.2 dev: true @@ -774,25 +774,22 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true - /@jridgewell/gen-mapping/0.1.1: - resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} + /@jridgewell/gen-mapping/0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} engines: {node: '>=6.0.0'} dependencies: '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.18 dev: true - /@jridgewell/gen-mapping/0.3.2: - resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} + /@jridgewell/resolve-uri/3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.17 dev: true - /@jridgewell/resolve-uri/3.1.0: - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + /@jridgewell/resolve-uri/3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} engines: {node: '>=6.0.0'} dev: true @@ -805,8 +802,12 @@ packages: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} dev: true - /@jridgewell/trace-mapping/0.3.17: - resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} + /@jridgewell/sourcemap-codec/1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping/0.3.18: + resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} dependencies: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 @@ -815,8 +816,8 @@ packages: /@jridgewell/trace-mapping/0.3.9: resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 dev: true /@nodelib/fs.scandir/2.1.5: @@ -918,7 +919,7 @@ packages: babel-plugin-transform-hook-names: 1.0.2_@babel+core@7.21.4 debug: 4.3.4 kolorist: 1.7.0 - resolve: 1.22.1 + resolve: 1.22.2 vite: 4.2.1 transitivePeerDependencies: - preact @@ -1673,7 +1674,7 @@ packages: hasBin: true dependencies: caniuse-lite: 1.0.30001474 - electron-to-chromium: 1.4.352 + electron-to-chromium: 1.4.355 node-releases: 2.0.10 update-browserslist-db: 1.0.10_browserslist@4.21.5 dev: true @@ -2151,8 +2152,8 @@ packages: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true - /electron-to-chromium/1.4.352: - resolution: {integrity: sha512-ikFUEyu5/q+wJpMOxWxTaEVk2M1qKqTGKKyfJmod1CPZxKfYnxVS41/GCBQg21ItBpZybyN8sNpRqCUGm+Zc4Q==} + /electron-to-chromium/1.4.355: + resolution: {integrity: sha512-056hxzEE4l667YeOccgjhRr5fTiwZ6EIJ4FpzGps4k3YcS8iAhiaBYUBrv5E2LDQJsussscv9EEUwAYKnv+ZKg==} dev: true /emoji-regex/8.0.0: @@ -2290,7 +2291,7 @@ packages: dependencies: debug: 3.2.7 is-core-module: 2.11.0 - resolve: 1.22.1 + resolve: 1.22.2 transitivePeerDependencies: - supports-color dev: true @@ -2376,7 +2377,7 @@ packages: is-glob: 4.0.3 minimatch: 3.1.2 object.values: 1.1.6 - resolve: 1.22.1 + resolve: 1.22.2 semver: 6.3.0 tsconfig-paths: 3.14.2 transitivePeerDependencies: @@ -2443,7 +2444,7 @@ packages: ignore: 5.2.4 is-core-module: 2.11.0 minimatch: 3.1.2 - resolve: 1.22.1 + resolve: 1.22.2 semver: 7.3.8 dev: true @@ -3596,8 +3597,8 @@ packages: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: true - /lint-staged/13.2.0: - resolution: {integrity: sha512-GbyK5iWinax5Dfw5obm2g2ccUiZXNGtAS4mCbJ0Lv4rq6iEtfBSjOYdcbOtAIFtM114t0vdpViDDetjVTSd8Vw==} + /lint-staged/13.2.1: + resolution: {integrity: sha512-8gfzinVXoPfga5Dz/ZOn8I2GOhf81Wvs+KwbEXQn/oWZAvCVS2PivrXfVbFJc93zD16uC0neS47RXHIjXKYZQw==} engines: {node: ^14.13.1 || >=16.0.0} hasBin: true dependencies: @@ -4326,7 +4327,7 @@ packages: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: hosted-git-info: 2.8.9 - resolve: 1.22.1 + resolve: 1.22.2 semver: 5.7.1 validate-npm-package-license: 3.0.4 dev: true @@ -4880,8 +4881,8 @@ packages: global-dirs: 0.1.1 dev: true - /resolve/1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} + /resolve/1.22.2: + resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} hasBin: true dependencies: is-core-module: 2.11.0 @@ -5704,7 +5705,7 @@ packages: dependencies: esbuild: 0.17.15 postcss: 8.4.21 - resolve: 1.22.1 + resolve: 1.22.2 rollup: 3.20.2 optionalDependencies: fsevents: 2.3.2