synthos 0.10.0 → 0.11.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.
Files changed (312) hide show
  1. package/README.md +5 -5
  2. package/default-pages/elevenlabs_effects_studio/chat-history.json +1 -0
  3. package/default-pages/elevenlabs_effects_studio/page.html +1345 -1363
  4. package/default-pages/elevenlabs_effects_studio/page.json +13 -11
  5. package/default-pages/elevenlabs_voice_studio/chat-history.json +1 -0
  6. package/default-pages/elevenlabs_voice_studio/page.html +782 -801
  7. package/default-pages/elevenlabs_voice_studio/page.json +13 -11
  8. package/default-pages/json_tools/chat-history.json +1 -0
  9. package/default-pages/json_tools/page.html +70 -90
  10. package/default-pages/json_tools/page.json +12 -10
  11. package/default-pages/my_notes/chat-history.json +1 -0
  12. package/default-pages/my_notes/page.html +115 -131
  13. package/default-pages/my_notes/page.json +14 -12
  14. package/default-pages/neon_asteroids/chat-history.json +1 -0
  15. package/default-pages/neon_asteroids/page.html +1777 -1803
  16. package/default-pages/neon_asteroids/page.json +14 -12
  17. package/default-pages/oregon_trail/chat-history.json +1 -0
  18. package/default-pages/oregon_trail/page.html +290 -307
  19. package/default-pages/oregon_trail/page.json +14 -12
  20. package/default-pages/solar_explorer/chat-history.json +1 -0
  21. package/default-pages/solar_explorer/page.html +1929 -1951
  22. package/default-pages/solar_explorer/page.json +14 -12
  23. package/default-pages/solar_tutorial/chat-history.json +1 -0
  24. package/default-pages/solar_tutorial/page.html +464 -478
  25. package/default-pages/solar_tutorial/page.json +12 -10
  26. package/default-pages/us_map/chat-history.json +1 -0
  27. package/default-pages/us_map/page.html +170 -193
  28. package/default-pages/us_map/page.json +14 -12
  29. package/default-pages/us_map/page.light.png +0 -0
  30. package/default-pages/us_map_1850/chat-history.json +1 -0
  31. package/default-pages/us_map_1850/page.html +302 -326
  32. package/default-pages/us_map_1850/page.json +14 -12
  33. package/default-pages/western_cities_1850/chat-history.json +1 -0
  34. package/default-pages/western_cities_1850/page.html +503 -527
  35. package/default-pages/western_cities_1850/page.json +14 -12
  36. package/default-themes/aurora-dawn.v3.css +15 -14
  37. package/default-themes/aurora-dusk.v3.css +26 -26
  38. package/default-themes/cosmos-dawn.v3.css +15 -14
  39. package/default-themes/cosmos-dusk.v3.css +26 -26
  40. package/default-themes/elemental-dawn.v3.css +200 -0
  41. package/default-themes/nebula-dawn.v3.css +15 -14
  42. package/default-themes/nebula-dusk.v3.css +24 -24
  43. package/default-themes/solar-flare-dawn.v3.css +15 -14
  44. package/default-themes/solar-flare-dusk.v3.css +26 -26
  45. package/dist/builders/anthropic.d.ts +26 -2
  46. package/dist/builders/anthropic.d.ts.map +1 -1
  47. package/dist/builders/anthropic.js +132 -31
  48. package/dist/builders/anthropic.js.map +1 -1
  49. package/dist/builders/claudecode.d.ts +13 -0
  50. package/dist/builders/claudecode.d.ts.map +1 -0
  51. package/dist/builders/claudecode.js +253 -0
  52. package/dist/builders/claudecode.js.map +1 -0
  53. package/dist/builders/index.d.ts +2 -1
  54. package/dist/builders/index.d.ts.map +1 -1
  55. package/dist/builders/index.js +8 -1
  56. package/dist/builders/index.js.map +1 -1
  57. package/dist/builders/openai.js +2 -1
  58. package/dist/builders/openai.js.map +1 -1
  59. package/dist/builders/types.d.ts +31 -7
  60. package/dist/builders/types.d.ts.map +1 -1
  61. package/dist/builders/types.js +60 -28
  62. package/dist/builders/types.js.map +1 -1
  63. package/dist/connectors/types.d.ts +8 -0
  64. package/dist/connectors/types.d.ts.map +1 -1
  65. package/dist/init.d.ts.map +1 -1
  66. package/dist/init.js +13 -6
  67. package/dist/init.js.map +1 -1
  68. package/dist/migrations.d.ts.map +1 -1
  69. package/dist/migrations.js +161 -14
  70. package/dist/migrations.js.map +1 -1
  71. package/dist/models/anthropic.d.ts +1 -0
  72. package/dist/models/anthropic.d.ts.map +1 -1
  73. package/dist/models/anthropic.js +129 -29
  74. package/dist/models/anthropic.js.map +1 -1
  75. package/dist/models/chainOfThought.d.ts.map +1 -1
  76. package/dist/models/chainOfThought.js +32 -19
  77. package/dist/models/chainOfThought.js.map +1 -1
  78. package/dist/models/index.d.ts +2 -2
  79. package/dist/models/index.d.ts.map +1 -1
  80. package/dist/models/index.js +2 -1
  81. package/dist/models/index.js.map +1 -1
  82. package/dist/models/providers.d.ts +1 -0
  83. package/dist/models/providers.d.ts.map +1 -1
  84. package/dist/models/providers.js +12 -4
  85. package/dist/models/providers.js.map +1 -1
  86. package/dist/models/types.d.ts +15 -1
  87. package/dist/models/types.d.ts.map +1 -1
  88. package/dist/models/types.js.map +1 -1
  89. package/dist/pages.d.ts +57 -8
  90. package/dist/pages.d.ts.map +1 -1
  91. package/dist/pages.js +258 -45
  92. package/dist/pages.js.map +1 -1
  93. package/dist/service/createCompletePrompt.d.ts.map +1 -1
  94. package/dist/service/createCompletePrompt.js +5 -0
  95. package/dist/service/createCompletePrompt.js.map +1 -1
  96. package/dist/service/mediaCache.d.ts +36 -0
  97. package/dist/service/mediaCache.d.ts.map +1 -0
  98. package/dist/service/mediaCache.js +182 -0
  99. package/dist/service/mediaCache.js.map +1 -0
  100. package/dist/service/pageValidator.d.ts +25 -0
  101. package/dist/service/pageValidator.d.ts.map +1 -0
  102. package/dist/service/pageValidator.js +315 -0
  103. package/dist/service/pageValidator.js.map +1 -0
  104. package/dist/service/server.d.ts.map +1 -1
  105. package/dist/service/server.js +4 -0
  106. package/dist/service/server.js.map +1 -1
  107. package/dist/service/sharedTableSchema.d.ts +73 -0
  108. package/dist/service/sharedTableSchema.d.ts.map +1 -0
  109. package/dist/service/sharedTableSchema.js +206 -0
  110. package/dist/service/sharedTableSchema.js.map +1 -0
  111. package/dist/service/transformPage.d.ts +49 -11
  112. package/dist/service/transformPage.d.ts.map +1 -1
  113. package/dist/service/transformPage.js +354 -241
  114. package/dist/service/transformPage.js.map +1 -1
  115. package/dist/service/useApiRoutes.d.ts.map +1 -1
  116. package/dist/service/useApiRoutes.js +288 -34
  117. package/dist/service/useApiRoutes.js.map +1 -1
  118. package/dist/service/useConnectorRoutes.d.ts.map +1 -1
  119. package/dist/service/useConnectorRoutes.js +170 -32
  120. package/dist/service/useConnectorRoutes.js.map +1 -1
  121. package/dist/service/useDataRoutes.d.ts.map +1 -1
  122. package/dist/service/useDataRoutes.js +59 -2
  123. package/dist/service/useDataRoutes.js.map +1 -1
  124. package/dist/service/useExtractRoutes.d.ts +4 -0
  125. package/dist/service/useExtractRoutes.d.ts.map +1 -0
  126. package/dist/service/useExtractRoutes.js +304 -0
  127. package/dist/service/useExtractRoutes.js.map +1 -0
  128. package/dist/service/usePageRoutes.d.ts +17 -0
  129. package/dist/service/usePageRoutes.d.ts.map +1 -1
  130. package/dist/service/usePageRoutes.js +1385 -483
  131. package/dist/service/usePageRoutes.js.map +1 -1
  132. package/dist/service/useSharedDataRoutes.d.ts.map +1 -1
  133. package/dist/service/useSharedDataRoutes.js +54 -2
  134. package/dist/service/useSharedDataRoutes.js.map +1 -1
  135. package/dist/settings.d.ts +27 -0
  136. package/dist/settings.d.ts.map +1 -1
  137. package/dist/settings.js +40 -1
  138. package/dist/settings.js.map +1 -1
  139. package/dist/themes.d.ts +0 -5
  140. package/dist/themes.d.ts.map +1 -1
  141. package/dist/themes.js +3 -95
  142. package/dist/themes.js.map +1 -1
  143. package/migration-rules/v2-to-v3.md +277 -119
  144. package/package.json +5 -1
  145. package/{default-pages/application → required-pages/_shell}/page.html +56 -42
  146. package/required-pages/_shell/page.json +14 -0
  147. package/required-pages/_starters/page.html +534 -0
  148. package/required-pages/_starters/page.json +12 -0
  149. package/required-pages/builder/page.html +353 -43
  150. package/required-pages/builder/page.json +12 -10
  151. package/required-pages/pages/page.html +697 -924
  152. package/required-pages/pages/page.json +12 -10
  153. package/required-pages/settings/page.html +1879 -1753
  154. package/required-pages/settings/page.json +12 -10
  155. package/required-pages/synthos_apis/page.html +834 -845
  156. package/required-pages/synthos_apis/page.json +12 -10
  157. package/required-pages/synthos_scripts/page.html +74 -88
  158. package/required-pages/synthos_scripts/page.json +12 -10
  159. package/scripts/append-instructions.py +90 -0
  160. package/scripts/audit-instructions.py +76 -0
  161. package/scripts/cleanup-shell-markup.mjs +112 -0
  162. package/service-connectors/buffer/connector.json +46 -0
  163. package/service-connectors/canva/connector.json +67 -0
  164. package/service-connectors/elevenlabs/connector.json +1 -1
  165. package/src/builders/anthropic.ts +155 -30
  166. package/src/builders/claudecode.ts +310 -0
  167. package/src/builders/index.ts +7 -1
  168. package/src/builders/openai.ts +2 -1
  169. package/src/builders/types.ts +93 -32
  170. package/src/connectors/types.ts +8 -0
  171. package/src/init.ts +13 -7
  172. package/src/migrations.ts +187 -16
  173. package/src/models/anthropic.ts +140 -30
  174. package/src/models/chainOfThought.ts +33 -18
  175. package/src/models/index.ts +2 -2
  176. package/src/models/providers.ts +12 -3
  177. package/src/models/types.ts +21 -1
  178. package/src/pages.ts +271 -35
  179. package/src/service/createCompletePrompt.ts +6 -0
  180. package/src/service/mediaCache.ts +206 -0
  181. package/src/service/pageValidator.ts +337 -0
  182. package/src/service/server.ts +4 -0
  183. package/src/service/sharedTableSchema.ts +236 -0
  184. package/src/service/transformPage.ts +370 -260
  185. package/src/service/useApiRoutes.ts +282 -32
  186. package/src/service/useConnectorRoutes.ts +189 -34
  187. package/src/service/useDataRoutes.ts +198 -116
  188. package/src/service/useExtractRoutes.ts +331 -0
  189. package/src/service/usePageRoutes.ts +1411 -394
  190. package/src/service/useSharedDataRoutes.ts +184 -109
  191. package/src/settings.ts +65 -0
  192. package/src/themes.ts +78 -180
  193. package/starters/blank_starter/chat-history.json +1 -0
  194. package/starters/blank_starter/page.dark.png +0 -0
  195. package/starters/blank_starter/page.html +47 -0
  196. package/starters/blank_starter/page.json +13 -0
  197. package/starters/blank_starter/page.light.png +0 -0
  198. package/starters/calculator_starter/chat-history.json +1 -0
  199. package/starters/calculator_starter/page.dark.png +0 -0
  200. package/starters/calculator_starter/page.html +232 -0
  201. package/starters/calculator_starter/page.json +13 -0
  202. package/starters/calculator_starter/page.light.png +0 -0
  203. package/starters/calendar_starter/chat-history.json +1 -0
  204. package/starters/calendar_starter/page.dark.png +0 -0
  205. package/starters/calendar_starter/page.html +495 -0
  206. package/starters/calendar_starter/page.json +13 -0
  207. package/starters/calendar_starter/page.light.png +0 -0
  208. package/starters/chat_starter/chat-history.json +1 -0
  209. package/starters/chat_starter/page.dark.png +0 -0
  210. package/starters/chat_starter/page.html +351 -0
  211. package/starters/chat_starter/page.json +13 -0
  212. package/starters/chat_starter/page.light.png +0 -0
  213. package/starters/checklist_starter/chat-history.json +1 -0
  214. package/starters/checklist_starter/page.dark.png +0 -0
  215. package/starters/checklist_starter/page.html +437 -0
  216. package/starters/checklist_starter/page.json +13 -0
  217. package/starters/checklist_starter/page.light.png +0 -0
  218. package/starters/dashboard_starter/chat-history.json +1 -0
  219. package/starters/dashboard_starter/page.dark.png +0 -0
  220. package/starters/dashboard_starter/page.html +195 -0
  221. package/starters/dashboard_starter/page.json +13 -0
  222. package/starters/dashboard_starter/page.light.png +0 -0
  223. package/starters/form_starter/chat-history.json +1 -0
  224. package/starters/form_starter/page.dark.png +0 -0
  225. package/starters/form_starter/page.html +313 -0
  226. package/starters/form_starter/page.json +13 -0
  227. package/starters/form_starter/page.light.png +0 -0
  228. package/starters/gallery_starter/chat-history.json +1 -0
  229. package/starters/gallery_starter/page.dark.png +0 -0
  230. package/starters/gallery_starter/page.html +418 -0
  231. package/starters/gallery_starter/page.json +13 -0
  232. package/starters/gallery_starter/page.light.png +0 -0
  233. package/starters/generator_starter/chat-history.json +1 -0
  234. package/starters/generator_starter/page.dark.png +0 -0
  235. package/starters/generator_starter/page.html +261 -0
  236. package/starters/generator_starter/page.json +13 -0
  237. package/starters/generator_starter/page.light.png +0 -0
  238. package/starters/index.html +538 -0
  239. package/starters/kanban_starter/chat-history.json +1 -0
  240. package/starters/kanban_starter/page.dark.png +0 -0
  241. package/starters/kanban_starter/page.html +432 -0
  242. package/starters/kanban_starter/page.json +13 -0
  243. package/starters/kanban_starter/page.light.png +0 -0
  244. package/starters/presentation_builder/chat-history.json +1 -0
  245. package/starters/presentation_builder/page.dark.png +0 -0
  246. package/starters/presentation_builder/page.html +970 -0
  247. package/starters/presentation_builder/page.json +15 -0
  248. package/starters/presentation_builder/page.light.png +0 -0
  249. package/starters/presentation_builder/presentation_voice/voice_config.json +9 -0
  250. package/starters/pulse_starter/chat-history.json +1 -0
  251. package/starters/pulse_starter/page.dark.png +0 -0
  252. package/starters/pulse_starter/page.html +698 -0
  253. package/starters/pulse_starter/page.json +13 -0
  254. package/starters/pulse_starter/page.light.png +0 -0
  255. package/starters/quiz_starter/chat-history.json +1 -0
  256. package/starters/quiz_starter/page.dark.png +0 -0
  257. package/starters/quiz_starter/page.html +292 -0
  258. package/starters/quiz_starter/page.json +13 -0
  259. package/starters/quiz_starter/page.light.png +0 -0
  260. package/starters/reference_starter/chat-history.json +1 -0
  261. package/starters/reference_starter/page.dark.png +0 -0
  262. package/starters/reference_starter/page.html +250 -0
  263. package/starters/reference_starter/page.json +13 -0
  264. package/starters/reference_starter/page.light.png +0 -0
  265. package/starters/retro_game_starter/chat-history.json +1 -0
  266. package/starters/retro_game_starter/page.dark.png +0 -0
  267. package/{default-pages → starters}/retro_game_starter/page.html +1281 -1308
  268. package/starters/retro_game_starter/page.json +15 -0
  269. package/starters/retro_game_starter/page.light.png +0 -0
  270. package/starters/roster_starter/chat-history.json +1 -0
  271. package/starters/roster_starter/page.dark.png +0 -0
  272. package/starters/roster_starter/page.html +600 -0
  273. package/starters/roster_starter/page.json +13 -0
  274. package/starters/roster_starter/page.light.png +0 -0
  275. package/starters/server.js +182 -0
  276. package/starters/start.cmd +1 -0
  277. package/starters/timeline_starter/chat-history.json +1 -0
  278. package/starters/timeline_starter/page.dark.png +0 -0
  279. package/starters/timeline_starter/page.html +446 -0
  280. package/starters/timeline_starter/page.json +13 -0
  281. package/starters/timeline_starter/page.light.png +0 -0
  282. package/starters/tutorial_starter/chat-history.json +1 -0
  283. package/starters/tutorial_starter/page.dark.png +0 -0
  284. package/starters/tutorial_starter/page.html +283 -0
  285. package/starters/tutorial_starter/page.json +13 -0
  286. package/starters/tutorial_starter/page.light.png +0 -0
  287. package/static-files/agent.v3.js +122 -0
  288. package/static-files/connector.v3.js +48 -0
  289. package/static-files/extract.v3.js +188 -0
  290. package/static-files/helpers.v3.js +50 -6
  291. package/static-files/page-bridge.js +114 -0
  292. package/static-files/page.v3.js +1292 -1290
  293. package/static-files/script.v3.js +32 -0
  294. package/static-files/server.v3.js +89 -0
  295. package/static-files/shell-bridge.v3.js +174 -0
  296. package/static-files/shell-modals.v3.js +521 -0
  297. package/static-files/{shell.css → shell.v3.css} +271 -22
  298. package/static-files/shell.v3.js +1865 -0
  299. package/static-files/storage.v3.js +176 -0
  300. package/tests/anthropic.spec.ts +42 -7
  301. package/tests/builders.spec.ts +72 -4
  302. package/tests/pageValidator.spec.ts +548 -0
  303. package/tests/profiles.spec.ts +122 -0
  304. package/tests/providers.spec.ts +1 -1
  305. package/tests/sharedTableSchema.spec.ts +242 -0
  306. package/tests/transformPage.spec.ts +62 -81
  307. package/default-pages/application/page.json +0 -10
  308. package/default-pages/retro_game_starter/page.json +0 -12
  309. package/default-pages/sidebar_page/page.html +0 -51
  310. package/default-pages/sidebar_page/page.json +0 -10
  311. package/default-pages/two-panel_page/page.html +0 -68
  312. package/default-pages/two-panel_page/page.json +0 -10
@@ -1,11 +1,13 @@
1
- {
2
- "title": "ElevenLabs Voice Studio",
3
- "categories": [
4
- "Tools",
5
- "Audio"
6
- ],
7
- "pinned": false,
8
- "showInAll": false,
9
- "pageVersion": 3,
10
- "mode": "locked"
11
- }
1
+ {
2
+ "title": "ElevenLabs Voice Studio",
3
+ "categories": [
4
+ "Tools",
5
+ "Audio"
6
+ ],
7
+ "pinned": false,
8
+ "showInAll": false,
9
+ "pageVersion": 3,
10
+ "mode": "locked",
11
+ "greeting": "Welcome to the ElevenLabs Voice Studio! Define voice profiles here and they'll be available to all your pages. Make sure the ElevenLabs connector is configured in Settings > Connectors.",
12
+ "firstRunGreeting": ""
13
+ }
@@ -0,0 +1 @@
1
+ [{"role":"assistant","content":"You can use the dropdown to select a conversion type, enter your text, and click \"Convert\" to see the result."}]
@@ -1,91 +1,71 @@
1
- <!DOCTYPE html><html lang="en"><head>
2
- <meta charset="UTF-8">
3
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
4
- <title>SynthOS - JSON Tools</title>
5
- <script id="theme-info" src="/api/theme-info.js" data-locked="true"></script>
6
- <link id="theme-css" rel="stylesheet" href="/api/theme.css" data-locked="true">
7
- <style>.dialog-title{font-size:22px;font-weight:700;min-height:var(--header-min-height);padding:var(--header-padding-vertical) var(--header-padding-horizontal);line-height:var(--header-line-height);display:flex;align-items:center;justify-content:center;box-sizing:border-box;background:linear-gradient(135deg,var(--accent-primary),var(--accent-secondary));color:#fff;border-radius:12px;width:100%;max-width:800px;box-shadow:0 6px 25px var(--accent-glow);position:relative;z-index:1}.dialog-content{font-size:14px;color:rgba(224,224,224,.8);padding:15px 0;flex-grow:1;width:100%;max-width:800px;position:relative;z-index:1;overflow-y:auto;display:flex;flex-direction:column;gap:15px}.conversion-select{width:100%;padding:12px 15px;border-radius:10px;border:1px solid var(--border-color);background:rgba(15,15,35,.8);color:var(--text-primary);font-size:14px;cursor:pointer;transition:.3s}.conversion-select:focus{outline:0;border-color:var(--text-secondary);box-shadow:0 0 15px var(--accent-glow)}.conversion-select option{background:var(--bg-tertiary);color:var(--text-primary)}.multi-line-input{width:100%;min-height:220px;padding:15px;border-radius:10px;border:1px solid var(--border-color);background:rgba(15,15,35,.8);color:var(--text-primary);font-size:14px;font-family:'Courier New',monospace;resize:vertical;transition:.3s}.multi-line-input:focus{outline:0;border-color:var(--text-secondary);box-shadow:0 0 15px var(--accent-glow)}.button-group{display:flex;justify-content:space-between;align-items:center;gap:10px}.button-group div{display:flex;gap:10px}.action-btn{padding:12px 24px;border:none;border-radius:25px;font-size:14px;font-weight:600;cursor:pointer;transition:.3s;letter-spacing:1px}.convert-btn{background:linear-gradient(135deg,var(--accent-primary) 0,var(--accent-secondary) 100%);color:#fff;box-shadow:0 4px 20px var(--accent-glow)}.convert-btn:hover{transform:translateY(-2px);box-shadow:0 6px 25px rgba(102,126,234,.6)}.reset-btn{background:rgba(102,126,234,.2);color:var(--text-secondary);border:1px solid var(--border-color)}.reset-btn:hover{background:rgba(102,126,234,.3);color:var(--accent-tertiary)}.copy-btn{background:linear-gradient(135deg,rgba(240,147,251,.3) 0,rgba(118,75,162,.3) 100%);color:var(--text-secondary);border:1px solid var(--border-color)}.copy-btn:hover:not(:disabled){background:linear-gradient(135deg,rgba(240,147,251,.5) 0,rgba(118,75,162,.5) 100%);color:var(--accent-tertiary)}.copy-btn:disabled{opacity:.5;cursor:not-allowed}.result-panel{width:100%;min-height:220px;max-height:350px;padding:15px;border-radius:10px;border:1px solid var(--border-color);background:rgba(15,15,35,.8);color:var(--accent-tertiary);font-size:13px;font-family:'Courier New',monospace;overflow-y:auto;white-space:pre-wrap;word-break:break-all}.light-mode .dialog-content{color:rgba(45,38,64,.8)}.light-mode .conversion-select,.light-mode .multi-line-input,.light-mode .result-panel{background:rgba(255,255,255,.8)}</style>
8
- <script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js"></script>
9
- <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/14.1.1/marked.min.js"></script>
10
- <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
11
- </head>
12
-
13
- <body>
14
- <div class="shell-toolbar" data-locked="true">
15
- <button class="shell-toolbar-btn" id="builderToggle" aria-label="Page Builder" data-locked="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"><path d="M7 18.5H6.2c-1.77 0-3.2-1.43-3.2-3.2V7.7C3 5.93 4.43 4.5 6.2 4.5h11.6c1.77 0 3.2 1.43 3.2 3.2v7.6c0 1.77-1.43 3.2-3.2 3.2H12l-4.2 3.2c-.5.38-1.2.02-1.2-.6V18.5Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><circle cx="8.5" cy="11.5" r="1" fill="currentColor"/><circle cx="12" cy="11.5" r="1" fill="currentColor"/><circle cx="15.5" cy="11.5" r="1" fill="currentColor"/></svg></button>
16
- <button class="shell-toolbar-btn" id="pagesBtn" aria-label="View All Pages" data-locked="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none"><rect x="3" y="3" width="11" height="12" rx="1.5" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M6 7.5h5M6 10h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><rect x="18" y="3" width="11" height="12" rx="1.5" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M21 7.5h5M21 10h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><rect x="3" y="18" width="11" height="12" rx="1.5" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M6 22.5h5M6 25h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><rect x="18" y="18" width="11" height="12" rx="1.5" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M21 22.5h5M21 25h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></button>
17
- <button class="shell-toolbar-btn" id="saveBtn" aria-label="Save Page" data-locked="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M17 21v-8H7v8" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M7 3v5h8" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg></button>
18
- <div class="shell-toolbar-spacer" data-locked="true"></div>
19
- <button class="shell-toolbar-btn" id="settingsBtn" aria-label="Settings" data-locked="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"><path d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z" stroke="currentColor" stroke-width="1.8"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg></button>
20
- </div>
21
- <div class="chat-panel" data-locked="true">
22
- <div class="chat-header" data-locked="true"><span>Page Builder</span><button class="chat-header-close" id="builderClose" aria-label="Close builder" data-locked="true">&times;</button></div>
23
- <div class="chat-messages" id="chatMessages" data-locked="true">
24
- <div class="chat-message">
25
- <p><strong>SynthOS:</strong> You can use the dropdown to select a conversion type, enter your text, and click
26
- "Convert" to see the result.</p>
27
- </div>
28
- </div>
29
- <form action="/" method="POST" id="chatForm" data-locked="true">
30
- <textarea class="chat-input" id="chatInput" name="message" rows="2" placeholder="Type a message..." data-locked="true"></textarea>
31
- </form>
32
- </div>
33
- <div class="viewer-panel" id="viewerPanel" style="display: flex; flex-direction: column;">
34
- <div class="dialog-title" style="max-width: 100%; flex-shrink: 0;">JSON Tools</div>
35
- <div class="dialog-content" style="max-width: 100%; flex: 1; display: flex; flex-direction: column; overflow: hidden;"><select class="conversion-select" id="conversionType" style="flex-shrink: 0;">
36
- <option value="escape">Escape JSON</option>
37
- <option value="unescape">Unescape JSON</option>
38
- <option value="format">Format JSON</option>
39
- <option value="unformat">Unformat JSON</option>
40
- <option value="toYaml">Convert to YAML</option>
41
- <option value="fromYaml" selected="">Convert from YAML</option>
42
- </select><textarea class="multi-line-input" id="userInput" placeholder="Enter your text here..." style="flex: 1; min-height: 150px;"># Sample YAML Configuration
43
- server:
44
- host: localhost
45
- port: 8080
46
- ssl: true
47
-
48
- database:
49
- type: postgresql
50
- connection:
51
- host: db.example.com
52
- port: 5432
53
- name: myapp_db
54
- credentials:
55
- username: admin
56
- password: secret123
57
-
58
- features:
59
- - authentication
60
- - logging
61
- - caching
62
- - rate_limiting
63
-
64
- users:
65
- - name: Alice
66
- role: admin
67
- active: true
68
- - name: Bob
69
- role: user
70
- active: false
71
-
72
- settings:
73
- debug_mode: false
74
- max_connections: 100
75
- timeout_seconds: 30
76
- allowed_origins:
77
- - https://example.com
78
- - https://api.example.com</textarea>
79
- <div class="button-group" style="flex-shrink: 0;">
80
- <div><button class="action-btn convert-btn" id="convertButton">Convert</button><button class="action-btn reset-btn" id="resetButton">Reset</button></div><button class="action-btn copy-btn" id="copyButton" disabled="">Copy to Clipboard</button>
81
- </div>
82
- <div id="resultPanel" class="result-panel" style="flex: 1; min-height: 200px;"></div>
83
- </div>
84
- <div id="loadingOverlay" class="loading-overlay"><div class="spinner"></div></div>
85
- </div>
86
- <div id="instructions" style="display: none;" data-locked="true"></div>
87
- <div id="thoughts" style="display: none;" data-locked="true"></div>
88
- <script id="json-tools-logic">document.getElementById("copyButton").addEventListener("click",function(){const resultPanel=document.getElementById("resultPanel");navigator.clipboard.writeText(resultPanel.innerText).then(()=>alert("Text copied to clipboard!"),err=>console.error("Could not copy text: ",err))}),document.getElementById("convertButton").addEventListener("click",function(){const userInput=document.getElementById("userInput").value,conversionType=document.getElementById("conversionType").value;let result="";try{"escape"===conversionType?result=JSON.stringify(userInput):"unescape"===conversionType?result=JSON.parse(userInput):"format"===conversionType?result=JSON.stringify(JSON.parse(userInput),null,2):"unformat"===conversionType?result=JSON.stringify(JSON.parse(userInput)):"toYaml"===conversionType?result=jsyaml.dump(JSON.parse(userInput),{indent:2}):"fromYaml"===conversionType&&(result=JSON.stringify(jsyaml.load(userInput),null,2))}catch(e){result="Invalid input: "+e.message}document.getElementById("resultPanel").innerText=result,document.getElementById("copyButton").disabled=!1}),document.getElementById("resetButton").addEventListener("click",function(){document.getElementById("userInput").value="",document.getElementById("resultPanel").innerText="",document.getElementById("copyButton").disabled=!0});</script>
89
- <script id="page-helpers" src="/api/page-helpers.js?v=3" data-locked="true"></script>
90
- <script id="page-script" src="/api/page-script.js?v=3" data-locked="true"></script>
1
+ <!DOCTYPE html><html lang="en"><head>
2
+ <meta charset="UTF-8">
3
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
4
+ <title>SynthOS - JSON Tools</title>
5
+ <script id="theme-info" src="/api/theme-info.js" data-locked="true"></script>
6
+ <link id="theme-css" rel="stylesheet" href="/api/theme.css" data-locked="true">
7
+ <style>.dialog-title{font-size:22px;font-weight:700;min-height:58px;padding:14px 20px;line-height:1.25;display:flex;align-items:center;justify-content:center;box-sizing:border-box;background:linear-gradient(135deg,var(--themePrimary),var(--themeDark));color:#fff;border-radius:12px;width:100%;max-width:800px;box-shadow:0 6px 25px rgba(0,0,0,0.15);position:relative;z-index:1}.dialog-content{font-size:14px;color:var(--bodySubtext);padding:15px 0;flex-grow:1;width:100%;max-width:800px;position:relative;z-index:1;overflow-y:auto;display:flex;flex-direction:column;gap:15px}.conversion-select{width:100%;padding:12px 15px;border-radius:10px;border:1px solid var(--bodyDivider);background:var(--inputBackground);color:var(--bodyText);font-size:14px;cursor:pointer;transition:.3s}.conversion-select:focus{outline:0;border-color:var(--themePrimary);box-shadow:0 0 4px rgba(0,0,0,0.15)}.conversion-select option{background:var(--defaultStateBackground);color:var(--bodyText)}.multi-line-input{width:100%;min-height:220px;padding:15px;border-radius:10px;border:1px solid var(--bodyDivider);background:var(--inputBackground);color:var(--bodyText);font-size:14px;font-family:'Courier New',monospace;resize:vertical;transition:.3s}.multi-line-input:focus{outline:0;border-color:var(--themePrimary);box-shadow:0 0 4px rgba(0,0,0,0.15)}.button-group{display:flex;justify-content:space-between;align-items:center;gap:10px}.button-group div{display:flex;gap:10px}.action-btn{padding:12px 24px;border:none;border-radius:25px;font-size:14px;font-weight:600;cursor:pointer;transition:.3s;letter-spacing:1px}.convert-btn{background:linear-gradient(135deg,var(--themePrimary) 0,var(--themeDark) 100%);color:#fff;box-shadow:0 4px 20px rgba(0,0,0,0.15)}.convert-btn:hover{transform:translateY(-2px);box-shadow:0 6px 25px rgba(0,0,0,0.25)}.reset-btn{background:var(--defaultStateBackground);color:var(--bodySubtext);border:1px solid var(--bodyDivider)}.reset-btn:hover{background:var(--bodyStandoutBackground);color:var(--themeSecondary)}.copy-btn{background:var(--defaultStateBackground);color:var(--bodySubtext);border:1px solid var(--bodyDivider)}.copy-btn:hover:not(:disabled){background:var(--bodyStandoutBackground);color:var(--themeSecondary)}.copy-btn:disabled{opacity:.5;cursor:not-allowed}.result-panel{width:100%;min-height:220px;max-height:350px;padding:15px;border-radius:10px;border:1px solid var(--bodyDivider);background:var(--inputBackground);color:var(--themeSecondary);font-size:13px;font-family:'Courier New',monospace;overflow-y:auto;white-space:pre-wrap;word-break:break-all}</style>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js"></script>
9
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/14.1.1/marked.min.js"></script>
10
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
11
+ </head>
12
+
13
+ <body>
14
+ <div class="viewer-panel" id="viewerPanel" style="display: flex; flex-direction: column;">
15
+ <div class="dialog-title" style="max-width: 100%; flex-shrink: 0;">JSON Tools</div>
16
+ <div class="dialog-content" style="max-width: 100%; flex: 1; display: flex; flex-direction: column; overflow: hidden;"><select class="conversion-select" id="conversionType" style="flex-shrink: 0;">
17
+ <option value="escape">Escape JSON</option>
18
+ <option value="unescape">Unescape JSON</option>
19
+ <option value="format">Format JSON</option>
20
+ <option value="unformat">Unformat JSON</option>
21
+ <option value="toYaml">Convert to YAML</option>
22
+ <option value="fromYaml" selected="">Convert from YAML</option>
23
+ </select><textarea class="multi-line-input" id="userInput" placeholder="Enter your text here..." style="flex: 1; min-height: 150px;"># Sample YAML Configuration
24
+ server:
25
+ host: localhost
26
+ port: 8080
27
+ ssl: true
28
+
29
+ database:
30
+ type: postgresql
31
+ connection:
32
+ host: db.example.com
33
+ port: 5432
34
+ name: myapp_db
35
+ credentials:
36
+ username: admin
37
+ password: secret123
38
+
39
+ features:
40
+ - authentication
41
+ - logging
42
+ - caching
43
+ - rate_limiting
44
+
45
+ users:
46
+ - name: Alice
47
+ role: admin
48
+ active: true
49
+ - name: Bob
50
+ role: user
51
+ active: false
52
+
53
+ settings:
54
+ debug_mode: false
55
+ max_connections: 100
56
+ timeout_seconds: 30
57
+ allowed_origins:
58
+ - https://example.com
59
+ - https://api.example.com</textarea>
60
+ <div class="button-group" style="flex-shrink: 0;">
61
+ <div><button class="action-btn convert-btn" id="convertButton">Convert</button><button class="action-btn reset-btn" id="resetButton">Reset</button></div><button class="action-btn copy-btn" id="copyButton" disabled="">Copy to Clipboard</button>
62
+ </div>
63
+ <div id="resultPanel" class="result-panel" style="flex: 1; min-height: 200px;"></div>
64
+ </div>
65
+
66
+ </div>
67
+ <div id="instructions" style="display: none;" data-locked="true"></div>
68
+ <div id="thoughts" style="display: none;" data-locked="true"></div>
69
+ <script id="json-tools-logic">document.getElementById("copyButton").addEventListener("click",function(){const resultPanel=document.getElementById("resultPanel");navigator.clipboard.writeText(resultPanel.innerText).then(()=>alert("Text copied to clipboard!"),err=>console.error("Could not copy text: ",err))}),document.getElementById("convertButton").addEventListener("click",function(){const userInput=document.getElementById("userInput").value,conversionType=document.getElementById("conversionType").value;let result="";try{"escape"===conversionType?result=JSON.stringify(userInput):"unescape"===conversionType?result=JSON.parse(userInput):"format"===conversionType?result=JSON.stringify(JSON.parse(userInput),null,2):"unformat"===conversionType?result=JSON.stringify(JSON.parse(userInput)):"toYaml"===conversionType?result=jsyaml.dump(JSON.parse(userInput),{indent:2}):"fromYaml"===conversionType&&(result=JSON.stringify(jsyaml.load(userInput),null,2))}catch(e){result="Invalid input: "+e.message}document.getElementById("resultPanel").innerText=result,document.getElementById("copyButton").disabled=!1}),document.getElementById("resetButton").addEventListener("click",function(){document.getElementById("userInput").value="",document.getElementById("resultPanel").innerText="",document.getElementById("copyButton").disabled=!0});</script>
70
+
91
71
  </body></html>
@@ -1,10 +1,12 @@
1
- {
2
- "title": "JSON Tools",
3
- "categories": [
4
- "Tools"
5
- ],
6
- "pinned": false,
7
- "showInAll": false,
8
- "pageVersion": 3,
9
- "mode": "unlocked"
10
- }
1
+ {
2
+ "title": "JSON Tools",
3
+ "categories": [
4
+ "Tools"
5
+ ],
6
+ "pinned": false,
7
+ "showInAll": false,
8
+ "pageVersion": 3,
9
+ "mode": "unlocked",
10
+ "greeting": "You can use the dropdown to select a conversion type, enter your text, and click \"Convert\" to see the result.",
11
+ "firstRunGreeting": ""
12
+ }
@@ -0,0 +1 @@
1
+ [{"role":"assistant","content":"Welcome to My Notes — a simple note-taking app! Your notes are listed in the sidebar on the left. Click any note to view or edit it, or tap \"+ New Note\" to create a fresh one. Each note has a rich text editor with formatting tools, and you can save or delete notes using the buttons below the editor. Use the search box to filter notes by title or content. What would you like to do?"}]
@@ -1,132 +1,116 @@
1
- <!DOCTYPE html><html lang="en"><head>
2
- <meta charset="UTF-8">
3
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
4
- <title>SynthOS - Notes</title>
5
- <script id="theme-info" src="/api/theme-info.js" data-locked="true"></script>
6
- <link id="theme-css" rel="stylesheet" href="/api/theme.css" data-locked="true">
7
- <link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor.min.css">
8
- <link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/theme/toastui-editor-dark.min.css">
9
- <script src="https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js"></script>
10
- <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
11
- <style id="notes-layout">
12
- /* Layout-only styles — all component styling comes from FluentLM */
13
- .notes-app {
14
- display: flex;
15
- height: 100%;
16
- width: 100%;
17
- overflow: hidden;
18
- }
19
- .notes-sidebar {
20
- width: 280px;
21
- min-width: 280px;
22
- background: var(--defaultStateBackground);
23
- border-right: 2px solid var(--neutralLight);
24
- display: flex;
25
- flex-direction: column;
26
- }
27
- .notes-sidebar-header {
28
- padding: 16px;
29
- border-bottom: 1px solid var(--neutralLight);
30
- display: flex;
31
- flex-wrap: wrap;
32
- justify-content: space-between;
33
- align-items: center;
34
- gap: 10px;
35
- }
36
- .notes-main {
37
- flex: 1;
38
- display: flex;
39
- flex-direction: column;
40
- min-width: 0;
41
- overflow: hidden;
42
- background: var(--bodyBackground);
43
- }
44
- .notes-list {
45
- flex: 1;
46
- overflow-y: auto;
47
- padding: 8px;
48
- }
49
- .notes-editor {
50
- flex: 1;
51
- display: flex;
52
- flex-direction: column;
53
- padding: 20px;
54
- min-width: 0;
55
- overflow: hidden;
56
- }
57
- .notes-instructions {
58
- flex: 1;
59
- display: flex;
60
- flex-direction: column;
61
- align-items: center;
62
- justify-content: center;
63
- text-align: center;
64
- padding: 40px;
65
- }
66
- .notes-instructions .instructions-icon {
67
- font-size: 64px;
68
- margin-bottom: 20px;
69
- opacity: 0.6;
70
- }
71
- .note-actions {
72
- display: flex;
73
- gap: 12px;
74
- margin-top: 16px;
75
- justify-content: flex-end;
76
- }
77
- #editor-container {
78
- flex: 1;
79
- display: flex;
80
- flex-direction: column;
81
- min-height: 0;
82
- }
83
- #editor-container .toastui-editor-defaultUI {
84
- border: none !important;
85
- border-radius: 10px !important;
86
- overflow: hidden;
87
- flex: 1;
88
- display: flex;
89
- flex-direction: column;
90
- }
91
- #editor-container .toastui-editor-main {
92
- flex: 1;
93
- }
94
- .toastui-editor-mode-switch {
95
- display: none !important;
96
- }
97
- .save-toast {
98
- opacity: 0;
99
- transform: translateY(4px);
100
- transition: opacity .3s, transform .3s;
101
- pointer-events: none;
102
- }
103
- .save-toast.show {
104
- opacity: 1;
105
- transform: translateY(0);
106
- pointer-events: auto;
107
- }
108
- </style></head>
109
-
110
-
111
- <body>
112
- <div class="shell-toolbar" data-locked="true">
113
- <button class="shell-toolbar-btn" id="builderToggle" aria-label="Page Builder" data-locked="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"><path d="M7 18.5H6.2c-1.77 0-3.2-1.43-3.2-3.2V7.7C3 5.93 4.43 4.5 6.2 4.5h11.6c1.77 0 3.2 1.43 3.2 3.2v7.6c0 1.77-1.43 3.2-3.2 3.2H12l-4.2 3.2c-.5.38-1.2.02-1.2-.6V18.5Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><circle cx="8.5" cy="11.5" r="1" fill="currentColor"/><circle cx="12" cy="11.5" r="1" fill="currentColor"/><circle cx="15.5" cy="11.5" r="1" fill="currentColor"/></svg></button>
114
- <button class="shell-toolbar-btn" id="pagesBtn" aria-label="View All Pages" data-locked="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none"><rect x="3" y="3" width="11" height="12" rx="1.5" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M6 7.5h5M6 10h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><rect x="18" y="3" width="11" height="12" rx="1.5" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M21 7.5h5M21 10h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><rect x="3" y="18" width="11" height="12" rx="1.5" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M6 22.5h5M6 25h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/><rect x="18" y="18" width="11" height="12" rx="1.5" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M21 22.5h5M21 25h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></button>
115
- <button class="shell-toolbar-btn" id="saveBtn" aria-label="Save Page" data-locked="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M17 21v-8H7v8" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M7 3v5h8" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg></button>
116
- <div class="shell-toolbar-spacer" data-locked="true"></div>
117
- <button class="shell-toolbar-btn" id="settingsBtn" aria-label="Settings" data-locked="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"><path d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z" stroke="currentColor" stroke-width="1.8"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg></button>
118
- </div>
119
- <div class="chat-panel" data-locked="true">
120
- <div class="chat-header" data-locked="true"><span>Page Builder</span><button class="chat-header-close" id="builderClose" aria-label="Close builder" data-locked="true">&times;</button></div>
121
- <div class="chat-messages" id="chatMessages" data-locked="true"><div class="chat-message"><p><strong>SynthOS:</strong> Welcome to <strong>My Notes</strong> — a simple note-taking app! Your notes are listed in the sidebar on the left. Click any note to view or edit it, or tap "+ New Note" to create a fresh one. Each note has a rich text editor with formatting tools, and you can save or delete notes using the buttons below the editor. Use the search box to filter notes by title or content. What would you like to do?</p></div></div>
122
- <form action="/" method="POST" id="chatForm" data-locked="true">
123
- <textarea class="chat-input" id="chatInput" name="message" rows="2" placeholder="Type a message..." data-locked="true"></textarea>
124
- </form>
125
- </div>
126
- <div class="viewer-panel" id="viewerPanel" style="justify-content: flex-start; align-items: stretch;"><div class="notes-app"><div class="notes-sidebar"><div class="notes-sidebar-header"><span class="flm-text flm-text--large flm-text--bold">My Notes</span><button class="flm-button flm-button--primary" id="addNoteBtn" data-icon="Add">New Note</button><div class="flm-searchbox" style="width:100%;margin-top:8px;"><input class="flm-searchbox-input" id="notesFilterInput" type="text" placeholder="Search notes..."></div></div><div class="notes-list flm-list flm-list--bordered" id="notesList"></div></div><div class="notes-main"><div class="notes-instructions" id="notesInstructions"><div class="instructions-icon"><i class="flm-icon flm-icon--large" data-icon="Edit" style="font-size:64px;opacity:0.6;"></i></div><span class="flm-text flm-text--xLarge flm-text--bold flm-text--block" style="margin-bottom:12px;">Welcome to Notes</span><span class="flm-text flm-text--secondary flm-text--block" style="max-width:300px;line-height:1.5;">Select a note from the sidebar to view or edit it, or click "+ New Note" to create a new one.</span></div><div class="notes-editor" id="notesEditor" style="display: none;"><div class="flm-textfield" style="margin-bottom:12px;"><input class="flm-textfield-input" id="noteTitleInput" placeholder="Note title..." style="font-size:24px;font-weight:600;"></div><div id="editor-container"></div><div id="saveToast" class="flm-messagebar flm-messagebar--success save-toast"></div><div class="note-actions"><button class="flm-button" id="noteDeleteBtn" data-icon="Delete" style="color:var(--errorText);">Delete</button><button class="flm-button" id="noteSaveBtn" data-icon="Save">Save</button></div></div></div></div><div id="deleteConfirmDialog" class="flm-dialog-overlay" data-light-dismiss><div class="flm-dialog" style="max-width:400px;width:90%;"><div class="flm-dialog-header"><h2 class="flm-dialog-title">Delete Note</h2></div><div class="flm-dialog-body"><p class="flm-text">Are you sure you want to delete this note? This action cannot be undone.</p></div><div class="flm-dialog-footer"><div style="flex:1;"></div><button class="flm-button" id="deleteConfirmCancel">Cancel</button><button class="flm-button" id="deleteConfirmOk" style="color:var(--errorText);">Delete</button></div></div></div><div id="unsavedDialog" class="flm-dialog-overlay" data-light-dismiss><div class="flm-dialog" style="max-width:400px;width:90%;"><div class="flm-dialog-header"><h2 class="flm-dialog-title">Unsaved Changes</h2></div><div class="flm-dialog-body"><p class="flm-text">You have unsaved changes. Do you want to discard them?</p></div><div class="flm-dialog-footer"><div style="flex:1;"></div><button class="flm-button" id="unsavedStayBtn">Stay</button><button class="flm-button" id="unsavedDiscardBtn" style="color:var(--errorText);">Discard</button></div></div></div><div id="loadingOverlay" class="loading-overlay"><div class="spinner"></div></div></div>
127
- <div id="instructions" style="display: none;" data-locked="true"></div>
128
- <div id="thoughts" style="display: none;" data-locked="true"></div>
129
- <script id="notes-app-logic">var currentNoteId=null,notes=[],editor=null;var isDirty=false,_loadingNote=false,_pendingNoteId=null;function updateSaveBtn(){var btn=document.getElementById("noteSaveBtn");if(isDirty)btn.classList.add("flm-button--primary");else btn.classList.remove("flm-button--primary")}function showSaveToast(){var t=document.getElementById("saveToast");t.textContent="Note saved";t.classList.add("show");setTimeout(function(){t.classList.remove("show")},2500)}var _tocViews=[];function tocPlugin(ctx){ctx.eventEmitter.listen("change",function(){setTimeout(function(){_tocViews.forEach(function(v){v.rebuild()})},0)});return{toHTMLRenderers:{toc:function(node){return[{type:"openTag",tagName:"div",outerNewLine:true,attributes:{"data-toc":"true"}},{type:"html",content:"<em>Table of Contents</em>"},{type:"closeTag",tagName:"div",outerNewLine:true}]}},wysiwygNodeViews:{customBlock:function(node,view,getPos){if(node.attrs.info!=="toc"){var pre=document.createElement("pre");pre.textContent=node.textContent;return{dom:pre,contentDOM:null,update:function(n){if(n.type.name==="customBlock"&&n.attrs.info!=="toc"){pre.textContent=n.textContent;return true}return false},destroy:function(){},stopEvent:function(){return false}}}var tocDiv=document.createElement("div");tocDiv.setAttribute("data-toc","true");tocDiv.contentEditable="false";tocDiv.style.cssText="padding:4px 0;user-select:none;";var tocView={dom:tocDiv,contentDOM:null,rebuild:function(){var pm=tocDiv.closest(".ProseMirror");if(!pm)return;var blocks=Array.from(pm.children);var idx=blocks.indexOf(tocDiv);if(idx<0)return;var parentLevel=0;for(var i=idx-1;i>=0;i--){var tag=blocks[i].tagName;if(/^H[1-6]$/.test(tag)){parentLevel=parseInt(tag.charAt(1));break}}var items=[];for(var i=idx+1;i<blocks.length;i++){var tag=blocks[i].tagName;if(/^H[1-6]$/.test(tag)){var lvl=parseInt(tag.charAt(1));if(parentLevel>0&&lvl<=parentLevel)break;var txt=blocks[i].textContent.trim();if(txt)items.push({level:lvl,text:txt})}}tocDiv.innerHTML="";if(items.length===0){var p=document.createElement("p");p.style.cssText="color:var(--bodySubtext);font-style:italic;margin:0;font-size:13px;";p.textContent="No headings found in this section";tocDiv.appendChild(p);return}var minLvl=Math.min.apply(null,items.map(function(it){return it.level}));var ul=document.createElement("ul");ul.style.cssText="list-style:none;padding:0;margin:0;";items.forEach(function(it){var li=document.createElement("li");var indent=it.level-minLvl;li.style.cssText="padding:2px 0;"+(indent>0?"margin-left:"+(indent*20)+"px;":"");var slug=it.text.toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,"-");var a=document.createElement("a");a.href="#"+slug;a.textContent=it.text;a.style.cssText="color:var(--themePrimary);text-decoration:none;";li.appendChild(a);ul.appendChild(li)});tocDiv.appendChild(ul)},update:function(n){if(n.type.name!=="customBlock"||n.attrs.info!=="toc")return false;tocView.rebuild();return true},destroy:function(){var i=_tocViews.indexOf(tocView);if(i>=0)_tocViews.splice(i,1)},stopEvent:function(e){return e.type==="mousedown"||e.type==="click"}};_tocViews.push(tocView);setTimeout(function(){tocView.rebuild()},0);return tocView}}}}function initEditor(){var tocBtn=document.createElement("button");tocBtn.className="toastui-editor-toolbar-icons";tocBtn.style.cssText="background-image:none;width:32px;height:32px;padding:0;display:flex;align-items:center;justify-content:center;margin:0;border:none;cursor:pointer;";tocBtn.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none" width="18" height="18" style="display:block;flex-shrink:0;"><rect x="2" y="3" width="2" height="2" rx="0.5" fill="currentColor"/><line x1="6" y1="4" x2="18" y2="4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/><rect x="4" y="8" width="2" height="2" rx="0.5" fill="currentColor"/><line x1="8" y1="9" x2="18" y2="9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/><rect x="4" y="13" width="2" height="2" rx="0.5" fill="currentColor"/><line x1="8" y1="14" x2="18" y2="14" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>';tocBtn.title="Insert Table of Contents";tocBtn.type="button";tocBtn.addEventListener("click",function(){if(!editor)return;var wasWysiwyg=!editor.isMarkdownMode();if(wasWysiwyg)editor.changeMode("markdown");editor.replaceSelection("\n$$toc\n$$\n\n");if(wasWysiwyg)editor.changeMode("wysiwyg")});editor=new toastui.Editor({el:document.querySelector("#editor-container"),height:"100%",initialEditType:"wysiwyg",previewStyle:"vertical",theme:"light"===window.themeInfo.mode?"light":"dark",placeholder:"Start writing your note...",plugins:[[tocPlugin]],toolbarItems:[["heading","bold","italic","strike"],["hr","quote"],["ul","ol","task","indent","outdent"],["table","link","image"],["code","codeblock"],[{el:tocBtn,tooltip:"Insert Table of Contents",name:"toc"}]]});editor.on("change",function(){if(!_loadingNote){isDirty=true;updateSaveBtn()}});var wwEl=document.querySelector(".toastui-editor-ww-container .ProseMirror");if(wwEl)wwEl.addEventListener("click",function(e){var a=e.target.closest("a");if(!a)return;var href=a.getAttribute("href");if(!href||href.charAt(0)!=="#")return;e.preventDefault();e.stopPropagation();var slug=href.slice(1),headings=wwEl.querySelectorAll("h1,h2,h3,h4,h5,h6");for(var i=0;i<headings.length;i++){var hSlug=headings[i].textContent.toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,"-");if(hSlug===slug){headings[i].scrollIntoView({behavior:"smooth",block:"start"});break}}})}async function loadNotes(){try{notes=await synthos.data.list("notes"),renderNotesList()}catch(e){console.error("Failed to load notes:",e),notes=[],renderNotesList()}}function renderNotesList(){var list=document.getElementById("notesList"),filter=(document.getElementById("notesFilterInput").value||"").toLowerCase();list.innerHTML="";var filtered=filter?notes.filter(function(n){return(n.title||"").toLowerCase().includes(filter)}):notes;if(filtered.length===0){list.innerHTML='<div style="padding:20px;text-align:center;color:var(--bodySubtext);font-size:13px;">'+(filter?"No matching notes.":'No notes yet.<br>Click "+ New Note" to create one.')+"</div>"}else{filtered.forEach(function(note){var item=document.createElement("div");item.className="flm-list-item"+(currentNoteId===note.id?" flm-list-item--selected":"");item.style.cssText="cursor:pointer;padding:12px 14px;";item.innerHTML='<div class="flm-list-item-content"><span class="flm-list-item-primary flm-text--semibold flm-text--nowrap">'+escapeHtml(note.title||"Untitled")+"</span></div>";item.onclick=function(){selectNote(note.id)};list.appendChild(item)})}}function escapeHtml(text){var div=document.createElement("div");return div.textContent=text,div.innerHTML}function selectNote(id){if(isDirty&&id!==currentNoteId){_pendingNoteId=id;document.getElementById("unsavedDialog").classList.add("flm-dialog-overlay--open");return}currentNoteId=id;var note=notes.find(function(n){return n.id===id});if(note){document.getElementById("notesInstructions").style.display="none";document.getElementById("notesEditor").style.display="flex";document.getElementById("noteTitleInput").value=note.title||"";if(editor){_loadingNote=true;editor.setMarkdown(note.content||"");_loadingNote=false;setTimeout(function(){var ww=document.querySelector(".toastui-editor-ww-container .ProseMirror");if(ww)ww.scrollTop=0;var sc=document.querySelector(".toastui-editor-ww-container");if(sc)sc.scrollTop=0},0)}isDirty=false;updateSaveBtn();renderNotesList()}}function showInstructions(){currentNoteId=null;document.getElementById("notesInstructions").style.display="flex";document.getElementById("notesEditor").style.display="none";renderNotesList()}document.getElementById("addNoteBtn").onclick=async function(){var newNote={id:crypto.randomUUID(),title:"",content:""};try{var saved=await synthos.data.save("notes",newNote);notes.unshift(saved);selectNote(saved.id)}catch(e){console.error("Failed to create note:",e)}};document.getElementById("noteSaveBtn").onclick=async function(){if(!currentNoteId)return;var title=document.getElementById("noteTitleInput").value,content=editor?editor.getMarkdown():"";try{var updated=await synthos.data.save("notes",{id:currentNoteId,title:title,content:content}),idx=notes.findIndex(function(n){return n.id===currentNoteId});if(idx>=0)notes[idx]=updated;isDirty=false;updateSaveBtn();showSaveToast();renderNotesList()}catch(e){console.error("Failed to save note:",e)}};document.getElementById("noteDeleteBtn").onclick=function(){if(currentNoteId){document.getElementById("deleteConfirmDialog").classList.add("flm-dialog-overlay--open")}};document.getElementById("deleteConfirmCancel").onclick=function(){document.getElementById("deleteConfirmDialog").classList.remove("flm-dialog-overlay--open")};document.getElementById("deleteConfirmOk").onclick=async function(){document.getElementById("deleteConfirmDialog").classList.remove("flm-dialog-overlay--open");if(currentNoteId){try{await synthos.data.remove("notes",currentNoteId);notes=notes.filter(function(n){return n.id!==currentNoteId});showInstructions()}catch(e){console.error("Failed to delete note:",e)}}};document.getElementById("notesFilterInput").addEventListener("input",renderNotesList);document.getElementById("unsavedStayBtn").onclick=function(){document.getElementById("unsavedDialog").classList.remove("flm-dialog-overlay--open");_pendingNoteId=null};document.getElementById("unsavedDiscardBtn").onclick=function(){document.getElementById("unsavedDialog").classList.remove("flm-dialog-overlay--open");isDirty=false;var target=_pendingNoteId;_pendingNoteId=null;selectNote(target)};document.getElementById("noteTitleInput").addEventListener("input",function(){if(!_loadingNote){isDirty=true;updateSaveBtn()}});initEditor();loadNotes();</script>
130
- <script id="page-helpers" src="/api/page-helpers.js?v=3" data-locked="true"></script>
131
- <script id="page-script" src="/api/page-script.js?v=3" data-locked="true"></script>
1
+ <!DOCTYPE html><html lang="en"><head>
2
+ <meta charset="UTF-8">
3
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
4
+ <title>SynthOS - Notes</title>
5
+ <script id="theme-info" src="/api/theme-info.js" data-locked="true"></script>
6
+ <link id="theme-css" rel="stylesheet" href="/api/theme.css" data-locked="true">
7
+ <link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor.min.css">
8
+ <link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/theme/toastui-editor-dark.min.css">
9
+ <script src="https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js"></script>
10
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
11
+ <style id="notes-layout">
12
+ /* Layout-only styles — all component styling comes from FluentLM */
13
+ .notes-app {
14
+ display: flex;
15
+ height: 100%;
16
+ width: 100%;
17
+ overflow: hidden;
18
+ }
19
+ .notes-sidebar {
20
+ width: 280px;
21
+ min-width: 280px;
22
+ background: var(--defaultStateBackground, #faf9f8);
23
+ border-right: 2px solid var(--bodyDivider, #edebe9);
24
+ display: flex;
25
+ flex-direction: column;
26
+ }
27
+ .notes-sidebar-header {
28
+ padding: 16px;
29
+ border-bottom: 1px solid var(--bodyDivider, #edebe9);
30
+ display: flex;
31
+ flex-wrap: wrap;
32
+ justify-content: space-between;
33
+ align-items: center;
34
+ gap: 10px;
35
+ }
36
+ .notes-main {
37
+ flex: 1;
38
+ display: flex;
39
+ flex-direction: column;
40
+ min-width: 0;
41
+ overflow: hidden;
42
+ background: var(--bodyBackground, #ffffff);
43
+ }
44
+ .notes-list {
45
+ flex: 1;
46
+ overflow-y: auto;
47
+ padding: 8px;
48
+ }
49
+ .notes-editor {
50
+ flex: 1;
51
+ display: flex;
52
+ flex-direction: column;
53
+ padding: 20px;
54
+ min-width: 0;
55
+ overflow: hidden;
56
+ }
57
+ .notes-instructions {
58
+ flex: 1;
59
+ display: flex;
60
+ flex-direction: column;
61
+ align-items: center;
62
+ justify-content: center;
63
+ text-align: center;
64
+ padding: 40px;
65
+ }
66
+ .notes-instructions .instructions-icon {
67
+ font-size: 64px;
68
+ margin-bottom: 20px;
69
+ opacity: 0.6;
70
+ }
71
+ .note-actions {
72
+ display: flex;
73
+ gap: 12px;
74
+ margin-top: 16px;
75
+ justify-content: flex-end;
76
+ }
77
+ #editor-container {
78
+ flex: 1;
79
+ display: flex;
80
+ flex-direction: column;
81
+ min-height: 0;
82
+ }
83
+ #editor-container .toastui-editor-defaultUI {
84
+ border: none !important;
85
+ border-radius: 10px !important;
86
+ overflow: hidden;
87
+ flex: 1;
88
+ display: flex;
89
+ flex-direction: column;
90
+ }
91
+ #editor-container .toastui-editor-main {
92
+ flex: 1;
93
+ }
94
+ .toastui-editor-mode-switch {
95
+ display: none !important;
96
+ }
97
+ .save-toast {
98
+ opacity: 0;
99
+ transform: translateY(4px);
100
+ transition: opacity .3s, transform .3s;
101
+ pointer-events: none;
102
+ }
103
+ .save-toast.show {
104
+ opacity: 1;
105
+ transform: translateY(0);
106
+ pointer-events: auto;
107
+ }
108
+ </style></head>
109
+
110
+ <body>
111
+ <div class="viewer-panel" id="viewerPanel" style="justify-content: flex-start; align-items: stretch;"><div class="notes-app"><div class="notes-sidebar"><div class="notes-sidebar-header"><span class="flm-text flm-text--large flm-text--bold">My Notes</span><button class="flm-button flm-button--primary" id="addNoteBtn" data-icon="Add">New Note</button><div class="flm-searchbox" style="width:100%;margin-top:8px;"><input class="flm-searchbox-input" id="notesFilterInput" type="text" placeholder="Search notes..."></div></div><div class="notes-list flm-list flm-list--bordered" id="notesList"></div></div><div class="notes-main"><div class="notes-instructions" id="notesInstructions"><div class="instructions-icon"><i class="flm-icon flm-icon--large" data-icon="Edit" style="font-size:64px;opacity:0.6;"></i></div><span class="flm-text flm-text--xLarge flm-text--bold flm-text--block" style="margin-bottom:12px;">Welcome to Notes</span><span class="flm-text flm-text--secondary flm-text--block" style="max-width:300px;line-height:1.5;">Select a note from the sidebar to view or edit it, or click "+ New Note" to create a new one.</span></div><div class="notes-editor" id="notesEditor" style="display: none;"><div class="flm-textfield" style="margin-bottom:12px;"><input class="flm-textfield-input" id="noteTitleInput" placeholder="Note title..." style="font-size:24px;font-weight:600;"></div><div id="editor-container"></div><div id="saveToast" class="flm-messagebar flm-messagebar--success save-toast"></div><div class="note-actions"><button class="flm-button" id="noteDeleteBtn" data-icon="Delete" style="color:var(--errorText, #d13438);">Delete</button><button class="flm-button" id="noteSaveBtn" data-icon="Save">Save</button></div></div></div></div><div id="deleteConfirmDialog" class="flm-dialog-overlay" data-light-dismiss=""><div class="flm-dialog" style="max-width:400px;width:90%;"><div class="flm-dialog-header"><h2 class="flm-dialog-title">Delete Note</h2></div><div class="flm-dialog-body"><p class="flm-text">Are you sure you want to delete this note? This action cannot be undone.</p></div><div class="flm-dialog-footer"><div style="flex:1;"></div><button class="flm-button" id="deleteConfirmCancel">Cancel</button><button class="flm-button" id="deleteConfirmOk" style="color:var(--errorText, #d13438);">Delete</button></div></div></div><div id="unsavedDialog" class="flm-dialog-overlay" data-light-dismiss=""><div class="flm-dialog" style="max-width:400px;width:90%;"><div class="flm-dialog-header"><h2 class="flm-dialog-title">Unsaved Changes</h2></div><div class="flm-dialog-body"><p class="flm-text">You have unsaved changes. Do you want to discard them?</p></div><div class="flm-dialog-footer"><div style="flex:1;"></div><button class="flm-button" id="unsavedStayBtn">Stay</button><button class="flm-button" id="unsavedDiscardBtn" style="color:var(--errorText, #d13438);">Discard</button></div></div></div></div>
112
+ <div id="instructions" style="display: none;" data-locked="true"></div>
113
+ <div id="thoughts" style="display: none;" data-locked="true"></div>
114
+ <script id="notes-app-logic">var currentNoteId=null,notes=[],editor=null;var isDirty=false,_loadingNote=false,_pendingNoteId=null;function updateSaveBtn(){var btn=document.getElementById("noteSaveBtn");if(isDirty)btn.classList.add("flm-button--primary");else btn.classList.remove("flm-button--primary")}function showSaveToast(){var t=document.getElementById("saveToast");t.textContent="Note saved";t.classList.add("show");setTimeout(function(){t.classList.remove("show")},2500)}var _tocViews=[];function tocPlugin(ctx){ctx.eventEmitter.listen("change",function(){setTimeout(function(){_tocViews.forEach(function(v){v.rebuild()})},0)});return{toHTMLRenderers:{toc:function(node){return[{type:"openTag",tagName:"div",outerNewLine:true,attributes:{"data-toc":"true"}},{type:"html",content:"<em>Table of Contents</em>"},{type:"closeTag",tagName:"div",outerNewLine:true}]}},wysiwygNodeViews:{customBlock:function(node,view,getPos){if(node.attrs.info!=="toc"){var pre=document.createElement("pre");pre.textContent=node.textContent;return{dom:pre,contentDOM:null,update:function(n){if(n.type.name==="customBlock"&&n.attrs.info!=="toc"){pre.textContent=n.textContent;return true}return false},destroy:function(){},stopEvent:function(){return false}}}var tocDiv=document.createElement("div");tocDiv.setAttribute("data-toc","true");tocDiv.contentEditable="false";tocDiv.style.cssText="padding:4px 0;user-select:none;";var tocView={dom:tocDiv,contentDOM:null,rebuild:function(){var pm=tocDiv.closest(".ProseMirror");if(!pm)return;var blocks=Array.from(pm.children);var idx=blocks.indexOf(tocDiv);if(idx<0)return;var parentLevel=0;for(var i=idx-1;i>=0;i--){var tag=blocks[i].tagName;if(/^H[1-6]$/.test(tag)){parentLevel=parseInt(tag.charAt(1));break}}var items=[];for(var i=idx+1;i<blocks.length;i++){var tag=blocks[i].tagName;if(/^H[1-6]$/.test(tag)){var lvl=parseInt(tag.charAt(1));if(parentLevel>0&&lvl<=parentLevel)break;var txt=blocks[i].textContent.trim();if(txt)items.push({level:lvl,text:txt})}}tocDiv.innerHTML="";if(items.length===0){var p=document.createElement("p");p.style.cssText="color:var(--bodySubtext, #605e5c);font-style:italic;margin:0;font-size:13px;";p.textContent="No headings found in this section";tocDiv.appendChild(p);return}var minLvl=Math.min.apply(null,items.map(function(it){return it.level}));var ul=document.createElement("ul");ul.style.cssText="list-style:none;padding:0;margin:0;";items.forEach(function(it){var li=document.createElement("li");var indent=it.level-minLvl;li.style.cssText="padding:2px 0;"+(indent>0?"margin-left:"+(indent*20)+"px;":"");var slug=it.text.toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,"-");var a=document.createElement("a");a.href="#"+slug;a.textContent=it.text;a.style.cssText="color:var(--themePrimary, #0078d4);text-decoration:none;";li.appendChild(a);ul.appendChild(li)});tocDiv.appendChild(ul)},update:function(n){if(n.type.name!=="customBlock"||n.attrs.info!=="toc")return false;tocView.rebuild();return true},destroy:function(){var i=_tocViews.indexOf(tocView);if(i>=0)_tocViews.splice(i,1)},stopEvent:function(e){return e.type==="mousedown"||e.type==="click"}};_tocViews.push(tocView);setTimeout(function(){tocView.rebuild()},0);return tocView}}}}function initEditor(){var tocBtn=document.createElement("button");tocBtn.className="toastui-editor-toolbar-icons";tocBtn.style.cssText="background-image:none;width:32px;height:32px;padding:0;display:flex;align-items:center;justify-content:center;margin:0;border:none;cursor:pointer;";tocBtn.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none" width="18" height="18" style="display:block;flex-shrink:0;"><rect x="2" y="3" width="2" height="2" rx="0.5" fill="currentColor"/><line x1="6" y1="4" x2="18" y2="4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/><rect x="4" y="8" width="2" height="2" rx="0.5" fill="currentColor"/><line x1="8" y1="9" x2="18" y2="9" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/><rect x="4" y="13" width="2" height="2" rx="0.5" fill="currentColor"/><line x1="8" y1="14" x2="18" y2="14" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg>';tocBtn.title="Insert Table of Contents";tocBtn.type="button";tocBtn.addEventListener("click",function(){if(!editor)return;var wasWysiwyg=!editor.isMarkdownMode();if(wasWysiwyg)editor.changeMode("markdown");editor.replaceSelection("\n$$toc\n$$\n\n");if(wasWysiwyg)editor.changeMode("wysiwyg")});editor=new toastui.Editor({el:document.querySelector("#editor-container"),height:"100%",initialEditType:"wysiwyg",previewStyle:"vertical",theme:"light"===window.themeInfo.mode?"light":"dark",placeholder:"Start writing your note...",plugins:[[tocPlugin]],toolbarItems:[["heading","bold","italic","strike"],["hr","quote"],["ul","ol","task","indent","outdent"],["table","link","image"],["code","codeblock"],[{el:tocBtn,tooltip:"Insert Table of Contents",name:"toc"}]]});editor.on("change",function(){if(!_loadingNote){isDirty=true;updateSaveBtn()}});var wwEl=document.querySelector(".toastui-editor-ww-container .ProseMirror");if(wwEl)wwEl.addEventListener("click",function(e){var a=e.target.closest("a");if(!a)return;var href=a.getAttribute("href");if(!href||href.charAt(0)!=="#")return;e.preventDefault();e.stopPropagation();var slug=href.slice(1),headings=wwEl.querySelectorAll("h1,h2,h3,h4,h5,h6");for(var i=0;i<headings.length;i++){var hSlug=headings[i].textContent.toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,"-");if(hSlug===slug){headings[i].scrollIntoView({behavior:"smooth",block:"start"});break}}})}async function loadNotes(){try{notes=await synthos.data.list("notes"),renderNotesList()}catch(e){console.error("Failed to load notes:",e),notes=[],renderNotesList()}}function renderNotesList(){var list=document.getElementById("notesList"),filter=(document.getElementById("notesFilterInput").value||"").toLowerCase();list.innerHTML="";var filtered=filter?notes.filter(function(n){return(n.title||"").toLowerCase().includes(filter)}):notes;if(filtered.length===0){list.innerHTML='<div style="padding:20px;text-align:center;color:var(--bodySubtext, #605e5c);font-size:13px;">'+(filter?"No matching notes.":'No notes yet.<br>Click "+ New Note" to create one.')+"</div>"}else{filtered.forEach(function(note){var item=document.createElement("div");item.className="flm-list-item"+(currentNoteId===note.id?" flm-list-item--selected":"");item.style.cssText="cursor:pointer;padding:12px 14px;";item.innerHTML='<div class="flm-list-item-content"><span class="flm-list-item-primary flm-text--semibold flm-text--nowrap">'+escapeHtml(note.title||"Untitled")+"</span></div>";item.onclick=function(){selectNote(note.id)};list.appendChild(item)})}}function escapeHtml(text){var div=document.createElement("div");return div.textContent=text,div.innerHTML}function selectNote(id){if(isDirty&&id!==currentNoteId){_pendingNoteId=id;document.getElementById("unsavedDialog").classList.add("flm-dialog-overlay--open");return}currentNoteId=id;var note=notes.find(function(n){return n.id===id});if(note){document.getElementById("notesInstructions").style.display="none";document.getElementById("notesEditor").style.display="flex";document.getElementById("noteTitleInput").value=note.title||"";if(editor){_loadingNote=true;editor.setMarkdown(note.content||"");_loadingNote=false;setTimeout(function(){var ww=document.querySelector(".toastui-editor-ww-container .ProseMirror");if(ww)ww.scrollTop=0;var sc=document.querySelector(".toastui-editor-ww-container");if(sc)sc.scrollTop=0},0)}isDirty=false;updateSaveBtn();renderNotesList()}}function showInstructions(){currentNoteId=null;document.getElementById("notesInstructions").style.display="flex";document.getElementById("notesEditor").style.display="none";renderNotesList()}document.getElementById("addNoteBtn").onclick=async function(){var newNote={id:crypto.randomUUID(),title:"",content:""};try{var saved=await synthos.data.save("notes",newNote);notes.unshift(saved);selectNote(saved.id)}catch(e){console.error("Failed to create note:",e)}};document.getElementById("noteSaveBtn").onclick=async function(){if(!currentNoteId)return;var title=document.getElementById("noteTitleInput").value,content=editor?editor.getMarkdown():"";try{var updated=await synthos.data.save("notes",{id:currentNoteId,title:title,content:content}),idx=notes.findIndex(function(n){return n.id===currentNoteId});if(idx>=0)notes[idx]=updated;isDirty=false;updateSaveBtn();showSaveToast();renderNotesList()}catch(e){console.error("Failed to save note:",e)}};document.getElementById("noteDeleteBtn").onclick=function(){if(currentNoteId){document.getElementById("deleteConfirmDialog").classList.add("flm-dialog-overlay--open")}};document.getElementById("deleteConfirmCancel").onclick=function(){document.getElementById("deleteConfirmDialog").classList.remove("flm-dialog-overlay--open")};document.getElementById("deleteConfirmOk").onclick=async function(){document.getElementById("deleteConfirmDialog").classList.remove("flm-dialog-overlay--open");if(currentNoteId){try{await synthos.data.remove("notes",currentNoteId);notes=notes.filter(function(n){return n.id!==currentNoteId});showInstructions()}catch(e){console.error("Failed to delete note:",e)}}};document.getElementById("notesFilterInput").addEventListener("input",renderNotesList);document.getElementById("unsavedStayBtn").onclick=function(){document.getElementById("unsavedDialog").classList.remove("flm-dialog-overlay--open");_pendingNoteId=null};document.getElementById("unsavedDiscardBtn").onclick=function(){document.getElementById("unsavedDialog").classList.remove("flm-dialog-overlay--open");isDirty=false;var target=_pendingNoteId;_pendingNoteId=null;selectNote(target)};document.getElementById("noteTitleInput").addEventListener("input",function(){if(!_loadingNote){isDirty=true;updateSaveBtn()}});initEditor();loadNotes();</script>
115
+
132
116
  </body></html>
@@ -1,12 +1,14 @@
1
- {
2
- "title": "My Notes",
3
- "categories": [
4
- "Apps"
5
- ],
6
- "pinned": true,
7
- "showInAll": true,
8
- "createdDate": "2026-02-13T04:35:31.170Z",
9
- "lastModified": "2026-02-14T23:52:47.462Z",
10
- "pageVersion": 3,
11
- "mode": "locked"
12
- }
1
+ {
2
+ "title": "My Notes",
3
+ "categories": [
4
+ "Apps"
5
+ ],
6
+ "pinned": true,
7
+ "showInAll": true,
8
+ "createdDate": "2026-02-13T04:35:31.170Z",
9
+ "lastModified": "2026-02-14T23:52:47.462Z",
10
+ "pageVersion": 3,
11
+ "mode": "locked",
12
+ "greeting": "Welcome to My Notes — a simple note-taking app! Your notes are listed in the sidebar on the left. Click any note to view or edit it, or tap \"+ New Note\" to create a fresh one. Each note has a rich text editor with formatting tools, and you can save or delete notes using the buttons below the editor. Use the search box to filter notes by title or content. What would you like to do?",
13
+ "firstRunGreeting": ""
14
+ }
@@ -0,0 +1 @@
1
+ [{"role":"assistant","content":"NEON ASTEROIDS \u2014 Destroy asteroids, dodge saucers, collect power-ups. Controls: WASD/Arrows to move, Space to fire, H for hyperspace, P to pause. Gamepad supported. Up to 4 players in Pass & Play mode."}]