doc-survival-kit 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Youssef MEDAGHRI-ALAOUI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,248 @@
1
+ # myTasks. myNotes. myLinks. & Diagrams !
2
+
3
+ > A three-column personal productivity dashboard, and a diagramming tool with zero dependencies, zero server, zero security compromises. Available in **French** and **English**.
4
+
5
+ ## Security — why this project can be used anywhere
6
+
7
+ This is one of the dashboard's greatest strengths. Here is why it poses **no risk** in a secure environment:
8
+
9
+ | Criterion | This project |
10
+ | ---------------- | ----------------------------------------------------------------------------- |
11
+ | Network requests | **None** — no CDN, no API, no tracking |
12
+ | External deps | **None** — plain HTML, CSS and Vanilla JavaScript only |
13
+ | Server required | **No** — opens directly via `file://` in the browser |
14
+ | Data sent | **Never** — everything stays on your machine (`localStorage` and local files) |
15
+ | Installation | **None** — no executable, no package manager, no admin rights |
16
+ | Auditable code | **Yes** — a handful of readable files, nothing minified or obfuscated |
17
+
18
+ > **In practice**: you can open this on any machine without internet access, or in any environment where installing tools or reaching external services is not possible. It makes no outbound connections, loads nothing from the outside, and stores your data only where you choose.
19
+
20
+ ---
21
+
22
+ ![Dashboard preview](mon_dashboard.png)
23
+
24
+ ![Diagraming preview](mes_diagrammes.png)
25
+
26
+ ## Why this project?
27
+
28
+ Some environments have **no internet access** or don't allow installing tools: no task-tracking software, no CDN, nothing from the outside.
29
+
30
+ Yet your productivity depends on your ability to **log your tasks**, your **notes** and your **useful links** somewhere — and find them again each morning.
31
+
32
+ This project solves that problem: a **single HTML file** you drop on your desktop that works in any browser, even offline.
33
+
34
+ ---
35
+
36
+ ## The three panels
37
+
38
+ ### myTasks. — Task manager
39
+
40
+ Add tasks in an instant, sort them by priority, tick them off as the day goes on.
41
+
42
+ - Three priority levels: **Urgent**, **Normal**, **Later**
43
+ - Status filters: All, To do, Done, Urgent, Normal, Later
44
+ - Checkbox to mark a task as complete
45
+ - Individual deletion
46
+
47
+ ### myNotes. — Structured notepad
48
+
49
+ Everything you need to remember, organised as notes made of freely stackable blocks.
50
+
51
+ - Five block types per note:
52
+ - **Title** — short bold text to structure the note
53
+ - **Text** — free paragraph
54
+ - **Code** — monospace block with grey background (commands, regex, snippets…)
55
+ - **List** — bullet points
56
+ - **Table** — columns separated by `|`, first line = headers
57
+ - Each note has a customisable colour
58
+ - Notes are **collapsed by default** — click the chevron to expand; use the toolbar button to expand/collapse all at once
59
+ - Add, edit and delete notes and blocks in edit mode
60
+
61
+ ### myLinks. — Useful link directory
62
+
63
+ Your links organised by category, accessible in one click.
64
+
65
+ - Customisable categories with a colour of your choice
66
+ - Categories are **collapsed by default** — click the chevron to expand; use the toolbar button to expand/collapse all at once
67
+ - Displayed with name and description
68
+ - Add, edit and delete in edit mode
69
+
70
+ ### myDiagrams. — Diagram editor
71
+
72
+ A lightweight SVG diagram editor accessible via the diagram icon (top-right of the dashboard).
73
+
74
+ ![Diagram editor overview](images/diagram-overview.png)
75
+
76
+ #### Shapes
77
+
78
+ Six shape types are available from the toolbar:
79
+
80
+ | Shape | Description |
81
+ | ----------------- | --------------------------------------------------------- |
82
+ | Rectangle | Standard box with slightly rounded corners |
83
+ | Rounded rectangle | Pill-shaped box |
84
+ | Database | Cylinder — represents a data store |
85
+ | External service | Solid ellipse — represents a third-party or cloud service |
86
+ | Free text | Label without a background |
87
+ | Post-it | Sticky note with a folded corner, multi-line text |
88
+
89
+ #### Arrows
90
+
91
+ - Draw arrows by clicking **source → target** with the arrow tool, or by **dragging from a connection dot** on any shape
92
+ - The label input opens automatically after creating an arrow
93
+ - **Double-click** an arrow (or use the ✎ button) to edit its label
94
+
95
+ #### Text editing
96
+
97
+ - **Double-click** a shape (or use the ✎ button) to edit its text inline
98
+ - For `rect`, `rounded`, `db`, `cloud` and `postit` shapes, a **transparent textarea** is overlaid directly on the shape — text wraps automatically as you type
99
+ - The text input for the `db` cylinder is positioned in the **body only**, below the top cap
100
+
101
+ #### Text formatting palette
102
+
103
+ When a shape is selected, a formatting palette appears. From left to right:
104
+
105
+ | Control | Effect |
106
+ | ------------- | -------------------------------------------------------------------------------------------------- |
107
+ | 6 colour dots | Apply a theme colour to the shape |
108
+ | ✎ | Open the inline text editor |
109
+ | `Aa+` / `Aa−` | Increase / decrease font size (range: 8–28 px) |
110
+ | ← / ↔ / → | Horizontal text alignment: left / centre / right |
111
+ | ↑ / ↕ / ↓ | Vertical text alignment: top / middle / bottom |
112
+ | Hollow drop | Copy the **font size** from another shape — click the button then click the source shape |
113
+ | Filled drop | Copy the **full style** from another shape (font size, colour, shape type, dimensions, alignments) |
114
+
115
+ > The style copy (filled drop) works with multi-selection: select several shapes, activate the drop, click the source — all selected shapes are updated at once.
116
+
117
+ #### Text wrapping
118
+
119
+ Text in `rect`, `rounded`, `db`, `cloud` and `postit` shapes wraps automatically to fit the shape width. Resizing a shape immediately re-flows the text. The font size set via `Aa+`/`Aa−` is also taken into account when computing line breaks.
120
+
121
+ #### Zoom per diagram
122
+
123
+ Each diagram remembers its own zoom level. Switching from one diagram to another restores the zoom you were using last time — stored in `localStorage` separately from the diagram data.
124
+
125
+ #### Lock per diagram
126
+
127
+ The lock button (🔓/🔒) in the toolbar freezes the diagram: all canvas interactions (selection, tools, keyboard shortcuts) are disabled and any click simply pans the view. The lock state is saved per diagram in `localStorage` and restored when you switch back to it.
128
+
129
+ #### Navigation
130
+
131
+ - The ☰ button opens the diagram list panel — clicking a diagram name switches to it **and closes the panel automatically**
132
+ - Diagram names **wrap to the next line** if they are too long — nothing is truncated
133
+ - Diagrams can be **reordered by drag & drop** in the panel: grab the `⠿` handle on the left of any item, drag it up or down, and a dashed orange line shows exactly where it will land
134
+ - The `+ New` button creates a new diagram
135
+ - The ← button in the top-right returns to the main dashboard
136
+
137
+ #### Saving
138
+
139
+ - Saves directly to `diagrammes.js` on disk via the File System Access API (same mechanism as notes and links)
140
+ - The green **save** button appears in the toolbar whenever the in-memory data differs from the saved file
141
+
142
+ ---
143
+
144
+ ## Data persistence
145
+
146
+ Everything is saved in the browser's `localStorage` — your content survives browser restarts.
147
+
148
+ To avoid losing data when you clear the cache or switch machines, each panel has a **"save changes"** button that overwrites the source file (`mesLiens.js` or `mesNotes.js`) directly on your disk, using the **File System Access API** (Chrome and Edge Chromium only).
149
+
150
+ > **First save**: a modal asks you to select the project folder. The file is then updated directly on every subsequent save, with no dialog.
151
+
152
+ ## Administration page
153
+
154
+ The ⚙ icon in the top-right corner of the dashboard opens `admin.html`. It lets you:
155
+
156
+ - **Choose the language** — switch between Français and English (saved in localStorage)
157
+ - **Clear localStorage** — resets to the default data from `mesLiens.js` and `mesNotes.js` on next load
158
+ - **Delete IndexedDB** — clears the stored file handle; the next save will ask you to select the folder again
159
+
160
+ The two reset actions are independent, can be checked separately, and are executed via a single button. The page explains the consequences before acting.
161
+
162
+ ## Internationalisation
163
+
164
+ The interface is available in **French** (default) and **English**. The language is chosen from the administration page and stored in `localStorage`.
165
+
166
+ Translations live in the `i18n/` folder:
167
+
168
+ | File | Role |
169
+ | -------------- | -------------------------------------------------------------------------- |
170
+ | `i18n/fr.js` | French translations (`var i18n_fr`) |
171
+ | `i18n/en.js` | English translations (`var i18n_en`) |
172
+ | `i18n/i18n.js` | Engine: reads `localStorage["lang"]`, exposes `window.t` and `applyI18n()` |
173
+
174
+ ---
175
+
176
+ ## Quick start
177
+
178
+ ### Via npx (recommended)
179
+
180
+ ```bash
181
+ npx doc-survival-kit
182
+ ```
183
+
184
+ Creates a `doc-survival-kit/` folder in the current directory and opens the application automatically in the browser. Subsequent runs simply open the application without overwriting anything.
185
+
186
+ > Requires Node.js >= 16.7. Use Chrome or Edge for file saving.
187
+
188
+ ### Without any tool
189
+
190
+ 1. Copy the following files and folder into a new directory:
191
+
192
+ - `index.html`
193
+ - `admin.html`
194
+ - `diagram.html`
195
+ - `diagram.js`
196
+ - `diagrammes.js`
197
+ - `liens.js`
198
+ - `mesLiens.js`
199
+ - `mesNotes.js`
200
+ - `notes.js`
201
+ - `style.css`
202
+ - `taches.js`
203
+ - `i18n/` (entire folder)
204
+
205
+ 2. Open `index.html` in Chrome or Edge
206
+ 3. That's it.
207
+
208
+ Sample content is already present in each panel to give you an idea of what you can put there.
209
+
210
+ ### Manually
211
+
212
+ 1. Clone or download this repository
213
+ 2. Open `index.html` in Chrome or Edge
214
+ 3. That's it.
215
+
216
+ ```bash
217
+ git clone https://github.com/ymedaghri/doc-survival-kit.git
218
+ cd doc-survival-kit
219
+ open index.html # macOS
220
+ # or
221
+ start index.html # Windows
222
+ ```
223
+
224
+ ---
225
+
226
+ ## Tech stack
227
+
228
+ | Technology | Detail |
229
+ | ------------------ | ------------------------------------------------------- |
230
+ | HTML | Semantic structure, no framework |
231
+ | CSS | Separate styles in `style.css`, no framework |
232
+ | JavaScript | Vanilla, no third-party library |
233
+ | Local storage | Browser `localStorage` |
234
+ | File storage | File System Access API (`showDirectoryPicker`) |
235
+ | Handle persistence | `IndexedDB` — file handle is remembered across sessions |
236
+
237
+ ---
238
+
239
+ ## Author
240
+
241
+ **Youssef MEDAGHRI-ALAOUI**
242
+ [craftskillz.com](https://www.craftskillz.com/posts/stay-secure-and-productive)
243
+
244
+ ---
245
+
246
+ ## License
247
+
248
+ This project is distributed under the **MIT** licence — you are free to use, modify and redistribute it, including in commercial projects, provided you retain the original author credit.
package/admin.html ADDED
@@ -0,0 +1,329 @@
1
+ <!doctype html>
2
+ <html lang="fr">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title data-i18n="page_title_admin">
7
+ Administration — doc-survival-kit
8
+ </title>
9
+ <link rel="stylesheet" href="style.css" />
10
+ <style>
11
+ .admin-shell {
12
+ max-width: 560px;
13
+ margin: 0 auto;
14
+ padding: 60px 36px 80px;
15
+ }
16
+ .admin-back {
17
+ position: fixed;
18
+ top: 16px;
19
+ right: 20px;
20
+ font-size: 1.4rem;
21
+ color: #78716c;
22
+ text-decoration: none;
23
+ background: #f5f5f4;
24
+ border: 1px solid #e7e5e4;
25
+ border-radius: 8px;
26
+ width: 40px;
27
+ height: 40px;
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: center;
31
+ transition:
32
+ background 0.15s,
33
+ color 0.15s;
34
+ line-height: 1;
35
+ }
36
+ .admin-back:hover {
37
+ background: #292524;
38
+ color: #fff;
39
+ border-color: #292524;
40
+ }
41
+ .admin-lang-section {
42
+ margin-bottom: 36px;
43
+ }
44
+ .admin-lang-section h2 {
45
+ font-family: "Cascadia Code", "SF Mono", "Consolas", monospace;
46
+ font-size: 0.65rem;
47
+ letter-spacing: 0.12em;
48
+ text-transform: uppercase;
49
+ color: #a8a29e;
50
+ margin-bottom: 12px;
51
+ }
52
+ .admin-lang-options {
53
+ display: flex;
54
+ gap: 8px;
55
+ }
56
+ .btn-lang {
57
+ font-family: "Cascadia Code", "SF Mono", "Consolas", monospace;
58
+ font-size: 0.7rem;
59
+ letter-spacing: 0.08em;
60
+ padding: 8px 20px;
61
+ border-radius: 8px;
62
+ border: 1px solid #e7e5e4;
63
+ background: #fff;
64
+ cursor: pointer;
65
+ transition:
66
+ background 0.15s,
67
+ border-color 0.15s,
68
+ color 0.15s;
69
+ }
70
+ .btn-lang:hover {
71
+ border-color: #f97316;
72
+ background: #fff7ed;
73
+ }
74
+ .btn-lang.active {
75
+ background: #f97316;
76
+ color: #fff;
77
+ border-color: #f97316;
78
+ }
79
+ .admin-intro {
80
+ background: #fff7ed;
81
+ border: 1px solid #fed7aa;
82
+ border-radius: 10px;
83
+ padding: 20px 24px;
84
+ margin-bottom: 36px;
85
+ }
86
+ .admin-intro h2 {
87
+ font-family: "Cascadia Code", "SF Mono", "Consolas", monospace;
88
+ font-size: 0.65rem;
89
+ letter-spacing: 0.12em;
90
+ text-transform: uppercase;
91
+ color: #f97316;
92
+ margin-bottom: 12px;
93
+ }
94
+ .admin-intro p {
95
+ font-size: 0.875rem;
96
+ line-height: 1.65;
97
+ color: #57534e;
98
+ margin-bottom: 10px;
99
+ }
100
+ .admin-intro p:last-child {
101
+ margin-bottom: 0;
102
+ }
103
+ .admin-intro strong {
104
+ color: #292524;
105
+ }
106
+ .admin-actions {
107
+ display: flex;
108
+ flex-direction: column;
109
+ gap: 12px;
110
+ margin-bottom: 32px;
111
+ }
112
+ .admin-check-label {
113
+ display: flex;
114
+ align-items: flex-start;
115
+ gap: 12px;
116
+ padding: 16px 20px;
117
+ border-radius: 10px;
118
+ border: 1px solid #e7e5e4;
119
+ background: #fff;
120
+ cursor: pointer;
121
+ transition:
122
+ border-color 0.15s,
123
+ background 0.15s;
124
+ }
125
+ .admin-check-label:hover {
126
+ border-color: #f97316;
127
+ background: #fff7ed;
128
+ }
129
+ .admin-check-label input[type="checkbox"] {
130
+ margin-top: 2px;
131
+ flex-shrink: 0;
132
+ width: 16px;
133
+ height: 16px;
134
+ accent-color: #f97316;
135
+ cursor: pointer;
136
+ }
137
+ .admin-check-text strong {
138
+ display: block;
139
+ font-size: 0.875rem;
140
+ font-weight: 600;
141
+ color: #292524;
142
+ margin-bottom: 3px;
143
+ }
144
+ .admin-check-text span {
145
+ font-size: 0.8rem;
146
+ color: #a8a29e;
147
+ line-height: 1.5;
148
+ }
149
+ .btn-execute {
150
+ font-family: "Cascadia Code", "SF Mono", "Consolas", monospace;
151
+ font-size: 0.65rem;
152
+ letter-spacing: 0.1em;
153
+ text-transform: uppercase;
154
+ padding: 10px 20px;
155
+ border-radius: 8px;
156
+ background: #fef2f2;
157
+ color: #ef4444;
158
+ border: 1px solid #fecaca;
159
+ transition:
160
+ background 0.15s,
161
+ color 0.15s,
162
+ border-color 0.15s;
163
+ cursor: pointer;
164
+ }
165
+ .btn-execute:hover {
166
+ background: #ef4444;
167
+ color: #fff;
168
+ border-color: #ef4444;
169
+ }
170
+ .btn-execute:disabled {
171
+ opacity: 0.4;
172
+ cursor: not-allowed;
173
+ }
174
+ .admin-feedback {
175
+ display: none;
176
+ margin-top: 20px;
177
+ padding: 14px 18px;
178
+ border-radius: 8px;
179
+ font-size: 0.875rem;
180
+ line-height: 1.5;
181
+ }
182
+ .admin-feedback.success {
183
+ background: #d1fae5;
184
+ color: #047857;
185
+ border: 1px solid #6ee7b7;
186
+ }
187
+ </style>
188
+ </head>
189
+ <body>
190
+ <a href="index.html" class="admin-back" title="Retour au dashboard">←</a>
191
+
192
+ <div class="admin-shell">
193
+ <h1>admin<span class="accent">.</span></h1>
194
+ <p class="subtitle" data-i18n="admin_subtitle">
195
+ réinitialisation des données
196
+ </p>
197
+
198
+ <!-- ── Sélecteur de langue ── -->
199
+ <div class="admin-lang-section">
200
+ <h2 data-i18n="admin_lang_title">Langue / Language</h2>
201
+ <div class="admin-lang-options">
202
+ <button class="btn-lang" id="btnLangFr" onclick="setLang('fr')">
203
+ Français
204
+ </button>
205
+ <button class="btn-lang" id="btnLangEn" onclick="setLang('en')">
206
+ English
207
+ </button>
208
+ </div>
209
+ </div>
210
+
211
+ <div class="admin-intro">
212
+ <h2 data-i18n="admin_why_title">Pourquoi cette page ?</h2>
213
+ <p data-i18n-html="admin_why_p1">
214
+ L'application stocke tes données à deux endroits dans ton navigateur :
215
+ le <strong>localStorage</strong> (tâches, notes, liens) et l'<strong
216
+ >IndexedDB</strong
217
+ >
218
+ (le handle du fichier pour la sauvegarde directe).
219
+ </p>
220
+ <p data-i18n-html="admin_why_p2">
221
+ Ces données <strong>ne sont pas supprimées</strong> en vidant le cache
222
+ classique ou en fermant le navigateur. Cette page te permet de les
223
+ effacer proprement, par exemple pour repartir d'une installation
224
+ vierge ou résoudre un problème de synchronisation entre le fichier et
225
+ le navigateur.
226
+ </p>
227
+ <p data-i18n-html="admin_why_p3">
228
+ <strong>Attention :</strong> ces actions sont irréversibles. Si tu
229
+ n'as pas sauvegardé tes modifications dans les fichiers
230
+ <code>mesLiens.js</code> et <code>mesNotes.js</code>, tes données
231
+ seront perdues.
232
+ </p>
233
+ </div>
234
+
235
+ <div class="admin-actions">
236
+ <label class="admin-check-label">
237
+ <input type="checkbox" id="checkLocalStorage" />
238
+ <div class="admin-check-text">
239
+ <strong data-i18n="admin_ls_label">Effacer le localStorage</strong>
240
+ <span data-i18n-html="admin_ls_desc"
241
+ >Supprime toutes les tâches, notes et liens mémorisés dans le
242
+ navigateur. Au prochain chargement, l'application repart des
243
+ données par défaut contenues dans <code>mesLiens.js</code> et
244
+ <code>mesNotes.js</code>.</span
245
+ >
246
+ </div>
247
+ </label>
248
+
249
+ <label class="admin-check-label">
250
+ <input type="checkbox" id="checkIndexedDB" />
251
+ <div class="admin-check-text">
252
+ <strong data-i18n="admin_idb_label">Supprimer l'IndexedDB</strong>
253
+ <span data-i18n="admin_idb_desc"
254
+ >Efface le handle de fichier mémorisé pour la sauvegarde directe.
255
+ La prochaine sauvegarde te demandera à nouveau de sélectionner le
256
+ dossier du projet, comme lors de la première utilisation.</span
257
+ >
258
+ </div>
259
+ </label>
260
+ </div>
261
+
262
+ <button
263
+ class="btn-execute"
264
+ id="btnExecute"
265
+ disabled
266
+ onclick="executer()"
267
+ data-i18n="admin_execute_btn"
268
+ >
269
+ exécuter les actions sélectionnées
270
+ </button>
271
+
272
+ <div class="admin-feedback" id="adminFeedback"></div>
273
+ </div>
274
+
275
+ <script src="i18n/fr.js"></script>
276
+ <script src="i18n/en.js"></script>
277
+ <script src="i18n/i18n.js"></script>
278
+ <script>
279
+ var chkLS = document.getElementById("checkLocalStorage");
280
+ var chkIDB = document.getElementById("checkIndexedDB");
281
+ var btn = document.getElementById("btnExecute");
282
+ var feedback = document.getElementById("adminFeedback");
283
+
284
+ // Highlight active language button
285
+ (function () {
286
+ var lang = localStorage.getItem("lang") || "fr";
287
+ document
288
+ .getElementById(lang === "en" ? "btnLangEn" : "btnLangFr")
289
+ .classList.add("active");
290
+ })();
291
+
292
+ function setLang(lang) {
293
+ localStorage.setItem("lang", lang);
294
+ window.location.reload();
295
+ }
296
+
297
+ function updateBtn() {
298
+ btn.disabled = !chkLS.checked && !chkIDB.checked;
299
+ }
300
+ chkLS.addEventListener("change", updateBtn);
301
+ chkIDB.addEventListener("change", updateBtn);
302
+
303
+ function executer() {
304
+ var messages = [];
305
+
306
+ if (chkLS.checked) {
307
+ localStorage.clear();
308
+ // Restore lang setting so the page stays in the right language
309
+ var lang = window.t === i18n_en ? "en" : "fr";
310
+ localStorage.setItem("lang", lang);
311
+ messages.push(window.t.admin_feedback_ls);
312
+ chkLS.checked = false;
313
+ }
314
+
315
+ if (chkIDB.checked) {
316
+ indexedDB.deleteDatabase("doc-survival-kit-db");
317
+ messages.push(window.t.admin_feedback_idb);
318
+ chkIDB.checked = false;
319
+ }
320
+
321
+ updateBtn();
322
+ feedback.textContent =
323
+ messages.join(" ") + " " + window.t.admin_feedback_return;
324
+ feedback.className = "admin-feedback success";
325
+ feedback.style.display = "block";
326
+ }
327
+ </script>
328
+ </body>
329
+ </html>
package/bin/cli.js ADDED
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const { exec } = require("child_process");
6
+
7
+ const DEST_DIR = path.join(process.cwd(), "doc-survival-kit");
8
+ const SRC_DIR = path.join(__dirname, "..");
9
+ const APP_FILES = [
10
+ "index.html",
11
+ "admin.html",
12
+ "diagram.html",
13
+ "style.css",
14
+ "liens.js",
15
+ "taches.js",
16
+ "notes.js",
17
+ "diagram.js",
18
+ ];
19
+ const DATA_FILES = ["mesLiens.js", "mesNotes.js", "diagrammes.js"];
20
+ const I18N_FILES = ["i18n/fr.js", "i18n/en.js", "i18n/i18n.js"];
21
+ const IMAGES_FILES = ["images/img_1774270331723.png"];
22
+
23
+ function openBrowser(filePath) {
24
+ const url = "file://" + filePath;
25
+ const cmd =
26
+ process.platform === "win32"
27
+ ? `start "" "${url}"`
28
+ : process.platform === "darwin"
29
+ ? `open "${url}"`
30
+ : `xdg-open "${url}"`;
31
+ exec(cmd, (err) => {
32
+ if (err) {
33
+ console.log("Ouvre manuellement dans Chrome ou Edge :");
34
+ console.log(filePath);
35
+ }
36
+ });
37
+ }
38
+
39
+ const htmlFile = path.join(DEST_DIR, "index.html");
40
+
41
+ if (fs.existsSync(DEST_DIR)) {
42
+ console.log("Le dossier doc-survival-kit existe déjà.");
43
+ console.log("Ouverture de l'application...");
44
+ openBrowser(htmlFile);
45
+ } else {
46
+ fs.mkdirSync(DEST_DIR, { recursive: true });
47
+
48
+ // Fichiers app (toujours copiés)
49
+ for (const file of APP_FILES) {
50
+ fs.copyFileSync(path.join(SRC_DIR, file), path.join(DEST_DIR, file));
51
+ }
52
+
53
+ // Fichiers i18n (toujours copiés)
54
+ fs.mkdirSync(path.join(DEST_DIR, "i18n"), { recursive: true });
55
+ for (const file of I18N_FILES) {
56
+ fs.copyFileSync(path.join(SRC_DIR, file), path.join(DEST_DIR, file));
57
+ }
58
+
59
+ // Fichiers i18n (toujours copiés)
60
+ fs.mkdirSync(path.join(DEST_DIR, "images"), { recursive: true });
61
+ for (const file of IMAGES_FILES) {
62
+ fs.copyFileSync(path.join(SRC_DIR, file), path.join(DEST_DIR, file));
63
+ }
64
+ // Fichiers de données (copiés seulement à la création)
65
+ for (const file of DATA_FILES) {
66
+ fs.copyFileSync(path.join(SRC_DIR, file), path.join(DEST_DIR, file));
67
+ }
68
+
69
+ console.log("doc-survival-kit créé dans : " + DEST_DIR);
70
+ console.log("");
71
+ console.log("Note : tes données sont sauvegardées dans ce dossier.");
72
+ console.log(" Ouvre toujours le fichier depuis ce même dossier.");
73
+ console.log("");
74
+ console.log("Ouverture de l'application...");
75
+ console.log("(Utilise Chrome ou Edge pour la sauvegarde de fichiers)");
76
+ openBrowser(htmlFile);
77
+ }