diff --git a/.eslintignore b/.eslintignore index 1b4baef2f..b4bfcf8de 100644 --- a/.eslintignore +++ b/.eslintignore @@ -12,3 +12,4 @@ static web-static public packages/frontend/i18n/src/i18n-generated.ts +packages/frontend/templates/edgeless-templates.gen.ts diff --git a/.gitignore b/.gitignore index 77f2822fc..719698cee 100644 --- a/.gitignore +++ b/.gitignore @@ -79,3 +79,6 @@ lib affine.db apps/web/next-routes.conf .nx + +packages/frontend/templates/edgeless +packages/frontend/core/public/static/templates diff --git a/.prettierignore b/.prettierignore index c516bb987..6a6737e63 100644 --- a/.prettierignore +++ b/.prettierignore @@ -16,6 +16,7 @@ packages/frontend/i18n/src/i18n-generated.ts packages/frontend/graphql/src/graphql/index.ts tests/affine-legacy/**/static .yarnrc.yml +packages/frontend/templates/edgeless-templates.gen.ts packages/frontend/templates/templates.gen.ts packages/frontend/templates/onboarding diff --git a/packages/frontend/core/src/bootstrap/edgeless-template.ts b/packages/frontend/core/src/bootstrap/edgeless-template.ts new file mode 100644 index 000000000..5bd085e10 --- /dev/null +++ b/packages/frontend/core/src/bootstrap/edgeless-template.ts @@ -0,0 +1,7 @@ +import { builtInTemplates } from '@affine/templates/edgeless'; +import { + EdgelessTemplatePanel, + type TemplateManager, +} from '@blocksuite/blocks'; + +EdgelessTemplatePanel.templates.extend(builtInTemplates as TemplateManager); diff --git a/packages/frontend/core/src/bootstrap/setup.ts b/packages/frontend/core/src/bootstrap/setup.ts index 4129e608f..59dbfe7eb 100644 --- a/packages/frontend/core/src/bootstrap/setup.ts +++ b/packages/frontend/core/src/bootstrap/setup.ts @@ -1,4 +1,5 @@ import './register-blocksuite-components'; +import './edgeless-template'; import { setupGlobal } from '@affine/env/global'; import * as Sentry from '@sentry/react'; diff --git a/packages/frontend/templates/build-edgeless.mjs b/packages/frontend/templates/build-edgeless.mjs new file mode 100644 index 000000000..46294979d --- /dev/null +++ b/packages/frontend/templates/build-edgeless.mjs @@ -0,0 +1,314 @@ +import { existsSync, mkdirSync, readFileSync, statSync } from 'node:fs'; +import fs from 'node:fs/promises'; +import path, { join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import JSZip from 'jszip'; + +const __dirname = join(fileURLToPath(import.meta.url), '..'); +const ZIP_PATH = join(__dirname, './edgeless-snapshot'); +const ASSETS_PREFIX = `/static/templates`; +const ASSETS_PATH = join(__dirname, '../core/public/', ASSETS_PREFIX); +const TEMPLATE_PATH = join(__dirname, './edgeless'); + +const getZipFilesInCategroies = () => { + return fs.readdir(ZIP_PATH).then(folders => { + return Promise.all( + folders + .filter(folder => { + return statSync(join(ZIP_PATH, folder)).isDirectory(); + }) + .map(async folder => { + const files = await fs.readdir(join(ZIP_PATH, folder)); + return { + category: folder, + files: files.filter(file => path.extname(file) === '.zip'), + }; + }) + ); + }); +}; + +const setupFolder = async () => { + if (!existsSync(ASSETS_PATH)) { + mkdirSync(ASSETS_PATH); + } + + if (!existsSync(TEMPLATE_PATH)) { + mkdirSync(TEMPLATE_PATH); + } +}; + +/** + * @typedef Block + * @type {object} + * @property {string} flavour + * @property {Array | undefined} children + * @property {object} props + * @property {string} props.sourceId + */ + +/** + * @param {Block} block + */ +const convertSourceId = (block, assetsExtMap) => { + if (block.props?.sourceId) { + const extname = assetsExtMap[block.props.sourceId]; + if (!extname) { + console.warn(`No extname found for ${block.props.sourceId}`); + } + block.props.sourceId = `${ASSETS_PREFIX}/${block.props.sourceId}${ + extname ?? '' + }`; + } + + if (block.children && Array.isArray(block.children)) { + block.children.forEach(block => convertSourceId(block, assetsExtMap)); + } +}; + +const parseSnapshot = async () => { + const filesInCategroies = await getZipFilesInCategroies(); + await setupFolder(); + /** + * @type {Array<{ category: string, templates: string[] }}>} + */ + const templatesInCategory = []; + + for (let cate of filesInCategroies) { + const templates = []; + const assetsExtentionMap = {}; + + for (let file of cate.files) { + const templateName = path.basename(file, '.zip'); + const zip = new JSZip(); + const { files: unarchivedFiles } = await zip.loadAsync( + readFileSync(join(ZIP_PATH, cate.category, file)) + ); + /** + * @type {Array} + */ + const assetsFiles = []; + /** + * @type {Array} + */ + const snapshotFiles = []; + + Object.entries(unarchivedFiles).forEach(([name, fileObj]) => { + if (name.includes('MACOSX') || name.includes('__MACOSX')) return; + + if (name.startsWith('assets/') && !fileObj.dir) { + assetsFiles.push(fileObj); + return; + } + + if (name.endsWith('.snapshot.json')) { + snapshotFiles.push(fileObj); + return; + } + }); + + await Promise.all( + assetsFiles.map(async file => { + const blob = await file.async('blob'); + const arrayBuffer = await blob.arrayBuffer(); + const buffer = Buffer.from(arrayBuffer, 'binary'); + const extname = path.extname(file.name); + + assetsExtentionMap[ + file.name.replace('assets/', '').replace(extname, '') + ] = extname; + + await fs.writeFile( + join(ASSETS_PATH, file.name.replace('assets/', '')), + buffer + ); + }) + ); + + await Promise.all( + snapshotFiles.map(async snapshot => { + const json = await snapshot.async('text'); + const snapshotContent = JSON.parse(json); + const previewPath = join( + ZIP_PATH, + cate.category, + `${templateName}.svg` + ); + let previewContent = ''; + + if (existsSync(previewPath)) { + const previewFile = readFileSync(previewPath, 'utf-8'); + previewContent = previewFile + .replace(/\n/g, '') + .replace(/\s+/g, ' ') + .replace('fill="white"', 'fill="currentColor"'); + } else { + console.warn(`No preview found for ${templateName}`); + } + + convertSourceId(snapshotContent.blocks, assetsExtentionMap); + + const template = { + name: templateName, + type: 'template', + preview: previewContent, + content: snapshotContent, + }; + + await fs.writeFile( + join(join(TEMPLATE_PATH, `${templateName}.json`)), + JSON.stringify(template, undefined, 2) + ); + + templates.push(templateName); + }) + ); + } + + templatesInCategory.push({ + category: cate.category, + templates, + }); + } + + return templatesInCategory; +}; + +function numberToWords(n) { + const ones = [ + 'Zero', + 'One', + 'Two', + 'Three', + 'Four', + 'Five', + 'Six', + 'Seven', + 'Eight', + 'Nine', + ]; + + if (n < 10) { + return ones[n]; + } else { + throw new Error(`Not implemented: ${n}`); + } +} + +const camelCaseNumber = variable => { + const words = variable.split(' '); + return words + .map(word => word.charAt(0).toUpperCase() + word.slice(1)) + .join(''); +}; + +const toVariableName = name => { + const converted = Array.from(name).reduce((pre, char) => { + if (char >= '0' && char <= '9') { + return pre + numberToWords(char - '0'); + } + + return pre + char; + }, ''); + + return camelCaseNumber(converted); +}; + +/** + * + * @param {Array<{category: string, templates: string[]}} templatesInGroup + */ +const buildScript = async templatesInGroup => { + const templates = []; + const templateVariableMap = {}; + + templatesInGroup.forEach(group => { + group.templates.forEach(template => { + templates.push(template); + templateVariableMap[template] = toVariableName(template); + }); + }); + + const importStatements = templates + .map(template => { + return `import ${toVariableName( + template + )} from './edgeless/${template}.json';`; + }) + .join('\n'); + const templatesDeclaration = templatesInGroup.map(group => { + return `'${group.category}': [ + ${group.templates + .map(template => templateVariableMap[template]) + .join(',\n ')} + ]`; + }); + + const code = `${importStatements} + +const templates = { + ${templatesDeclaration.join(',\n ')} +} + +function lcs(text1: string, text2: string) { + const dp: number[][] = Array.from({ length: text1.length + 1 }) + .fill(null) + .map(() => Array.from({length: text2.length + 1}).fill(0)); + + for (let i = 1; i <= text1.length; i++) { + for (let j = 1; j <= text2.length; j++) { + if (text1[i - 1] === text2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + + return dp[text1.length][text2.length]; +} + +export const builtInTemplates = { + list: async (category: string) => { + // @ts-expect-error type should be asserted when using + return templates[category] ?? [] + }, + + categories: async () => { + return Object.keys(templates) + }, + + search: async(query: string) => { + const candidates: unknown[] = []; + const cates = Object.keys(templates); + + query = query.toLowerCase(); + + for(let cate of cates) { + // @ts-expect-error type should be asserted when using + const templatesOfCate = templates[cate]; + + for(let temp of templatesOfCate) { + if(lcs(query, temp.name.toLowerCase()) === query.length) { + candidates.push(temp); + } + } + } + + return candidates; + }, +} +`; + + await fs.writeFile(join(__dirname, './edgeless-templates.gen.ts'), code, { + encoding: 'utf-8', + }); +}; + +async function main() { + const templatesInGroup = await parseSnapshot(); + await buildScript(templatesInGroup); +} + +main(); diff --git a/packages/frontend/templates/edgeless-snapshot/Brainstorming/5W2H.svg b/packages/frontend/templates/edgeless-snapshot/Brainstorming/5W2H.svg new file mode 100644 index 000000000..824f1ca65 --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Brainstorming/5W2H.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Brainstorming/5W2H.zip b/packages/frontend/templates/edgeless-snapshot/Brainstorming/5W2H.zip new file mode 100644 index 000000000..dd97c28fd Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Brainstorming/5W2H.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Brainstorming/Concept Map.svg b/packages/frontend/templates/edgeless-snapshot/Brainstorming/Concept Map.svg new file mode 100644 index 000000000..d920121e0 --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Brainstorming/Concept Map.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Brainstorming/Concept Map.zip b/packages/frontend/templates/edgeless-snapshot/Brainstorming/Concept Map.zip new file mode 100644 index 000000000..803f71174 Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Brainstorming/Concept Map.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Brainstorming/Flowchart.svg b/packages/frontend/templates/edgeless-snapshot/Brainstorming/Flowchart.svg new file mode 100644 index 000000000..c4569ffcc --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Brainstorming/Flowchart.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Brainstorming/Flowchart.zip b/packages/frontend/templates/edgeless-snapshot/Brainstorming/Flowchart.zip new file mode 100644 index 000000000..d55ae17dd Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Brainstorming/Flowchart.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Brainstorming/SMART.svg b/packages/frontend/templates/edgeless-snapshot/Brainstorming/SMART.svg new file mode 100644 index 000000000..f1662f7b3 --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Brainstorming/SMART.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Brainstorming/SMART.zip b/packages/frontend/templates/edgeless-snapshot/Brainstorming/SMART.zip new file mode 100644 index 000000000..ae60fe795 Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Brainstorming/SMART.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Brainstorming/SWOT.svg b/packages/frontend/templates/edgeless-snapshot/Brainstorming/SWOT.svg new file mode 100644 index 000000000..a23662171 --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Brainstorming/SWOT.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Brainstorming/SWOT.zip b/packages/frontend/templates/edgeless-snapshot/Brainstorming/SWOT.zip new file mode 100644 index 000000000..6317e6359 Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Brainstorming/SWOT.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Marketing/4P Marketing Matrix.svg b/packages/frontend/templates/edgeless-snapshot/Marketing/4P Marketing Matrix.svg new file mode 100644 index 000000000..8c85ca4f0 --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Marketing/4P Marketing Matrix.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Marketing/4P Marketing Matrix.zip b/packages/frontend/templates/edgeless-snapshot/Marketing/4P Marketing Matrix.zip new file mode 100644 index 000000000..30406e0fa Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Marketing/4P Marketing Matrix.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Marketing/Storyboard.svg b/packages/frontend/templates/edgeless-snapshot/Marketing/Storyboard.svg new file mode 100644 index 000000000..dab228b92 --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Marketing/Storyboard.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Marketing/Storyboard.zip b/packages/frontend/templates/edgeless-snapshot/Marketing/Storyboard.zip new file mode 100644 index 000000000..6cf0b9e1f Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Marketing/Storyboard.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Marketing/User Journey Map.svg b/packages/frontend/templates/edgeless-snapshot/Marketing/User Journey Map.svg new file mode 100644 index 000000000..a264216f3 --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Marketing/User Journey Map.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Marketing/User Journey Map.zip b/packages/frontend/templates/edgeless-snapshot/Marketing/User Journey Map.zip new file mode 100644 index 000000000..abf7fee3f Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Marketing/User Journey Map.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Presentation/Business Proposal.svg b/packages/frontend/templates/edgeless-snapshot/Presentation/Business Proposal.svg new file mode 100644 index 000000000..2fa6d5d84 --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Presentation/Business Proposal.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Presentation/Business Proposal.zip b/packages/frontend/templates/edgeless-snapshot/Presentation/Business Proposal.zip new file mode 100644 index 000000000..7bf271db4 Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Presentation/Business Proposal.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Presentation/Data Analysis.svg b/packages/frontend/templates/edgeless-snapshot/Presentation/Data Analysis.svg new file mode 100644 index 000000000..554277c6f --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Presentation/Data Analysis.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Presentation/Data Analysis.zip b/packages/frontend/templates/edgeless-snapshot/Presentation/Data Analysis.zip new file mode 100644 index 000000000..2b39d0b26 Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Presentation/Data Analysis.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Presentation/Simple Presentation.svg b/packages/frontend/templates/edgeless-snapshot/Presentation/Simple Presentation.svg new file mode 100644 index 000000000..c346c753b --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Presentation/Simple Presentation.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Presentation/Simple Presentation.zip b/packages/frontend/templates/edgeless-snapshot/Presentation/Simple Presentation.zip new file mode 100644 index 000000000..ac2fe4504 Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Presentation/Simple Presentation.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Project Management/Fishbone Diagram.svg b/packages/frontend/templates/edgeless-snapshot/Project Management/Fishbone Diagram.svg new file mode 100644 index 000000000..c6502864b --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Project Management/Fishbone Diagram.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Project Management/Fishbone Diagram.zip b/packages/frontend/templates/edgeless-snapshot/Project Management/Fishbone Diagram.zip new file mode 100644 index 000000000..e3b43f52f Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Project Management/Fishbone Diagram.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Project Management/Gantt Chart.svg b/packages/frontend/templates/edgeless-snapshot/Project Management/Gantt Chart.svg new file mode 100644 index 000000000..e6070908f --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Project Management/Gantt Chart.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Project Management/Gantt Chart.zip b/packages/frontend/templates/edgeless-snapshot/Project Management/Gantt Chart.zip new file mode 100644 index 000000000..06cde0727 Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Project Management/Gantt Chart.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Project Management/Monthly Calendar.svg b/packages/frontend/templates/edgeless-snapshot/Project Management/Monthly Calendar.svg new file mode 100644 index 000000000..921bf2787 --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Project Management/Monthly Calendar.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Project Management/Monthly Calendar.zip b/packages/frontend/templates/edgeless-snapshot/Project Management/Monthly Calendar.zip new file mode 100644 index 000000000..20f30ace9 Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Project Management/Monthly Calendar.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Project Management/Project Planning.svg b/packages/frontend/templates/edgeless-snapshot/Project Management/Project Planning.svg new file mode 100644 index 000000000..3ad873154 --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Project Management/Project Planning.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Project Management/Project Planning.zip b/packages/frontend/templates/edgeless-snapshot/Project Management/Project Planning.zip new file mode 100644 index 000000000..1fe22e6ed Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Project Management/Project Planning.zip differ diff --git a/packages/frontend/templates/edgeless-snapshot/Project Management/Project Tracking Kanban.svg b/packages/frontend/templates/edgeless-snapshot/Project Management/Project Tracking Kanban.svg new file mode 100644 index 000000000..258158131 --- /dev/null +++ b/packages/frontend/templates/edgeless-snapshot/Project Management/Project Tracking Kanban.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/frontend/templates/edgeless-snapshot/Project Management/Project Tracking Kanban.zip b/packages/frontend/templates/edgeless-snapshot/Project Management/Project Tracking Kanban.zip new file mode 100644 index 000000000..a2b3b0de0 Binary files /dev/null and b/packages/frontend/templates/edgeless-snapshot/Project Management/Project Tracking Kanban.zip differ diff --git a/packages/frontend/templates/edgeless-templates.gen.ts b/packages/frontend/templates/edgeless-templates.gen.ts new file mode 100644 index 000000000..adb9daa44 --- /dev/null +++ b/packages/frontend/templates/edgeless-templates.gen.ts @@ -0,0 +1,92 @@ +import FiveWTwoH from './edgeless/5W2H.json'; +import ConceptMap from './edgeless/Concept Map.json'; +import Flowchart from './edgeless/Flowchart.json'; +import SMART from './edgeless/SMART.json'; +import SWOT from './edgeless/SWOT.json'; +import FourPMarketingMatrix from './edgeless/4P Marketing Matrix.json'; +import Storyboard from './edgeless/Storyboard.json'; +import UserJourneyMap from './edgeless/User Journey Map.json'; +import BusinessProposal from './edgeless/Business Proposal.json'; +import DataAnalysis from './edgeless/Data Analysis.json'; +import SimplePresentation from './edgeless/Simple Presentation.json'; +import FishboneDiagram from './edgeless/Fishbone Diagram.json'; +import GanttChart from './edgeless/Gantt Chart.json'; +import MonthlyCalendar from './edgeless/Monthly Calendar.json'; +import ProjectPlanning from './edgeless/Project Planning.json'; +import ProjectTrackingKanban from './edgeless/Project Tracking Kanban.json'; + +const templates = { + 'Brainstorming': [ + FiveWTwoH, + ConceptMap, + Flowchart, + SMART, + SWOT + ], + 'Marketing': [ + FourPMarketingMatrix, + Storyboard, + UserJourneyMap + ], + 'Presentation': [ + BusinessProposal, + DataAnalysis, + SimplePresentation + ], + 'Project Management': [ + FishboneDiagram, + GanttChart, + MonthlyCalendar, + ProjectPlanning, + ProjectTrackingKanban + ] +} + +function lcs(text1: string, text2: string) { + const dp: number[][] = Array.from({ length: text1.length + 1 }) + .fill(null) + .map(() => Array.from({length: text2.length + 1}).fill(0)); + + for (let i = 1; i <= text1.length; i++) { + for (let j = 1; j <= text2.length; j++) { + if (text1[i - 1] === text2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + + return dp[text1.length][text2.length]; +} + +export const builtInTemplates = { + list: async (category: string) => { + // @ts-expect-error type should be asserted when using + return templates[category] ?? [] + }, + + categories: async () => { + return Object.keys(templates) + }, + + search: async(query: string) => { + const candidates: unknown[] = []; + const cates = Object.keys(templates); + + query = query.toLowerCase(); + + for(let cate of cates) { + // @ts-expect-error type should be asserted when using + const templatesOfCate = templates[cate]; + + for(let temp of templatesOfCate) { + if(lcs(query, temp.name.toLowerCase()) === query.length) { + candidates.push(temp); + } + } + } + + return candidates; + }, +} diff --git a/packages/frontend/templates/package.json b/packages/frontend/templates/package.json index 11c258a98..f79a42f5f 100644 --- a/packages/frontend/templates/package.json +++ b/packages/frontend/templates/package.json @@ -4,10 +4,14 @@ "sideEffect": false, "version": "0.12.0", "scripts": { - "postinstall": "node ./build.mjs" + "postinstall": "node ./build.mjs && node ./build-edgeless.mjs" }, "type": "module", "exports": { - ".": "./templates.gen.ts" + ".": "./templates.gen.ts", + "./edgeless": "./edgeless-templates.gen.ts" + }, + "devDependencies": { + "jszip": "^3.10.1" } } diff --git a/tools/cli/src/bin/dev-core.ts b/tools/cli/src/bin/dev-core.ts index c422ca967..a9432aca4 100644 --- a/tools/cli/src/bin/dev-core.ts +++ b/tools/cli/src/bin/dev-core.ts @@ -171,6 +171,14 @@ function awaitChildProcess(child: ChildProcess): Promise { } try { + await awaitChildProcess( + spawn('node', ['build-edgeless.mjs'], { + cwd: path.resolve(projectRoot, 'packages/frontend/templates'), + stdio: 'inherit', + shell: true, + env: process.env, + }) + ); // Start webpack await awaitChildProcess( spawn( diff --git a/yarn.lock b/yarn.lock index 2112bec7f..0c91d4553 100644 --- a/yarn.lock +++ b/yarn.lock @@ -790,6 +790,8 @@ __metadata: "@affine/templates@workspace:*, @affine/templates@workspace:packages/frontend/templates": version: 0.0.0-use.local resolution: "@affine/templates@workspace:packages/frontend/templates" + dependencies: + jszip: "npm:^3.10.1" languageName: unknown linkType: soft