2023-04-25 11:01:25 +00:00
|
|
|
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync } from 'fs'
|
|
|
|
import { join } from 'path'
|
|
|
|
import { optimize } from 'svgo'
|
|
|
|
import {
|
|
|
|
readJsonIfExists,
|
2024-01-16 14:38:05 +00:00
|
|
|
REPO_ROOT,
|
2023-05-09 16:08:38 +00:00
|
|
|
writeCodeFile,
|
2023-04-25 11:01:25 +00:00
|
|
|
writeFile,
|
|
|
|
writeJsonFile,
|
|
|
|
writeStringFile,
|
|
|
|
} from './lib/file'
|
2023-06-01 18:01:49 +00:00
|
|
|
import { nicelog } from './lib/nicelog'
|
2023-04-25 11:01:25 +00:00
|
|
|
|
|
|
|
// We'll need to copy the assets into these folders
|
2024-01-16 14:38:05 +00:00
|
|
|
const PUBLIC_FOLDER_PATHS = [join(REPO_ROOT, 'packages', 'assets')]
|
2023-04-25 11:01:25 +00:00
|
|
|
|
|
|
|
const FONT_MAPPING: Record<string, string> = {
|
|
|
|
'IBMPlexMono-Medium': 'monospace',
|
|
|
|
'IBMPlexSerif-Medium': 'serif',
|
|
|
|
'IBMPlexSans-Medium': 'sansSerif',
|
2023-12-19 14:17:45 +00:00
|
|
|
'Shantell_Sans-Tldrawish': 'draw',
|
2023-04-25 11:01:25 +00:00
|
|
|
}
|
|
|
|
|
2024-01-16 14:38:05 +00:00
|
|
|
const ASSETS_FOLDER_PATH = join(REPO_ROOT, 'assets')
|
2023-04-25 11:01:25 +00:00
|
|
|
|
|
|
|
const collectedAssetUrls: {
|
2023-05-05 13:10:36 +00:00
|
|
|
fonts: Record<string, string>
|
|
|
|
icons: Record<string, string>
|
|
|
|
translations: Record<string, string>
|
|
|
|
embedIcons: Record<string, string>
|
2023-04-25 11:01:25 +00:00
|
|
|
} = {
|
2023-05-05 13:10:36 +00:00
|
|
|
fonts: {},
|
|
|
|
icons: {},
|
|
|
|
translations: {},
|
|
|
|
embedIcons: {},
|
2023-04-25 11:01:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 1. ICONS
|
|
|
|
|
|
|
|
async function copyIcons() {
|
|
|
|
// Get a list of all icons
|
|
|
|
const icons = readdirSync(join(ASSETS_FOLDER_PATH, 'icons', 'icon')).filter((icon) =>
|
|
|
|
icon.endsWith('.svg')
|
|
|
|
)
|
|
|
|
|
|
|
|
// Write list of names into icon-names.json (just the name, not extension)
|
|
|
|
const iconNames = icons.map((name) => name.replace('.svg', ''))
|
|
|
|
|
|
|
|
const sourceFolderPath = join(ASSETS_FOLDER_PATH, 'icons', 'icon')
|
|
|
|
|
|
|
|
// Create the optimized SVGs
|
|
|
|
const optimizedSvgs = icons.map((icon) => {
|
|
|
|
const iconPath = join(sourceFolderPath, icon)
|
|
|
|
const content = readFileSync(iconPath, 'utf8')
|
|
|
|
const svg = optimize(content, { path: iconPath })
|
|
|
|
return { fileName: icon, data: svg.data }
|
|
|
|
})
|
|
|
|
|
|
|
|
// Optimize all of the svg icons and write them into the new folders
|
|
|
|
for (const folderPath of PUBLIC_FOLDER_PATHS) {
|
|
|
|
const publicIconsRootFolderPath = join(folderPath, 'icons')
|
|
|
|
const pulicIconsFolderPath = join(publicIconsRootFolderPath, 'icon')
|
|
|
|
|
|
|
|
if (existsSync(publicIconsRootFolderPath)) {
|
|
|
|
rmSync(publicIconsRootFolderPath, { recursive: true })
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the folders
|
|
|
|
mkdirSync(publicIconsRootFolderPath, { recursive: true })
|
|
|
|
mkdirSync(pulicIconsFolderPath, { recursive: true })
|
|
|
|
|
|
|
|
// Copy each optimized icons into the new folder
|
|
|
|
for (const { fileName, data } of optimizedSvgs) {
|
|
|
|
await writeStringFile(join(pulicIconsFolderPath, fileName), data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write the JSON file containing all of the names of the icons
|
|
|
|
await writeJsonFile(join(pulicIconsFolderPath, 'icon-names.json'), iconNames)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the names of all of the svg icons and create a TypeScript file of valid icon names
|
|
|
|
const iconTypeFile = `
|
|
|
|
/** @public */
|
|
|
|
export type TLUiIconType =
|
|
|
|
${icons.map((icon) => JSON.stringify(icon.replace('.svg', ''))).join(' | ')}
|
|
|
|
|
|
|
|
/** @public */
|
2023-06-02 21:16:09 +00:00
|
|
|
export const iconTypes = [
|
2023-04-25 11:01:25 +00:00
|
|
|
${icons.map((icon) => JSON.stringify(icon.replace('.svg', ''))).join(', ')}
|
|
|
|
] as const`
|
|
|
|
|
2023-05-09 16:08:38 +00:00
|
|
|
await writeCodeFile(
|
|
|
|
'scripts/refresh-assets.ts',
|
|
|
|
'typescript',
|
2024-01-16 14:38:05 +00:00
|
|
|
join(REPO_ROOT, 'packages', 'tldraw', 'src', 'lib', 'ui', 'icon-types.ts'),
|
2023-04-25 11:01:25 +00:00
|
|
|
iconTypeFile
|
|
|
|
)
|
|
|
|
|
|
|
|
// add to the asset declaration file
|
|
|
|
for (const icon of icons) {
|
|
|
|
const name = icon.replace('.svg', '')
|
2023-05-05 13:10:36 +00:00
|
|
|
collectedAssetUrls.icons[name] = `icons/icon/${icon}`
|
2023-04-25 11:01:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2. EMBED-ICONS
|
|
|
|
|
|
|
|
async function copyEmbedIcons() {
|
|
|
|
const folderName = 'embed-icons'
|
|
|
|
const extension = '.png'
|
|
|
|
|
|
|
|
const sourceFolderPath = join(ASSETS_FOLDER_PATH, folderName)
|
|
|
|
const itemsToCopy = readdirSync(sourceFolderPath).filter((icon) => icon.endsWith(extension))
|
|
|
|
|
|
|
|
for (const publicFolderPath of PUBLIC_FOLDER_PATHS) {
|
|
|
|
const destinationFolderPath = join(publicFolderPath, folderName)
|
|
|
|
|
|
|
|
// Delete the folder if it exists
|
|
|
|
if (existsSync(destinationFolderPath)) {
|
|
|
|
rmSync(destinationFolderPath, { recursive: true })
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make the new folder
|
|
|
|
mkdirSync(destinationFolderPath, { recursive: true })
|
|
|
|
|
|
|
|
// Copy all items into the new folder
|
|
|
|
for (const item of itemsToCopy) {
|
|
|
|
await writeFile(join(destinationFolderPath, item), readFileSync(join(sourceFolderPath, item)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add to the asset declaration file
|
|
|
|
for (const item of itemsToCopy) {
|
|
|
|
const name = item.replace(extension, '')
|
2023-05-05 13:10:36 +00:00
|
|
|
collectedAssetUrls.embedIcons[name] = `${folderName}/${item}`
|
2023-04-25 11:01:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 3. FONTS
|
|
|
|
|
|
|
|
async function copyFonts() {
|
|
|
|
const folderName = 'fonts'
|
|
|
|
const extension = '.woff2'
|
|
|
|
|
|
|
|
const sourceFolderPath = join(ASSETS_FOLDER_PATH, folderName)
|
|
|
|
const itemsToCopy = readdirSync(sourceFolderPath).filter((icon) => icon.endsWith(extension))
|
|
|
|
|
|
|
|
for (const publicFolderPath of PUBLIC_FOLDER_PATHS) {
|
|
|
|
const destinationFolderPath = join(publicFolderPath, folderName)
|
|
|
|
|
|
|
|
// Delete the folder if it exists
|
|
|
|
if (existsSync(destinationFolderPath)) {
|
|
|
|
rmSync(destinationFolderPath, { recursive: true })
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make the new folder
|
|
|
|
mkdirSync(destinationFolderPath)
|
|
|
|
|
|
|
|
// Copy all items into the new folder
|
|
|
|
for (const item of itemsToCopy) {
|
|
|
|
await writeFile(join(destinationFolderPath, item), readFileSync(join(sourceFolderPath, item)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add to the asset declaration file
|
|
|
|
for (const item of itemsToCopy) {
|
|
|
|
const itemWithoutExtension = item.replace(extension, '')
|
|
|
|
const name = FONT_MAPPING[itemWithoutExtension]
|
|
|
|
if (!name) {
|
2023-06-01 18:01:49 +00:00
|
|
|
nicelog('Font mapping not found for', itemWithoutExtension)
|
2023-04-25 11:01:25 +00:00
|
|
|
process.exit(1)
|
|
|
|
}
|
2023-05-05 13:10:36 +00:00
|
|
|
collectedAssetUrls.fonts[name] = `${folderName}/${item}`
|
2023-04-25 11:01:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 3. TRANSLATIONS
|
|
|
|
|
|
|
|
async function copyTranslations() {
|
|
|
|
const folderName = 'translations'
|
|
|
|
const extension = '.json'
|
|
|
|
|
|
|
|
const sourceFolderPath = join(ASSETS_FOLDER_PATH, folderName)
|
|
|
|
const itemsToCopy = readdirSync(sourceFolderPath).filter((item) => item.endsWith(extension))
|
|
|
|
|
|
|
|
for (const publicFolderPath of PUBLIC_FOLDER_PATHS) {
|
|
|
|
const destinationFolderPath = join(publicFolderPath, folderName)
|
|
|
|
|
|
|
|
// Delete the folder if it exists
|
|
|
|
if (existsSync(destinationFolderPath)) {
|
|
|
|
rmSync(destinationFolderPath, { recursive: true })
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make the new folder
|
|
|
|
mkdirSync(destinationFolderPath)
|
|
|
|
|
|
|
|
// Copy all items into the new folder
|
|
|
|
for (const item of itemsToCopy) {
|
|
|
|
await writeFile(join(destinationFolderPath, item), readFileSync(join(sourceFolderPath, item)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create hardcoded files
|
tldraw zero - package shuffle (#1710)
This PR moves code between our packages so that:
- @tldraw/editor is a “core” library with the engine and canvas but no
shapes, tools, or other things
- @tldraw/tldraw contains everything particular to the experience we’ve
built for tldraw
At first look, this might seem like a step away from customization and
configuration, however I believe it greatly increases the configuration
potential of the @tldraw/editor while also providing a more accurate
reflection of what configuration options actually exist for
@tldraw/tldraw.
## Library changes
@tldraw/editor re-exports its dependencies and @tldraw/tldraw re-exports
@tldraw/editor.
- users of @tldraw/editor WITHOUT @tldraw/tldraw should almost always
only import things from @tldraw/editor.
- users of @tldraw/tldraw should almost always only import things from
@tldraw/tldraw.
- @tldraw/polyfills is merged into @tldraw/editor
- @tldraw/indices is merged into @tldraw/editor
- @tldraw/primitives is merged mostly into @tldraw/editor, partially
into @tldraw/tldraw
- @tldraw/file-format is merged into @tldraw/tldraw
- @tldraw/ui is merged into @tldraw/tldraw
Many (many) utils and other code is moved from the editor to tldraw. For
example, embeds now are entirely an feature of @tldraw/tldraw. The only
big chunk of code left in core is related to arrow handling.
## API Changes
The editor can now be used without tldraw's assets. We load them in
@tldraw/tldraw instead, so feel free to use whatever fonts or images or
whatever that you like with the editor.
All tools and shapes (except for the `Group` shape) are moved to
@tldraw/tldraw. This includes the `select` tool.
You should use the editor with at least one tool, however, so you now
also need to send in an `initialState` prop to the Editor /
<TldrawEditor> component indicating which state the editor should begin
in.
The `components` prop now also accepts `SelectionForeground`.
The complex selection component that we use for tldraw is moved to
@tldraw/tldraw. The default component is quite basic but can easily be
replaced via the `components` prop. We pass down our tldraw-flavored
SelectionFg via `components`.
Likewise with the `Scribble` component: the `DefaultScribble` no longer
uses our freehand tech and is a simple path instead. We pass down the
tldraw-flavored scribble via `components`.
The `ExternalContentManager` (`Editor.externalContentManager`) is
removed and replaced with a mapping of types to handlers.
- Register new content handlers with
`Editor.registerExternalContentHandler`.
- Register new asset creation handlers (for files and URLs) with
`Editor.registerExternalAssetHandler`
### Change Type
- [x] `major` — Breaking change
### Test Plan
- [x] Unit Tests
- [x] End to end tests
### Release Notes
- [@tldraw/editor] lots, wip
- [@tldraw/ui] gone, merged to tldraw/tldraw
- [@tldraw/polyfills] gone, merged to tldraw/editor
- [@tldraw/primitives] gone, merged to tldraw/editor / tldraw/tldraw
- [@tldraw/indices] gone, merged to tldraw/editor
- [@tldraw/file-format] gone, merged to tldraw/tldraw
---------
Co-authored-by: alex <alex@dytry.ch>
2023-07-17 21:22:34 +00:00
|
|
|
const uiPath = join(
|
2024-01-16 14:38:05 +00:00
|
|
|
REPO_ROOT,
|
tldraw zero - package shuffle (#1710)
This PR moves code between our packages so that:
- @tldraw/editor is a “core” library with the engine and canvas but no
shapes, tools, or other things
- @tldraw/tldraw contains everything particular to the experience we’ve
built for tldraw
At first look, this might seem like a step away from customization and
configuration, however I believe it greatly increases the configuration
potential of the @tldraw/editor while also providing a more accurate
reflection of what configuration options actually exist for
@tldraw/tldraw.
## Library changes
@tldraw/editor re-exports its dependencies and @tldraw/tldraw re-exports
@tldraw/editor.
- users of @tldraw/editor WITHOUT @tldraw/tldraw should almost always
only import things from @tldraw/editor.
- users of @tldraw/tldraw should almost always only import things from
@tldraw/tldraw.
- @tldraw/polyfills is merged into @tldraw/editor
- @tldraw/indices is merged into @tldraw/editor
- @tldraw/primitives is merged mostly into @tldraw/editor, partially
into @tldraw/tldraw
- @tldraw/file-format is merged into @tldraw/tldraw
- @tldraw/ui is merged into @tldraw/tldraw
Many (many) utils and other code is moved from the editor to tldraw. For
example, embeds now are entirely an feature of @tldraw/tldraw. The only
big chunk of code left in core is related to arrow handling.
## API Changes
The editor can now be used without tldraw's assets. We load them in
@tldraw/tldraw instead, so feel free to use whatever fonts or images or
whatever that you like with the editor.
All tools and shapes (except for the `Group` shape) are moved to
@tldraw/tldraw. This includes the `select` tool.
You should use the editor with at least one tool, however, so you now
also need to send in an `initialState` prop to the Editor /
<TldrawEditor> component indicating which state the editor should begin
in.
The `components` prop now also accepts `SelectionForeground`.
The complex selection component that we use for tldraw is moved to
@tldraw/tldraw. The default component is quite basic but can easily be
replaced via the `components` prop. We pass down our tldraw-flavored
SelectionFg via `components`.
Likewise with the `Scribble` component: the `DefaultScribble` no longer
uses our freehand tech and is a simple path instead. We pass down the
tldraw-flavored scribble via `components`.
The `ExternalContentManager` (`Editor.externalContentManager`) is
removed and replaced with a mapping of types to handlers.
- Register new content handlers with
`Editor.registerExternalContentHandler`.
- Register new asset creation handlers (for files and URLs) with
`Editor.registerExternalAssetHandler`
### Change Type
- [x] `major` — Breaking change
### Test Plan
- [x] Unit Tests
- [x] End to end tests
### Release Notes
- [@tldraw/editor] lots, wip
- [@tldraw/ui] gone, merged to tldraw/tldraw
- [@tldraw/polyfills] gone, merged to tldraw/editor
- [@tldraw/primitives] gone, merged to tldraw/editor / tldraw/tldraw
- [@tldraw/indices] gone, merged to tldraw/editor
- [@tldraw/file-format] gone, merged to tldraw/tldraw
---------
Co-authored-by: alex <alex@dytry.ch>
2023-07-17 21:22:34 +00:00
|
|
|
'packages',
|
|
|
|
'tldraw',
|
|
|
|
'src',
|
|
|
|
'lib',
|
|
|
|
'ui',
|
|
|
|
'hooks',
|
|
|
|
'useTranslation'
|
|
|
|
)
|
2023-04-25 11:01:25 +00:00
|
|
|
|
|
|
|
// languages.ts
|
2023-06-03 20:46:53 +00:00
|
|
|
|
2023-04-25 11:01:25 +00:00
|
|
|
const languagesSource = await readJsonIfExists(join(sourceFolderPath, 'languages.json'))!
|
2024-01-25 11:26:33 +00:00
|
|
|
type Language = { label: string; locale: string }
|
2023-04-25 11:01:25 +00:00
|
|
|
const languagesFile = `
|
|
|
|
/** @public */
|
2024-01-25 11:26:33 +00:00
|
|
|
export const LANGUAGES = ${JSON.stringify(
|
|
|
|
languagesSource.sort((a: Language, b: Language) => a.label.localeCompare(b.label))
|
|
|
|
)} as const
|
2023-04-25 11:01:25 +00:00
|
|
|
`
|
2024-01-16 14:38:05 +00:00
|
|
|
const schemaPath = join(REPO_ROOT, 'packages', 'tlschema', 'src', 'translations')
|
2023-04-25 11:01:25 +00:00
|
|
|
const schemaLanguagesFilePath = join(schemaPath, 'languages.ts')
|
2023-05-09 16:08:38 +00:00
|
|
|
await writeCodeFile(
|
|
|
|
'scripts/refresh-assets.ts',
|
|
|
|
'typescript',
|
|
|
|
schemaLanguagesFilePath,
|
|
|
|
languagesFile
|
|
|
|
)
|
2023-04-25 11:01:25 +00:00
|
|
|
|
|
|
|
// main.ts
|
|
|
|
|
|
|
|
const defaultTranslation = await readJsonIfExists(join(sourceFolderPath, 'main.json'))!
|
|
|
|
const defaultTranslationFilePath = join(uiPath, 'defaultTranslation.ts')
|
|
|
|
const defaultTranslationFile = `
|
|
|
|
/** @internal */
|
|
|
|
export const DEFAULT_TRANSLATION = ${JSON.stringify(defaultTranslation)}
|
|
|
|
`
|
2023-05-09 16:08:38 +00:00
|
|
|
await writeCodeFile(
|
|
|
|
'scripts/refresh-assets.ts',
|
|
|
|
'typescript',
|
|
|
|
defaultTranslationFilePath,
|
|
|
|
defaultTranslationFile
|
|
|
|
)
|
2023-04-25 11:01:25 +00:00
|
|
|
|
|
|
|
// translationKeys.ts
|
|
|
|
|
|
|
|
const translationKeys = Object.keys(defaultTranslation).map((key) => `'${key}'`)
|
2023-06-02 21:16:09 +00:00
|
|
|
const translationKeysFilePath = join(uiPath, 'TLUiTranslationKey.ts')
|
2023-04-25 11:01:25 +00:00
|
|
|
const translationKeysFile = `
|
|
|
|
/** @public */
|
2023-06-02 21:16:09 +00:00
|
|
|
export type TLUiTranslationKey = ${translationKeys.join(' | ')}
|
2023-04-25 11:01:25 +00:00
|
|
|
`
|
2023-05-09 16:08:38 +00:00
|
|
|
await writeCodeFile(
|
|
|
|
'scripts/refresh-assets.ts',
|
|
|
|
'typescript',
|
|
|
|
translationKeysFilePath,
|
|
|
|
translationKeysFile
|
|
|
|
)
|
2023-04-25 11:01:25 +00:00
|
|
|
|
|
|
|
// add to the asset declaration file
|
|
|
|
for (const item of itemsToCopy) {
|
|
|
|
const name = item.replace(extension, '')
|
2023-05-05 13:10:36 +00:00
|
|
|
collectedAssetUrls.translations[name] = `${folderName}/${item}`
|
2023-04-25 11:01:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-05 13:10:36 +00:00
|
|
|
// 4. ASSET DECLARATION FILES
|
|
|
|
async function writeUrlBasedAssetDeclarationFile() {
|
2024-01-16 14:38:05 +00:00
|
|
|
const codeFilePath = join(REPO_ROOT, 'packages', 'assets', 'urls.js')
|
2023-06-09 11:43:01 +00:00
|
|
|
const codeFile = `
|
2023-04-25 11:01:25 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
2023-05-09 16:08:38 +00:00
|
|
|
/// <reference path="./modules.d.ts" />
|
2023-06-09 11:43:01 +00:00
|
|
|
import { formatAssetUrl } from './utils.js'
|
2023-05-09 16:08:38 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {AssetUrlOptions} [opts]
|
|
|
|
* @public
|
|
|
|
*/
|
|
|
|
export function getAssetUrlsByMetaUrl(opts) {
|
2023-04-25 11:01:25 +00:00
|
|
|
return {
|
2023-05-05 13:10:36 +00:00
|
|
|
${Object.entries(collectedAssetUrls)
|
2023-04-25 11:01:25 +00:00
|
|
|
.flatMap(([type, assets]) => [
|
|
|
|
`${type}: {`,
|
|
|
|
...Object.entries(assets).map(
|
2023-05-05 13:10:36 +00:00
|
|
|
([name, href]) =>
|
|
|
|
`${JSON.stringify(name)}: formatAssetUrl(new URL(${JSON.stringify(
|
2023-05-09 16:08:38 +00:00
|
|
|
'./' + href
|
2023-05-05 13:10:36 +00:00
|
|
|
)}, import.meta.url).href, opts),`
|
2023-04-25 11:01:25 +00:00
|
|
|
),
|
|
|
|
'},',
|
|
|
|
])
|
|
|
|
.join('\n')}
|
2023-05-09 16:08:38 +00:00
|
|
|
}
|
2023-04-25 11:01:25 +00:00
|
|
|
}
|
|
|
|
`
|
|
|
|
|
2023-06-09 11:43:01 +00:00
|
|
|
await writeCodeFile('scripts/refresh-assets.ts', 'javascript', codeFilePath, codeFile)
|
2023-04-25 11:01:25 +00:00
|
|
|
}
|
2023-06-09 11:43:01 +00:00
|
|
|
|
2024-01-19 15:31:01 +00:00
|
|
|
async function writeImportBasedAssetDeclarationFile(
|
|
|
|
importSuffix: string,
|
|
|
|
fileName: string
|
|
|
|
): Promise<void> {
|
2023-05-05 13:10:36 +00:00
|
|
|
let imports = `
|
|
|
|
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
2023-05-09 16:08:38 +00:00
|
|
|
/// <reference path="./modules.d.ts" />
|
2023-06-09 11:43:01 +00:00
|
|
|
import { formatAssetUrl } from './utils.js'
|
|
|
|
|
2023-05-05 13:10:36 +00:00
|
|
|
`
|
|
|
|
|
|
|
|
let declarations = `
|
2023-05-09 16:08:38 +00:00
|
|
|
/**
|
|
|
|
* @param {AssetUrlOptions} [opts]
|
|
|
|
* @public
|
|
|
|
*/
|
|
|
|
export function getAssetUrlsByImport(opts) {
|
2023-05-05 13:10:36 +00:00
|
|
|
return {
|
|
|
|
`
|
|
|
|
|
|
|
|
for (const [type, assets] of Object.entries(collectedAssetUrls)) {
|
|
|
|
declarations += `${type}: {\n`
|
|
|
|
for (const [name, href] of Object.entries(assets)) {
|
|
|
|
const variableName = `${type}_${name}`
|
|
|
|
.replace(/[^a-zA-Z0-9_]/g, '_')
|
|
|
|
.replace(/_+/g, '_')
|
|
|
|
.replace(/_(.)/g, (_, letter) => letter.toUpperCase())
|
2024-01-19 15:31:01 +00:00
|
|
|
imports += `import ${variableName} from ${JSON.stringify('./' + href + importSuffix)};\n`
|
2023-05-05 13:10:36 +00:00
|
|
|
declarations += `${JSON.stringify(name)}: formatAssetUrl(${variableName}, opts),\n`
|
|
|
|
}
|
|
|
|
declarations += '},\n'
|
|
|
|
}
|
|
|
|
|
|
|
|
declarations += `
|
2023-05-09 16:08:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
2024-01-19 15:31:01 +00:00
|
|
|
const codeFilePath = join(REPO_ROOT, 'packages', 'assets', fileName)
|
2023-05-09 16:08:38 +00:00
|
|
|
await writeCodeFile(
|
|
|
|
'scripts/refresh-assets.ts',
|
|
|
|
'javascript',
|
2023-06-09 11:43:01 +00:00
|
|
|
codeFilePath,
|
2023-05-09 16:08:38 +00:00
|
|
|
imports + declarations
|
|
|
|
)
|
2023-06-09 11:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async function writeSelfHostedAssetDeclarationFile(): Promise<void> {
|
2024-01-16 14:38:05 +00:00
|
|
|
const codeFilePath = join(REPO_ROOT, 'packages', 'assets', 'selfHosted.js')
|
2023-06-09 11:43:01 +00:00
|
|
|
const codeFile = `
|
|
|
|
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
|
|
|
|
/// <reference path="./modules.d.ts" />
|
|
|
|
import { formatAssetUrl } from './utils.js'
|
2023-05-09 16:08:38 +00:00
|
|
|
|
2023-06-09 11:43:01 +00:00
|
|
|
/**
|
|
|
|
* @param {AssetUrlOptions} [opts]
|
|
|
|
* @public
|
|
|
|
*/
|
|
|
|
export function getAssetUrls(opts) {
|
|
|
|
return {
|
|
|
|
${Object.entries(collectedAssetUrls)
|
|
|
|
.flatMap(([type, assets]) => [
|
|
|
|
`${type}: {`,
|
|
|
|
...Object.entries(assets).map(
|
|
|
|
([name, href]) =>
|
|
|
|
`${JSON.stringify(name)}: formatAssetUrl(${JSON.stringify('./' + href)}, opts),`
|
|
|
|
),
|
|
|
|
'},',
|
|
|
|
])
|
|
|
|
.join('\n')}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`
|
|
|
|
|
|
|
|
await writeCodeFile('scripts/refresh-assets.ts', 'javascript', codeFilePath, codeFile)
|
2023-05-09 16:08:38 +00:00
|
|
|
}
|
|
|
|
|
2023-06-09 11:43:01 +00:00
|
|
|
async function writeAssetDeclarationDTSFile() {
|
2023-05-09 16:08:38 +00:00
|
|
|
let dts = `
|
2023-06-09 11:43:01 +00:00
|
|
|
export type AssetUrl = string | { src: string }
|
|
|
|
export type AssetUrlOptions = { baseUrl?: string } | ((assetUrl: string) => string)
|
|
|
|
export type AssetUrls = {
|
2023-05-09 16:08:38 +00:00
|
|
|
`
|
|
|
|
|
|
|
|
for (const [type, assets] of Object.entries(collectedAssetUrls)) {
|
|
|
|
dts += `${type}: {\n`
|
|
|
|
for (const name of Object.keys(assets)) {
|
|
|
|
dts += `${JSON.stringify(name)}: string,\n`
|
|
|
|
}
|
|
|
|
dts += '},\n'
|
|
|
|
}
|
|
|
|
|
|
|
|
dts += `
|
2023-05-05 13:10:36 +00:00
|
|
|
}
|
|
|
|
`
|
2023-04-25 11:01:25 +00:00
|
|
|
|
2024-01-16 14:38:05 +00:00
|
|
|
const assetDeclarationFilePath = join(REPO_ROOT, 'packages', 'assets', 'types.d.ts')
|
2023-05-09 16:08:38 +00:00
|
|
|
await writeCodeFile('scripts/refresh-assets.ts', 'typescript', assetDeclarationFilePath, dts)
|
2023-04-25 11:01:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// --- RUN
|
|
|
|
async function main() {
|
2023-06-01 18:01:49 +00:00
|
|
|
nicelog('Copying icons...')
|
2023-04-25 11:01:25 +00:00
|
|
|
await copyIcons()
|
2023-06-01 18:01:49 +00:00
|
|
|
nicelog('Copying embed icons...')
|
2023-04-25 11:01:25 +00:00
|
|
|
await copyEmbedIcons()
|
2023-06-01 18:01:49 +00:00
|
|
|
nicelog('Copying fonts...')
|
2023-04-25 11:01:25 +00:00
|
|
|
await copyFonts()
|
2023-06-01 18:01:49 +00:00
|
|
|
nicelog('Copying translations...')
|
2023-04-25 11:01:25 +00:00
|
|
|
await copyTranslations()
|
2023-06-01 18:01:49 +00:00
|
|
|
nicelog('Writing asset declaration file...')
|
2023-06-09 11:43:01 +00:00
|
|
|
await writeAssetDeclarationDTSFile()
|
2023-05-05 13:10:36 +00:00
|
|
|
await writeUrlBasedAssetDeclarationFile()
|
2024-01-19 15:31:01 +00:00
|
|
|
await writeImportBasedAssetDeclarationFile('', 'imports.js')
|
|
|
|
await writeImportBasedAssetDeclarationFile('?url', 'imports.vite.js')
|
2023-06-09 11:43:01 +00:00
|
|
|
await writeSelfHostedAssetDeclarationFile()
|
2023-06-01 18:01:49 +00:00
|
|
|
nicelog('Done!')
|
2023-04-25 11:01:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
main()
|