Compare commits

..

43 Commits

Author SHA1 Message Date
hamid zarghami 677c62e6eb fix extra light weight
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-11 09:39:03 +03:30
hamid zarghami e0eb29488a position x and y in line 2026-07-11 09:31:40 +03:30
hamid zarghami ae3787241a object box smaller 2026-07-11 09:21:13 +03:30
hamid zarghami 9e105606a3 fix blur in viewer 2026-07-11 09:10:41 +03:30
hamid zarghami c6bb275d05 fix order in blur layers + fix aligment 2026-07-11 09:05:13 +03:30
hamid zarghami 4273e899ca cursor ignore
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-08 16:44:46 +03:30
hamid zarghami 0361e05acb blur
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-08 16:42:55 +03:30
hamid zarghami 33cce93064 bg opcity
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-08 15:50:21 +03:30
hamid zarghami a2a591420c color opacity
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-08 09:21:41 +03:30
hamid zarghami 3c764a1652 spinner to loading page compeletely
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-05 16:26:37 +03:30
hamid zarghami 954ad48486 ankle gredient 2026-07-05 16:18:57 +03:30
hamid zarghami 368cace143 border radius for all shape 2026-07-05 15:52:39 +03:30
hamid zarghami 46926c66e7 blue
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-04 14:51:24 +03:30
hamid zarghami a448ff10de rtl in mobile 2026-07-04 14:45:44 +03:30
hamid zarghami 80a92ea4c4 fix in mobile 2026-07-04 14:43:51 +03:30
hamid zarghami 63a774c4af fix repeat animation 2026-07-04 14:21:27 +03:30
hamid zarghami 1ed198ca69 add max width in text
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-02 12:23:58 +03:30
hamid zarghami d94bf77522 background video 2026-07-02 12:08:29 +03:30
hamid zarghami 5e314bb581 add skill
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 16:54:06 +03:30
hamid zarghami 0391513928 next and prev
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 16:30:23 +03:30
hamid zarghami 22d15f9a13 progressbar uploading
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 16:27:21 +03:30
hamid zarghami bbb797cc62 border z-index than paper 2026-07-01 16:21:43 +03:30
hamid zarghami 4af7181384 fix animation 2026-07-01 16:17:03 +03:30
hamid zarghami cda1b5b5bd fix viewer in even pages
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 15:11:47 +03:30
hamid zarghami 2b4fd31ea2 fix diffrent size in editor and viewer
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 11:53:30 +03:30
hamid zarghami 168af3bf95 pages video fix 2026-07-01 11:23:11 +03:30
hamid zarghami 0bef54c51c pages list in editor 2026-07-01 11:20:55 +03:30
hamid zarghami 85ba8e4261 magnifier
deploy to danak / build_and_deploy (push) Has been cancelled
2026-07-01 11:17:08 +03:30
hamid zarghami 39e18c3331 RTL Trick
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-22 16:44:00 +03:30
hamid zarghami ca02a621da paint
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-20 15:32:02 +03:30
hamid zarghami b13a46ec65 auto save fix
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-20 12:59:39 +03:30
hamid zarghami e93ab38b05 mask 2026-06-20 12:19:23 +03:30
hamid zarghami 052b737653 change design alignmentsetting 2026-06-20 11:35:37 +03:30
hamid zarghami b8de25e9d1 fix big size image
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-15 16:40:08 +03:30
hamid zarghami 8b194fd7cd change icon
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-15 14:15:57 +03:30
hamid zarghami b7ffb2b857 fonts
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-15 09:35:24 +03:30
hamid zarghami c6d1097a30 move custum shape to shapes 2026-06-14 12:30:24 +03:30
hamid zarghami 494a6a53fc move pages 2026-06-14 11:48:55 +03:30
hamid zarghami ebb2092ec1 fix bug custom shape 2026-06-13 16:46:37 +03:30
hamid zarghami 9447500725 fix custom shape in viewer 2026-06-13 16:31:24 +03:30
hamid zarghami 46f5389036 remove line and peykan from sidebar and added to shape 2026-06-13 16:26:52 +03:30
hamid zarghami f9113ef9c8 costum shape 2026-06-13 16:22:46 +03:30
hamid zarghami e6fc300fba audio name
deploy to danak / build_and_deploy (push) Has been cancelled
2026-06-13 15:43:30 +03:30
213 changed files with 7116 additions and 1354 deletions
+116
View File
@@ -0,0 +1,116 @@
---
name: dpage-editor
description: Guides development in the dpage-editor React/Konva catalogue editor and HTML flip-book viewer. Use when editing editor tools, viewer rendering, Zustand store, catalogue autosave, entrance animations, masks, or any code under src/pages/editor or src/pages/viewer.
---
# dpage-editor
## Stack
- React 19 + TypeScript + Vite
- Canvas editor: **Konva** / **react-konva**
- Viewer: **react-pageflip** (HTML/CSS, not Konva)
- State: **Zustand** (`editorStore`)
- Data: **TanStack Query** + axios services
- Styling: **Tailwind CSS 4**, `clx()` from `@/helpers/utils`
- i18n: react-i18next (Persian UI)
## Architecture
| Area | Path | Role |
|------|------|------|
| Editor page | `src/pages/editor/Editor.tsx` | Loads catalogue, autosave, Konva lifecycle |
| Editor store | `src/pages/editor/store/editorStore.ts` | Pages, objects, undo, selection |
| Object types | `src/pages/editor/store/editorStore.types.ts` | `EditorObject`, `ToolType`, animations |
| Canvas | `src/pages/editor/components/canvas/` | Layers, drawing, transform, snap |
| Tools (Konva) | `src/pages/editor/components/tools/` | One component per shape/media type |
| Sidebar | `src/pages/editor/components/sidebar/` | ToolsBar, settings, instructions |
| Viewer | `src/pages/viewer/` | Flip-book, entrance animations, magnifier |
| Book render | `src/pages/viewer/components/BookPage.tsx` | HTML mirror of `EditorObject` |
| Catalogue API | `src/pages/catalogue/hooks/useCatalogueData.ts` | Load/save `content` JSON |
**Source of truth:** `EditorObject[]` per page, serialized into catalogue `content`. Editor and viewer must stay in sync.
## Critical conventions
### Konva text rendering
In `Editor.tsx`, `Konva.legacyTextRendering = true` is required. Konva 10's new text baseline breaks transformer bounds for Persian/Latin text. Do not remove without fixing text measurement.
### Store sync
`objects` and `pages[currentPageId].objects` must stay synced. Use existing helpers (`withSyncedCurrentPageObjects`, store actions) — never update one without the other.
### IDs and cloning
- Use `createScopedId` / helpers in `editorStore.helpers.ts` for new IDs.
- Undo history uses `structuredClone` on object lists; new fields on `EditorObject` must be JSON-serializable.
### Path alias
Use `@/` imports (e.g. `@/pages/editor/store/editorStore`).
## Adding or changing a tool type
Checklist — touch all relevant layers:
1. **`ToolType`** in `editorStore.types.ts` — add union member + fields on `EditorObject` if needed.
2. **Konva shape**`src/pages/editor/components/tools/<Name>Shape.tsx`, export from `tools/index.ts`.
3. **`ObjectRenderer.tsx`** — `switch (obj.type)` case + props wiring.
4. **Sidebar**`ToolsBar.tsx`, `ToolInstructions.tsx`, optional `instructions/` + `settings/`.
5. **Creation defaults** — store action or drawing handler that sets initial `x`, `y`, `width`, `height`.
6. **Viewer**`BookPage.tsx` `renderObject` branch; reuse utils from `src/pages/editor/utils/` (gradient, fontFamily, textStyle, customShape).
7. **Entrance animation** (if applicable) — `entranceAnimations.css`, `entranceAnimationStyle.ts`, `useBookEntranceController.ts`.
Default tool prop pattern:
```typescript
type ShapeProps = {
obj: EditorObject;
isSelected: boolean;
transformerRef: React.RefObject<Konva.Transformer | null>;
onSelect: (id: string, node: Konva.Node, e?: Konva.KonvaEventObject<MouseEvent>) => void;
onUpdate: (id: string, updates: Partial<EditorObject>) => void;
draggable: boolean;
};
```
## Editor vs viewer
| Concern | Editor | Viewer |
|---------|--------|--------|
| Rendering | Konva nodes | HTML/CSS (`BookPage`) |
| Interaction | Select, transform, draw | Flip pages, links, autoplay |
| Scale | Stage zoom | `VIEWER_SCALE` + viewport hooks |
| Media | Full controls in sidebar | `staticMedia` option for thumbnails |
| RTL | Stage coordinates | `RTL_COVER_PAD_PAGE_ID` for odd page counts |
Viewer-specific logic belongs in `src/pages/viewer/hooks/` and `utils/`, not in editor components.
## Autosave (Editor.tsx)
- `useUpdateCatalog` debounces saves.
- On catalogue `id` change: `cancelPendingUpdate`, `resetEditor`, reload once per id (`loadedCatalogIdRef`).
- Skip first autosave after load (`skipNextAutosaveRef`).
## Code style for this repo
- Prefer extending existing components over new abstractions.
- Keep comments for non-obvious Konva/RTL/safari workarounds (see `BookViewer.tsx`, `Editor.tsx`).
- Match Persian UI strings in surrounding files.
- Minimize diff scope; do not refactor unrelated editor/viewer code.
- Run `npm run build` after substantive changes (strict TypeScript).
## Common pitfalls
- Adding an `EditorObject` field but forgetting viewer render → object invisible in preview.
- Transform commits: use `transformCommit.ts` patterns so scale/rotation persist correctly.
- Mask/group: check `groupId`, `maskId`, `isMask` in both editor layers and `maskStyle.ts`.
- Page background: editor `documentSettings` ↔ viewer `resolvePageBackground`.
- Fullscreen/viewer chrome: `isViewerPath` hides app header/sidebar in `MainRouter.tsx`.
## Key routes
- Editor: `/editor/:id`
- Viewer: `/viewer/:id` or `/viewer/:businessSlug/:slug`
- Catalogue list: see `src/config/Paths.ts`
+35
View File
@@ -0,0 +1,35 @@
# Dependencies
node_modules/
# Build outputs
dist/
dist-ssr/
build/
out/
# Caches
.cache/
.vite/
# Coverage
coverage/
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Environment / secrets
.env
.env.*
!.env.example
# Editor / IDE
.vscode/
!.vscode/extensions.json
.idea/
# OS files
.DS_Store
+147 -120
View File
@@ -23,6 +23,7 @@
"moment-jalaali": "^0.10.4", "moment-jalaali": "^0.10.4",
"page-flip": "^2.0.7", "page-flip": "^2.0.7",
"react": "^19.2.0", "react": "^19.2.0",
"react-colorful": "^5.7.0",
"react-dom": "^19.2.0", "react-dom": "^19.2.0",
"react-dropzone": "^14.3.8", "react-dropzone": "^14.3.8",
"react-i18next": "^16.3.0", "react-i18next": "^16.3.0",
@@ -54,13 +55,13 @@
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
"version": "7.27.1", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-validator-identifier": "^7.27.1", "@babel/helper-validator-identifier": "^7.29.7",
"js-tokens": "^4.0.0", "js-tokens": "^4.0.0",
"picocolors": "^1.1.1" "picocolors": "^1.1.1"
}, },
@@ -69,9 +70,9 @@
} }
}, },
"node_modules/@babel/compat-data": { "node_modules/@babel/compat-data": {
"version": "7.28.5", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
"integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -79,21 +80,21 @@
} }
}, },
"node_modules/@babel/core": { "node_modules/@babel/core": {
"version": "7.28.5", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.29.7",
"@babel/generator": "^7.28.5", "@babel/generator": "^7.29.7",
"@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-compilation-targets": "^7.29.7",
"@babel/helper-module-transforms": "^7.28.3", "@babel/helper-module-transforms": "^7.29.7",
"@babel/helpers": "^7.28.4", "@babel/helpers": "^7.29.7",
"@babel/parser": "^7.28.5", "@babel/parser": "^7.29.7",
"@babel/template": "^7.27.2", "@babel/template": "^7.29.7",
"@babel/traverse": "^7.28.5", "@babel/traverse": "^7.29.7",
"@babel/types": "^7.28.5", "@babel/types": "^7.29.7",
"@jridgewell/remapping": "^2.3.5", "@jridgewell/remapping": "^2.3.5",
"convert-source-map": "^2.0.0", "convert-source-map": "^2.0.0",
"debug": "^4.1.0", "debug": "^4.1.0",
@@ -110,14 +111,14 @@
} }
}, },
"node_modules/@babel/generator": { "node_modules/@babel/generator": {
"version": "7.28.5", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz",
"integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.28.5", "@babel/parser": "^7.29.7",
"@babel/types": "^7.28.5", "@babel/types": "^7.29.7",
"@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.28", "@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2" "jsesc": "^3.0.2"
@@ -127,14 +128,14 @@
} }
}, },
"node_modules/@babel/helper-compilation-targets": { "node_modules/@babel/helper-compilation-targets": {
"version": "7.27.2", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
"integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/compat-data": "^7.27.2", "@babel/compat-data": "^7.29.7",
"@babel/helper-validator-option": "^7.27.1", "@babel/helper-validator-option": "^7.29.7",
"browserslist": "^4.24.0", "browserslist": "^4.24.0",
"lru-cache": "^5.1.1", "lru-cache": "^5.1.1",
"semver": "^6.3.1" "semver": "^6.3.1"
@@ -144,9 +145,9 @@
} }
}, },
"node_modules/@babel/helper-globals": { "node_modules/@babel/helper-globals": {
"version": "7.28.0", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
"integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -154,29 +155,29 @@
} }
}, },
"node_modules/@babel/helper-module-imports": { "node_modules/@babel/helper-module-imports": {
"version": "7.27.1", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
"integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/traverse": "^7.27.1", "@babel/traverse": "^7.29.7",
"@babel/types": "^7.27.1" "@babel/types": "^7.29.7"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-module-transforms": { "node_modules/@babel/helper-module-transforms": {
"version": "7.28.3", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
"integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-module-imports": "^7.27.1", "@babel/helper-module-imports": "^7.29.7",
"@babel/helper-validator-identifier": "^7.27.1", "@babel/helper-validator-identifier": "^7.29.7",
"@babel/traverse": "^7.28.3" "@babel/traverse": "^7.29.7"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -196,9 +197,9 @@
} }
}, },
"node_modules/@babel/helper-string-parser": { "node_modules/@babel/helper-string-parser": {
"version": "7.27.1", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -206,9 +207,9 @@
} }
}, },
"node_modules/@babel/helper-validator-identifier": { "node_modules/@babel/helper-validator-identifier": {
"version": "7.28.5", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -216,9 +217,9 @@
} }
}, },
"node_modules/@babel/helper-validator-option": { "node_modules/@babel/helper-validator-option": {
"version": "7.27.1", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
"integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -226,27 +227,27 @@
} }
}, },
"node_modules/@babel/helpers": { "node_modules/@babel/helpers": {
"version": "7.28.4", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz",
"integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/template": "^7.27.2", "@babel/template": "^7.29.7",
"@babel/types": "^7.28.4" "@babel/types": "^7.29.7"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.28.5", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz",
"integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/types": "^7.28.5" "@babel/types": "^7.29.7"
}, },
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@@ -297,33 +298,33 @@
} }
}, },
"node_modules/@babel/template": { "node_modules/@babel/template": {
"version": "7.27.2", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
"integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.29.7",
"@babel/parser": "^7.27.2", "@babel/parser": "^7.29.7",
"@babel/types": "^7.27.1" "@babel/types": "^7.29.7"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/traverse": { "node_modules/@babel/traverse": {
"version": "7.28.5", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz",
"integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.29.7",
"@babel/generator": "^7.28.5", "@babel/generator": "^7.29.7",
"@babel/helper-globals": "^7.28.0", "@babel/helper-globals": "^7.29.7",
"@babel/parser": "^7.28.5", "@babel/parser": "^7.29.7",
"@babel/template": "^7.27.2", "@babel/template": "^7.29.7",
"@babel/types": "^7.28.5", "@babel/types": "^7.29.7",
"debug": "^4.3.1" "debug": "^4.3.1"
}, },
"engines": { "engines": {
@@ -331,14 +332,14 @@
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.28.5", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
"integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.27.1", "@babel/helper-string-parser": "^7.29.7",
"@babel/helper-validator-identifier": "^7.28.5" "@babel/helper-validator-identifier": "^7.29.7"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -2570,13 +2571,16 @@
} }
}, },
"node_modules/baseline-browser-mapping": { "node_modules/baseline-browser-mapping": {
"version": "2.8.25", "version": "2.10.38",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.25.tgz", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz",
"integrity": "sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==", "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
"baseline-browser-mapping": "dist/cli.js" "baseline-browser-mapping": "dist/cli.cjs"
},
"engines": {
"node": ">=6.0.0"
} }
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
@@ -2604,9 +2608,9 @@
} }
}, },
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.28.0", "version": "4.28.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz",
"integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -2624,11 +2628,11 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"baseline-browser-mapping": "^2.8.25", "baseline-browser-mapping": "^2.10.38",
"caniuse-lite": "^1.0.30001754", "caniuse-lite": "^1.0.30001799",
"electron-to-chromium": "^1.5.249", "electron-to-chromium": "^1.5.376",
"node-releases": "^2.0.27", "node-releases": "^2.0.48",
"update-browserslist-db": "^1.1.4" "update-browserslist-db": "^1.2.3"
}, },
"bin": { "bin": {
"browserslist": "cli.js" "browserslist": "cli.js"
@@ -2661,9 +2665,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001754", "version": "1.0.30001799",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz",
"integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==", "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -2875,9 +2879,9 @@
} }
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.250", "version": "1.5.376",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.250.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.376.tgz",
"integrity": "sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw==", "integrity": "sha512-cUVA7/RvbFTEuw/i3obUwDTRIXojaxkResf+ibByPFxjc6XK3VNtcQXV0NSbAlJ0FMjcJGgftVVB4Qo184EXvA==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@@ -3338,16 +3342,16 @@
} }
}, },
"node_modules/form-data": { "node_modules/form-data": {
"version": "4.0.5", "version": "4.0.6",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"asynckit": "^0.4.0", "asynckit": "^0.4.0",
"combined-stream": "^1.0.8", "combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0", "es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2", "hasown": "^2.0.4",
"mime-types": "^2.1.12" "mime-types": "^2.1.35"
}, },
"engines": { "engines": {
"node": ">= 6" "node": ">= 6"
@@ -3537,9 +3541,9 @@
} }
}, },
"node_modules/hasown": { "node_modules/hasown": {
"version": "2.0.2", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"function-bind": "^1.1.2" "function-bind": "^1.1.2"
@@ -3742,10 +3746,20 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/js-yaml": { "node_modules/js-yaml": {
"version": "4.1.1", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==",
"dev": true, "dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"argparse": "^2.0.1" "argparse": "^2.0.1"
@@ -4292,11 +4306,14 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/node-releases": { "node_modules/node-releases": {
"version": "2.0.27", "version": "2.0.48",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.48.tgz",
"integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "integrity": "sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT",
"engines": {
"node": ">=18"
}
}, },
"node_modules/object-assign": { "node_modules/object-assign": {
"version": "4.1.1", "version": "4.1.1",
@@ -4540,6 +4557,16 @@
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
} }
}, },
"node_modules/react-colorful": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.7.0.tgz",
"integrity": "sha512-fuesYIemttah97XmsIHmz4OORDHiSFzyc9HMAIrCHJou2jaRQmL8cFJ76K4zQhhj8jzwOBlOi4BaGTjjOZCfTg==",
"license": "MIT",
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/react-date-object": { "node_modules/react-date-object": {
"version": "2.1.9", "version": "2.1.9",
"resolved": "https://registry.npmjs.org/react-date-object/-/react-date-object-2.1.9.tgz", "resolved": "https://registry.npmjs.org/react-date-object/-/react-date-object-2.1.9.tgz",
@@ -5137,9 +5164,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/update-browserslist-db": { "node_modules/update-browserslist-db": {
"version": "1.1.4", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
"integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -5206,9 +5233,9 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "7.3.3", "version": "7.3.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.3.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.5.tgz",
"integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", "integrity": "sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"esbuild": "^0.27.0", "esbuild": "^0.27.0",
+1
View File
@@ -25,6 +25,7 @@
"moment-jalaali": "^0.10.4", "moment-jalaali": "^0.10.4",
"page-flip": "^2.0.7", "page-flip": "^2.0.7",
"react": "^19.2.0", "react": "^19.2.0",
"react-colorful": "^5.7.0",
"react-dom": "^19.2.0", "react-dom": "^19.2.0",
"react-dropzone": "^14.3.8", "react-dropzone": "^14.3.8",
"react-i18next": "^16.3.0", "react-i18next": "^16.3.0",
+398
View File
@@ -0,0 +1,398 @@
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.join(__dirname, "../src/assets/fonts/irancell/fonts-editor");
const OUT_JSON = path.join(ROOT, "fonts.json");
const OUT_CSS = path.join(ROOT, "fonts.css");
const WEIGHT_LABELS = {
100: "Thin",
200: "Extra Light",
300: "Light",
400: "Regular",
500: "Medium",
600: "Semi Bold",
700: "Bold",
800: "Extra Bold",
900: "Black",
};
/** @type {Array<{ id: string; label: string; cssFamily: string; category: "persian" | "english"; faces: Array<{ weight: number; src: string; format?: string }> }>} */
const FONT_FAMILIES = [
{
id: "irancell",
label: "ایرانسل",
cssFamily: "editor-irancell",
category: "persian",
defaultWeight: "300",
faces: [
{ weight: 200, src: "../irancell-extralight.ttf" },
{ weight: 300, src: "../irancell-light.ttf" },
{ weight: 600, src: "../irancell-bold.ttf" },
{ weight: 700, src: "../irancell-bold.ttf" },
],
},
{
id: "peyda",
label: "پیدا",
cssFamily: "editor-peyda",
category: "persian",
faces: [
{ weight: 100, src: "Persian Font/peyda/woff2/PeydaWeb-Thin.woff2", format: "woff2" },
{ weight: 200, src: "Persian Font/peyda/woff2/peydaWeb-extralight.woff2", format: "woff2" },
{ weight: 300, src: "Persian Font/peyda/woff2/peydaWeb-light.woff2", format: "woff2" },
{ weight: 400, src: "Persian Font/peyda/woff2/PeydaWeb-Regular.woff2", format: "woff2" },
{ weight: 500, src: "Persian Font/peyda/woff2/PeydaWeb-Medium.woff2", format: "woff2" },
{ weight: 600, src: "Persian Font/peyda/woff2/PeydaWeb-SemiBold.woff2", format: "woff2" },
{ weight: 700, src: "Persian Font/peyda/woff2/PeydaWeb-Bold.woff2", format: "woff2" },
{ weight: 800, src: "Persian Font/peyda/woff2/PeydaWeb-ExtraBold.woff2", format: "woff2" },
{ weight: 900, src: "Persian Font/peyda/woff2/PeydaWeb-Black.woff2", format: "woff2" },
],
},
{
id: "iransans-fanum",
label: "ایران‌سنس (اعداد فارسی)",
cssFamily: "editor-iransans-fanum",
category: "persian",
faces: [
{ weight: 200, src: "Persian Font/IRANSansWeb(FaNum)_UltraLight.ttf" },
{ weight: 300, src: "Persian Font/IRANSansWeb(FaNum)_Light.ttf" },
{ weight: 400, src: "Persian Font/IRANSansWeb(FaNum).ttf" },
{ weight: 500, src: "Persian Font/IRANSansWeb(FaNum)_Medium.ttf" },
{ weight: 700, src: "Persian Font/IRANSansWeb(FaNum)_Bold.ttf" },
],
},
{
id: "sahel",
label: "ساحل",
cssFamily: "editor-sahel",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/Sahel-VF.ttf" }],
},
{
id: "yekan",
label: "یکان",
cssFamily: "editor-yekan",
category: "persian",
faces: [
{ weight: 400, src: "Persian Font/Yekan.ttf" },
{ weight: 700, src: "Persian Font/BYekan.ttf" },
],
},
{
id: "btehran",
label: "تهران",
cssFamily: "editor-btehran",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BTehran.ttf" }],
},
{
id: "byagut",
label: "یاقوت",
cssFamily: "editor-byagut",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BYagut.ttf" }],
},
{
id: "byas",
label: "یاس",
cssFamily: "editor-byas",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BYas.ttf" }],
},
{
id: "bzar",
label: "زر",
cssFamily: "editor-bzar",
category: "persian",
faces: [{ weight: 700, src: "Persian Font/BZarBd.ttf" }],
},
{
id: "bkoodak",
label: "کودک",
cssFamily: "editor-bkoodak",
category: "persian",
faces: [{ weight: 700, src: "Persian Font/BKoodakBold.ttf" }],
},
{
id: "bbaran",
label: "باران",
cssFamily: "editor-bbaran",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BBaran.ttf" }],
},
{
id: "broya",
label: "رویا",
cssFamily: "editor-broya",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BRoya.ttf" }],
},
{
id: "bmahsa",
label: "مهسا",
cssFamily: "editor-bmahsa",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BMahsa.ttf" }],
},
{
id: "bmorvarid",
label: "مروارید",
cssFamily: "editor-bmorvarid",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BMorvarid.ttf" }],
},
{
id: "bbc-nassim",
label: "نسیم",
cssFamily: "editor-bbc-nassim",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/BBCNassim.ttf" }],
},
{
id: "far-titr",
label: "تیتر",
cssFamily: "editor-far-titr",
category: "persian",
faces: [{ weight: 400, src: "Persian Font/Far_TitrDF.ttf" }],
},
{
id: "roboto",
label: "Roboto",
cssFamily: "editor-roboto",
category: "english",
faces: [
{ weight: 100, src: "English Font/Roboto-Thin-webfont.ttf" },
{ weight: 300, src: "English Font/Roboto-Light-webfont.ttf" },
{ weight: 400, src: "English Font/Roboto-Regular-webfont.ttf" },
{ weight: 500, src: "English Font/Roboto-Medium-webfont.ttf" },
{ weight: 700, src: "English Font/Roboto-Bold-webfont.ttf" },
{ weight: 900, src: "English Font/Roboto-Black-webfont.ttf" },
],
},
{
id: "roboto-condensed",
label: "Roboto Condensed",
cssFamily: "editor-roboto-condensed",
category: "english",
faces: [
{ weight: 400, src: "English Font/Roboto-Condensed-webfont.ttf" },
{ weight: 700, src: "English Font/Roboto-BoldCondensed-webfont.ttf" },
],
},
{
id: "vollkorn",
label: "Vollkorn",
cssFamily: "editor-vollkorn",
category: "english",
faces: [
{ weight: 400, src: "English Font/Vollkorn-Regular.ttf" },
{ weight: 500, src: "English Font/Vollkorn-Medium.ttf" },
{ weight: 600, src: "English Font/Vollkorn-Semibold.ttf" },
{ weight: 700, src: "English Font/Vollkorn-Bold.ttf" },
],
},
{
id: "caviar-dreams",
label: "Caviar Dreams",
cssFamily: "editor-caviar-dreams",
category: "english",
faces: [
{ weight: 400, src: "English Font/CaviarDreams.ttf" },
{ weight: 700, src: "English Font/CaviarDreams_Bold.ttf" },
],
},
{
id: "raleway",
label: "Raleway",
cssFamily: "editor-raleway",
category: "english",
faces: [
{ weight: 200, src: "English Font/raleway-extralight-webfont.ttf" },
{ weight: 400, src: "English Font/raleway-regular-webfont.ttf" },
{ weight: 500, src: "English Font/raleway-medium-webfont.ttf" },
{ weight: 600, src: "English Font/raleway-semibold-webfont.ttf" },
{ weight: 700, src: "English Font/raleway-bold-webfont.ttf" },
{ weight: 800, src: "English Font/raleway-extrabold-webfont.ttf" },
],
},
{
id: "proxima-nova",
label: "Proxima Nova",
cssFamily: "editor-proxima-nova",
category: "english",
faces: [
{ weight: 300, src: "English Font/proximanova-light-webfont.ttf" },
{ weight: 400, src: "English Font/proximanova-reg-webfont.ttf" },
{ weight: 600, src: "English Font/proximanova-semibold-webfont.ttf" },
{ weight: 700, src: "English Font/proximanova-bold-webfont.ttf" },
{ weight: 800, src: "English Font/proximanova-extrabold-webfont.ttf" },
{ weight: 900, src: "English Font/proximanova-black-webfont.ttf" },
],
},
{
id: "proxima-nova-condensed",
label: "Proxima Nova Condensed",
cssFamily: "editor-proxima-nova-condensed",
category: "english",
faces: [
{ weight: 300, src: "English Font/proximanovacond-light-webfont.ttf" },
{ weight: 600, src: "English Font/proximanovacond-semiboldit-webfont.ttf" },
],
},
{
id: "din-pro",
label: "DIN Pro",
cssFamily: "editor-din-pro",
category: "english",
faces: [
{ weight: 400, src: "English Font/dinpro-regular.ttf" },
{ weight: 500, src: "English Font/dinpro-medium.ttf" },
{ weight: 700, src: "English Font/dinpro-bold.ttf" },
{ weight: 900, src: "English Font/dinpro-black.ttf" },
],
},
{
id: "din-alternate",
label: "DIN Alternate",
cssFamily: "editor-din-alternate",
category: "english",
faces: [
{ weight: 300, src: "English Font/din-lightalternate.ttf" },
{ weight: 400, src: "English Font/din-regularalternate.ttf" },
{ weight: 500, src: "English Font/din-mediumalternate.ttf" },
{ weight: 700, src: "English Font/din-boldalternate.ttf" },
{ weight: 900, src: "English Font/din-blackalternate.ttf" },
],
},
{
id: "abril-fatface",
label: "Abril Fatface",
cssFamily: "editor-abril-fatface",
category: "english",
faces: [{ weight: 400, src: "English Font/AbrilFatface-Regular.otf", format: "opentype" }],
},
{
id: "anton",
label: "Anton",
cssFamily: "editor-anton",
category: "english",
faces: [{ weight: 400, src: "English Font/Anton.ttf" }],
},
{
id: "bebas-neue",
label: "Bebas Neue",
cssFamily: "editor-bebas-neue",
category: "english",
faces: [{ weight: 400, src: "English Font/Bebas Neue.ttf" }],
},
{
id: "kepler-std",
label: "Kepler Std",
cssFamily: "editor-kepler-std",
category: "english",
faces: [{ weight: 400, src: "English Font/kepler-std.ttf" }],
},
{
id: "playfair-display",
label: "Playfair Display",
cssFamily: "editor-playfair-display",
category: "english",
faces: [{ weight: 900, src: "English Font/playfairdisplay-black-webfont.ttf" }],
},
];
function encodeUrlSegment(segment) {
return segment
.split("/")
.map((part) => encodeURIComponent(part))
.join("/");
}
function buildCss(families) {
const blocks = families.flatMap((family) =>
family.faces.map((face) => {
const formatSuffix = face.format ? ` format("${face.format}")` : "";
const url = encodeUrlSegment(face.src);
return `@font-face {
font-family: "${family.cssFamily}";
font-style: normal;
font-weight: ${face.weight};
src: url("${url}")${formatSuffix};
}`;
}),
);
return `/* Auto-generated by scripts/generate-editor-fonts.mjs — do not edit manually */\n\n${blocks.join("\n\n")}\n`;
}
function buildJson(families) {
const fonts = families.map((family) => {
const srcToFace = new Map();
for (const face of family.faces) {
const existing = srcToFace.get(face.src);
if (!existing || face.weight > existing.weight) {
srcToFace.set(face.src, face);
}
}
const uniqueWeightFaces = [...srcToFace.values()].sort(
(a, b) => a.weight - b.weight,
);
const uniqueWeights = uniqueWeightFaces.map((f) => f.weight);
return {
id: family.id,
label: family.label,
cssFamily: family.cssFamily,
category: family.category,
defaultWeight: family.defaultWeight
? String(family.defaultWeight)
: uniqueWeights.includes(400)
? "400"
: String(uniqueWeights[0]),
weights: uniqueWeightFaces.map((face) => ({
value: String(face.weight),
label: WEIGHT_LABELS[face.weight] || String(face.weight),
})),
};
});
return {
version: 1,
fonts,
};
}
function verifySources(families) {
const missing = [];
for (const family of families) {
for (const face of family.faces) {
const resolved = face.src.startsWith("../")
? path.join(ROOT, face.src)
: path.join(ROOT, face.src);
if (!fs.existsSync(resolved)) {
missing.push(resolved);
}
}
}
if (missing.length) {
console.error("Missing font files:\n" + missing.map((m) => ` - ${m}`).join("\n"));
process.exit(1);
}
}
verifySources(FONT_FAMILIES);
const json = buildJson(FONT_FAMILIES);
const css = buildCss(FONT_FAMILIES);
fs.writeFileSync(OUT_JSON, JSON.stringify(json, null, 2) + "\n");
fs.writeFileSync(OUT_CSS, css);
console.log(`Wrote ${OUT_JSON}`);
console.log(`Wrote ${OUT_CSS}`);
console.log(`Fonts: ${json.fonts.length}`);
+1
View File
@@ -7,6 +7,7 @@ import { I18nextProvider } from "react-i18next";
import "react-multi-date-picker/styles/layouts/mobile.css"; import "react-multi-date-picker/styles/layouts/mobile.css";
import { BrowserRouter } from "react-router-dom"; import { BrowserRouter } from "react-router-dom";
import "./assets/fonts/irancell/style.css"; import "./assets/fonts/irancell/style.css";
import "./assets/fonts/irancell/fonts-editor/fonts.css";
import ToastContainer from "./components/Toast"; import ToastContainer from "./components/Toast";
import MainRouter from "./router/MainRouter"; import MainRouter from "./router/MainRouter";
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More