flea-qml 0.0.0-stage → 0.2.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 (637) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +511 -2
  3. package/THIRD-PARTY-NOTICES.md +29 -0
  4. package/demos/App.java +5 -0
  5. package/demos/Dockerfile +4 -0
  6. package/demos/Main.kt +3 -0
  7. package/demos/Program.cs +1 -0
  8. package/demos/README.md +12 -0
  9. package/demos/app.dart +3 -0
  10. package/demos/app.deb +0 -0
  11. package/demos/app.js +1 -0
  12. package/demos/backup.tar +0 -0
  13. package/demos/budget.xlsx +0 -0
  14. package/demos/build.sh +2 -0
  15. package/demos/bundle.zip +0 -0
  16. package/demos/clip.mp4 +0 -0
  17. package/demos/data.sqlite +0 -0
  18. package/demos/disk.iso +0 -0
  19. package/demos/engine.cpp +5 -0
  20. package/demos/firmware.bin +0 -0
  21. package/demos/flake.nix +4 -0
  22. package/demos/folder/inside.txt +1 -0
  23. package/demos/font.ttf +0 -0
  24. package/demos/index.html +5 -0
  25. package/demos/index.php +2 -0
  26. package/demos/init.lua +1 -0
  27. package/demos/letter.docx +0 -0
  28. package/demos/lib.rs +3 -0
  29. package/demos/main.c +6 -0
  30. package/demos/main.h +3 -0
  31. package/demos/math-and-diagrams.md +200 -0
  32. package/demos/notes.tar.gz +0 -0
  33. package/demos/notes.txt +3 -0
  34. package/demos/photo.png +0 -0
  35. package/demos/program +2 -0
  36. package/demos/report.pdf +32 -0
  37. package/demos/script.py +1 -0
  38. package/demos/server.go +7 -0
  39. package/demos/settings.json +4 -0
  40. package/demos/slides.pptx +0 -0
  41. package/demos/song.mp3 +0 -0
  42. package/demos/style.css +4 -0
  43. package/demos/tool.rb +1 -0
  44. package/demos/types.ts +2 -0
  45. package/docs/pele.md +23 -0
  46. package/docs/protocol.md +3420 -0
  47. package/docs/temml.md +63 -0
  48. package/index.js +107 -0
  49. package/package.json +34 -4
  50. package/src/archive.js +407 -0
  51. package/src/archiveops.js +728 -0
  52. package/src/backend.js +369 -0
  53. package/src/bulkrename.js +95 -0
  54. package/src/clip-host.js +76 -0
  55. package/src/clip.js +462 -0
  56. package/src/code.js +168 -0
  57. package/src/compare.js +74 -0
  58. package/src/create.js +128 -0
  59. package/src/dirsize.js +147 -0
  60. package/src/figure-svg.js +530 -0
  61. package/src/figure-thread.js +23 -0
  62. package/src/figure.js +132 -0
  63. package/src/find.js +55 -0
  64. package/src/flea.js +39 -0
  65. package/src/fsinfo.js +39 -0
  66. package/src/highlight.js +141 -0
  67. package/src/html.js +52 -0
  68. package/src/kinds.js +89 -0
  69. package/src/listing.js +130 -0
  70. package/src/markdown-html.js +317 -0
  71. package/src/mathml.js +186 -0
  72. package/src/menu.js +180 -0
  73. package/src/meta.js +135 -0
  74. package/src/office.js +810 -0
  75. package/src/order.js +100 -0
  76. package/src/peek.js +49 -0
  77. package/src/pele-wrapper.js +695 -0
  78. package/src/permissions.js +180 -0
  79. package/src/places.js +313 -0
  80. package/src/preview-language.js +10 -0
  81. package/src/terminal-server.js +95 -0
  82. package/src/terminal-shell.js +26 -0
  83. package/src/transfer.js +669 -0
  84. package/src/trash-record.js +41 -0
  85. package/src/trash.js +210 -0
  86. package/src/trashbrowse.js +327 -0
  87. package/src/uistate.js +393 -0
  88. package/src/uistore.js +168 -0
  89. package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
  90. package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
  91. package/src/vendor/LICENSES/MIT-katex.txt +21 -0
  92. package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
  93. package/src/vendor/LICENSES/MIT-pele.txt +40 -0
  94. package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
  95. package/src/vendor/LICENSES/MIT-temml.txt +21 -0
  96. package/src/vendor/pele.js +145 -0
  97. package/src/vendor/temml.mjs +14708 -0
  98. package/src/watch.js +98 -0
  99. package/src/wayland/client.js +109 -0
  100. package/src/wayland/protocol.js +55 -0
  101. package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
  102. package/src/wayland/protocols/wayland.xml +3248 -0
  103. package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
  104. package/src/wayland/resource-io.js +6 -0
  105. package/src/wayland/socket-discovery.js +26 -0
  106. package/src/wayland/transport-posix.js +120 -0
  107. package/src/wayland/transport-win32.js +11 -0
  108. package/src/wayland/transport.js +3 -0
  109. package/src/wayland/win32-resources.js +80 -0
  110. package/src/wayland/win32-wire.js +62 -0
  111. package/test/archive.test.js +80 -0
  112. package/test/bench-markdown-scroll.mjs +190 -0
  113. package/test/clip-host.test.js +113 -0
  114. package/test/code-preview.test.js +35 -0
  115. package/test/compare-ui-paths.test.js +24 -0
  116. package/test/compare.test.js +54 -0
  117. package/test/delete-trash.test.js +67 -0
  118. package/test/dirsize.test.js +138 -0
  119. package/test/file-ops.test.js +307 -0
  120. package/test/file-url.test.js +24 -0
  121. package/test/find-contents.test.js +161 -0
  122. package/test/find-input.test.js +66 -0
  123. package/test/fixtures/pele-parity.json +1006 -0
  124. package/test/highlight-launcher.test.js +35 -0
  125. package/test/html-preview.test.js +22 -0
  126. package/test/input.test.js +15 -0
  127. package/test/keymap.test.js +26 -0
  128. package/test/language-icons.test.js +36 -0
  129. package/test/launcher.test.js +51 -0
  130. package/test/manual-archive-here-ui.mjs +47 -0
  131. package/test/manual-code-scroll.mjs +28 -0
  132. package/test/manual-column-scroll.mjs +24 -0
  133. package/test/manual-compare-ui.mjs +20 -0
  134. package/test/manual-find-status.mjs +37 -0
  135. package/test/manual-folder-focus.mjs +63 -0
  136. package/test/manual-html-security.mjs +23 -0
  137. package/test/manual-html-ui.mjs +30 -0
  138. package/test/manual-syntax-preview.mjs +26 -0
  139. package/test/manual-terminal-lifecycle.mjs +42 -0
  140. package/test/manual-terminal-navigation.mjs +48 -0
  141. package/test/manual-terminal-ui.mjs +47 -0
  142. package/test/manual-trash-ui.mjs +86 -0
  143. package/test/markdown-diagrams.test.js +93 -0
  144. package/test/markdown-html.test.js +105 -0
  145. package/test/mathml.test.js +92 -0
  146. package/test/menu-transfer.test.js +57 -0
  147. package/test/office-preview.test.js +154 -0
  148. package/test/pele-parity.test.js +28 -0
  149. package/test/places.test.js +134 -0
  150. package/test/preview-keys.test.js +60 -0
  151. package/test/preview-language.test.js +22 -0
  152. package/test/status-filename.test.js +20 -0
  153. package/test/transfer-replace-merge.test.js +187 -0
  154. package/test/trash-address.test.js +23 -0
  155. package/test/trash-view.test.js +37 -0
  156. package/test/trashbrowse.test.js +135 -0
  157. package/ui/AboutFacts.qml +78 -0
  158. package/ui/ArchiveCards.qml +95 -0
  159. package/ui/ArchiveCompressDialog.qml +378 -0
  160. package/ui/ArchiveHereConfirm.qml +127 -0
  161. package/ui/ArchivePasswordDialog.qml +257 -0
  162. package/ui/Backend.qml +775 -0
  163. package/ui/BulkOldNames.qml +47 -0
  164. package/ui/BulkRenameDialog.qml +380 -0
  165. package/ui/CardFrame.qml +67 -0
  166. package/ui/CardScroll.qml +79 -0
  167. package/ui/CheckBox.qml +73 -0
  168. package/ui/ChromeBar.qml +360 -0
  169. package/ui/ChromeButton.qml +131 -0
  170. package/ui/ChromeModes.qml +43 -0
  171. package/ui/CodeLines.qml +256 -0
  172. package/ui/CodeRefusal.qml +52 -0
  173. package/ui/CollideConfirm.qml +147 -0
  174. package/ui/CollideHost.qml +167 -0
  175. package/ui/ColumnPane.qml +525 -0
  176. package/ui/ColumnRow.qml +380 -0
  177. package/ui/ColumnsArea.qml +594 -0
  178. package/ui/ColumnsLanding.qml +147 -0
  179. package/ui/CompareView.qml +321 -0
  180. package/ui/ContextMenu.qml +743 -0
  181. package/ui/ConvertDialog.qml +456 -0
  182. package/ui/CountedWorker.qml +7 -0
  183. package/ui/Crumb.qml +64 -0
  184. package/ui/CrumbDrop.qml +25 -0
  185. package/ui/CsvTable.qml +394 -0
  186. package/ui/CursorMark.qml +41 -0
  187. package/ui/DefaultClaim.qml +130 -0
  188. package/ui/DeviceLock.qml +47 -0
  189. package/ui/DeviceMounts.qml +540 -0
  190. package/ui/DialogButton.qml +150 -0
  191. package/ui/DialogField.qml +147 -0
  192. package/ui/DialogHeader.qml +31 -0
  193. package/ui/DialogScrim.qml +20 -0
  194. package/ui/DialogTitle.qml +37 -0
  195. package/ui/Divider.qml +9 -0
  196. package/ui/DropInto.qml +126 -0
  197. package/ui/DropTarget.qml +35 -0
  198. package/ui/DropboxMark.qml +60 -0
  199. package/ui/EmptyState.qml +150 -0
  200. package/ui/EscapeHint.qml +11 -0
  201. package/ui/FactsTable.qml +54 -0
  202. package/ui/FastScrollHandler.qml +476 -0
  203. package/ui/FatNamesConfirm.qml +157 -0
  204. package/ui/Favourites.qml +143 -0
  205. package/ui/FigureService.qml +120 -0
  206. package/ui/FileDrag.qml +267 -0
  207. package/ui/FilterStrip.qml +133 -0
  208. package/ui/FitMetrics.qml +22 -0
  209. package/ui/FlashDriveRows.qml +137 -0
  210. package/ui/FlashHost.qml +72 -0
  211. package/ui/FlashImageRow.qml +104 -0
  212. package/ui/FlashRunner.qml +119 -0
  213. package/ui/FlashStepRow.qml +172 -0
  214. package/ui/FlashStrip.qml +38 -0
  215. package/ui/FlashView.qml +397 -0
  216. package/ui/FleaMark.qml +88 -0
  217. package/ui/FlyoutFade.qml +23 -0
  218. package/ui/FontPane.qml +170 -0
  219. package/ui/Glass.qml +114 -0
  220. package/ui/GlassTagger.qml +59 -0
  221. package/ui/Glyph.qml +64 -0
  222. package/ui/GlyphSolid.qml +22 -0
  223. package/ui/GridArea.qml +664 -0
  224. package/ui/GridTile.qml +325 -0
  225. package/ui/GvfsBridge.qml +164 -0
  226. package/ui/Header.qml +433 -0
  227. package/ui/HoverTimers.qml +39 -0
  228. package/ui/HtmlClip.qml +30 -0
  229. package/ui/HtmlPane.qml +63 -0
  230. package/ui/HyprlandMark.qml +45 -0
  231. package/ui/Ipc.qml +1005 -0
  232. package/ui/IpcControls.qml +7 -0
  233. package/ui/IpcMenuState.qml +48 -0
  234. package/ui/IpcPreviewState.qml +185 -0
  235. package/ui/JumpPath.qml +51 -0
  236. package/ui/KeymapSheet.qml +561 -0
  237. package/ui/KeymapSheetResult.qml +89 -0
  238. package/ui/KindStack.qml +40 -0
  239. package/ui/LangMark.qml +51 -0
  240. package/ui/LangMarkLoader.qml +26 -0
  241. package/ui/List.qml +480 -0
  242. package/ui/LoadingState.qml +54 -0
  243. package/ui/LocalSend.qml +56 -0
  244. package/ui/LocalSendMark.qml +73 -0
  245. package/ui/MarkdownBlockView.qml +311 -0
  246. package/ui/MarkdownBlocks.qml +35 -0
  247. package/ui/MarkdownFigure.qml +254 -0
  248. package/ui/MarkdownImages.qml +72 -0
  249. package/ui/MarkdownList.qml +81 -0
  250. package/ui/MarkdownMathsText.qml +97 -0
  251. package/ui/MarkdownPane.qml +83 -0
  252. package/ui/MarkdownPictures.qml +41 -0
  253. package/ui/MarkdownQuote.qml +52 -0
  254. package/ui/MarkdownRemote.qml +82 -0
  255. package/ui/MarkdownSource.qml +155 -0
  256. package/ui/MarkdownTable.qml +222 -0
  257. package/ui/MarkdownTableScroll.qml +64 -0
  258. package/ui/MarkdownTableWheel.qml +126 -0
  259. package/ui/MarkdownText.qml +87 -0
  260. package/ui/MarkdownWorker.js +132 -0
  261. package/ui/MatchText.qml +99 -0
  262. package/ui/MediaSession.qml +38 -0
  263. package/ui/MediaSound.qml +26 -0
  264. package/ui/MediaStrip.qml +191 -0
  265. package/ui/MediaTrack.qml +36 -0
  266. package/ui/MediaVolume.qml +54 -0
  267. package/ui/MenuActionDialog.qml +396 -0
  268. package/ui/MenuEdgeFade.qml +24 -0
  269. package/ui/MenuHost.qml +227 -0
  270. package/ui/MenuRow.qml +351 -0
  271. package/ui/MountListing.qml +100 -0
  272. package/ui/NetworkDialog.qml +435 -0
  273. package/ui/NetworkForm.qml +426 -0
  274. package/ui/NetworkMounts.qml +913 -0
  275. package/ui/NetworkPlaces.qml +127 -0
  276. package/ui/OpenWithDialog.qml +613 -0
  277. package/ui/Opener.qml +95 -0
  278. package/ui/Pane.qml +1320 -0
  279. package/ui/PaneMenuActions.qml +527 -0
  280. package/ui/PanePath.qml +90 -0
  281. package/ui/PaneRail.qml +268 -0
  282. package/ui/PaneStates.qml +88 -0
  283. package/ui/PaneSwap.qml +339 -0
  284. package/ui/PaneWire.qml +601 -0
  285. package/ui/ParkedWait.qml +9 -0
  286. package/ui/PathEntry.qml +186 -0
  287. package/ui/PathJump.qml +400 -0
  288. package/ui/PdfViewer.qml +297 -0
  289. package/ui/PermissionsDialog.qml +658 -0
  290. package/ui/PermissionsHeadings.qml +31 -0
  291. package/ui/PhoneMounts.qml +67 -0
  292. package/ui/PickerAnswers.qml +75 -0
  293. package/ui/PickerBox.qml +26 -0
  294. package/ui/PickerChrome.qml +295 -0
  295. package/ui/PickerFilter.qml +97 -0
  296. package/ui/PickerGrid.qml +308 -0
  297. package/ui/PickerHeader.qml +28 -0
  298. package/ui/PickerLifecycle.qml +27 -0
  299. package/ui/PickerList.qml +218 -0
  300. package/ui/PickerListing.qml +149 -0
  301. package/ui/PickerPathBar.qml +127 -0
  302. package/ui/PickerPlaces.qml +189 -0
  303. package/ui/PickerRecent.qml +92 -0
  304. package/ui/PickerSave.qml +101 -0
  305. package/ui/PickerSelection.qml +155 -0
  306. package/ui/PickerWindow.qml +846 -0
  307. package/ui/PowerSectorsReader.qml +10 -0
  308. package/ui/PrebuildDriver.qml +146 -0
  309. package/ui/Preview.qml +1005 -0
  310. package/ui/PreviewAnimation.qml +24 -0
  311. package/ui/PreviewArchive.qml +91 -0
  312. package/ui/PreviewColumn.qml +553 -0
  313. package/ui/PreviewEdge.qml +63 -0
  314. package/ui/PreviewFacts.qml +30 -0
  315. package/ui/PreviewFactsLine.qml +34 -0
  316. package/ui/PreviewHtml.qml +233 -0
  317. package/ui/PreviewImage.qml +253 -0
  318. package/ui/PreviewImagePan.qml +13 -0
  319. package/ui/PreviewImageSharp.qml +32 -0
  320. package/ui/PreviewLines.qml +106 -0
  321. package/ui/PreviewMarkdown.qml +706 -0
  322. package/ui/PreviewMedia.qml +250 -0
  323. package/ui/PreviewPdf.qml +482 -0
  324. package/ui/PreviewScroll.qml +201 -0
  325. package/ui/PreviewSwap.qml +335 -0
  326. package/ui/PreviewText.qml +149 -0
  327. package/ui/ProtocolChip.qml +18 -0
  328. package/ui/QuickLookArchive.qml +41 -0
  329. package/ui/QuickLookBar.qml +103 -0
  330. package/ui/QuickLookPrepare.qml +355 -0
  331. package/ui/QuickLookSwap.qml +10 -0
  332. package/ui/QuickLookWarm.qml +65 -0
  333. package/ui/RailDrop.qml +155 -0
  334. package/ui/RailHeading.qml +19 -0
  335. package/ui/RailPlaces.qml +38 -0
  336. package/ui/RailTrashRow.qml +67 -0
  337. package/ui/RenameField.qml +353 -0
  338. package/ui/RendererRetry.qml +11 -0
  339. package/ui/ResizeHandle.qml +52 -0
  340. package/ui/Reveal.qml +54 -0
  341. package/ui/Row.qml +476 -0
  342. package/ui/RowDrag.qml +213 -0
  343. package/ui/RowDropTarget.qml +27 -0
  344. package/ui/RunCard.qml +286 -0
  345. package/ui/Scripts.qml +65 -0
  346. package/ui/SearchStrip.qml +232 -0
  347. package/ui/SelectionBand.qml +140 -0
  348. package/ui/SelectionPreview.qml +370 -0
  349. package/ui/SettingsFavourite.qml +122 -0
  350. package/ui/SettingsGroup.qml +96 -0
  351. package/ui/SettingsHint.qml +12 -0
  352. package/ui/SettingsMetrics.qml +29 -0
  353. package/ui/SettingsPane.qml +178 -0
  354. package/ui/SettingsPanel.qml +547 -0
  355. package/ui/SettingsRail.qml +128 -0
  356. package/ui/SettingsRow.qml +409 -0
  357. package/ui/SettingsRuler.qml +85 -0
  358. package/ui/SettingsSegment.qml +85 -0
  359. package/ui/ShareBrowser.qml +113 -0
  360. package/ui/ShareLink.qml +67 -0
  361. package/ui/ShelfPins.qml +101 -0
  362. package/ui/Sidebar.qml +728 -0
  363. package/ui/SidebarRow.qml +358 -0
  364. package/ui/Spinner.qml +60 -0
  365. package/ui/StableModel.qml +89 -0
  366. package/ui/StateMessage.qml +84 -0
  367. package/ui/StatusBar.qml +512 -0
  368. package/ui/StatusFileName.qml +27 -0
  369. package/ui/TabBar.qml +673 -0
  370. package/ui/TabDragGeometry.qml +60 -0
  371. package/ui/TagMenuMark.qml +52 -0
  372. package/ui/TagRailSection.qml +53 -0
  373. package/ui/TagSlot.qml +40 -0
  374. package/ui/TagState.qml +150 -0
  375. package/ui/TagSwatch.qml +28 -0
  376. package/ui/Taildrop.qml +86 -0
  377. package/ui/TailscaleMark.qml +50 -0
  378. package/ui/TerminalService.qml +69 -0
  379. package/ui/TerminalTab.qml +48 -0
  380. package/ui/TerminalTabs.qml +27 -0
  381. package/ui/Theme.qml +460 -0
  382. package/ui/ThemeColors.qml +43 -0
  383. package/ui/TransferCard.qml +239 -0
  384. package/ui/TrashConfirm.qml +129 -0
  385. package/ui/TrashDropHandler.qml +11 -0
  386. package/ui/TrashHost.qml +202 -0
  387. package/ui/TrashMonitor.qml +30 -0
  388. package/ui/TrashToolbar.qml +19 -0
  389. package/ui/TrashView.qml +492 -0
  390. package/ui/UnlockDialog.qml +450 -0
  391. package/ui/UnlockHost.qml +206 -0
  392. package/ui/UpdateCheck.qml +97 -0
  393. package/ui/UserDirs.qml +25 -0
  394. package/ui/ViewState.qml +565 -0
  395. package/ui/ViewportScrollBar.qml +195 -0
  396. package/ui/ViewportScrollBars.qml +25 -0
  397. package/ui/WebPreview.qml +33 -0
  398. package/ui/WebPreviewView.qml +26 -0
  399. package/ui/WindowBody.qml +829 -0
  400. package/ui/WindowDrag.qml +35 -0
  401. package/ui/boot/Commons/AudioNodes.qml +50 -0
  402. package/ui/boot/Commons/AudioNodesModel.js +96 -0
  403. package/ui/boot/Commons/Border.qml +243 -0
  404. package/ui/boot/Commons/BorderGeometry.js +373 -0
  405. package/ui/boot/Commons/Color.qml +258 -0
  406. package/ui/boot/Commons/I18n.qml +118 -0
  407. package/ui/boot/Commons/InputDevices.qml +112 -0
  408. package/ui/boot/Commons/InputMethodState.qml +38 -0
  409. package/ui/boot/Commons/IpcRegistry.qml +77 -0
  410. package/ui/boot/Commons/Numbers.js +19 -0
  411. package/ui/boot/Commons/Plural.js +91 -0
  412. package/ui/boot/Commons/ShellIpc.qml +12 -0
  413. package/ui/boot/Commons/Style.qml +561 -0
  414. package/ui/boot/Commons/Translations.qml +100 -0
  415. package/ui/boot/Commons/UntypedInput.qml +152 -0
  416. package/ui/boot/Commons/Util.qml +188 -0
  417. package/ui/boot/Commons/qmldir +13 -0
  418. package/ui/boot/LICENSE-omarchy +20 -0
  419. package/ui/boot/Ui/BackgroundMedia.qml +49 -0
  420. package/ui/boot/Ui/BarIconButton.qml +106 -0
  421. package/ui/boot/Ui/BarIconContent.qml +38 -0
  422. package/ui/boot/Ui/BarIndicator.qml +53 -0
  423. package/ui/boot/Ui/BarWidget.qml +50 -0
  424. package/ui/boot/Ui/BorderOverlay.qml +54 -0
  425. package/ui/boot/Ui/BorderSurface.qml +40 -0
  426. package/ui/boot/Ui/Button.qml +224 -0
  427. package/ui/boot/Ui/ButtonGroup.qml +131 -0
  428. package/ui/boot/Ui/ConfirmDialog.qml +134 -0
  429. package/ui/boot/Ui/CursorSurface.qml +42 -0
  430. package/ui/boot/Ui/Dropdown.qml +245 -0
  431. package/ui/boot/Ui/FilterInput.qml +26 -0
  432. package/ui/boot/Ui/IconContentBounds.qml +141 -0
  433. package/ui/boot/Ui/KeyboardPanel.qml +453 -0
  434. package/ui/boot/Ui/MultiSelect.qml +624 -0
  435. package/ui/boot/Ui/NumberField.qml +86 -0
  436. package/ui/boot/Ui/OpticalGlyph.qml +68 -0
  437. package/ui/boot/Ui/OverlayWindow.qml +102 -0
  438. package/ui/boot/Ui/Panel.qml +60 -0
  439. package/ui/boot/Ui/PanelActionButton.qml +105 -0
  440. package/ui/boot/Ui/PanelController.qml +16 -0
  441. package/ui/boot/Ui/PanelHero.qml +112 -0
  442. package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
  443. package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
  444. package/ui/boot/Ui/PanelSeparator.qml +19 -0
  445. package/ui/boot/Ui/PanelSlider.qml +156 -0
  446. package/ui/boot/Ui/PanelToolTip.qml +50 -0
  447. package/ui/boot/Ui/PluginBarApi.qml +89 -0
  448. package/ui/boot/Ui/PointerMoveGate.qml +54 -0
  449. package/ui/boot/Ui/PopupCard.qml +181 -0
  450. package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
  451. package/ui/boot/Ui/SearchableDropdown.qml +354 -0
  452. package/ui/boot/Ui/SizedImage.qml +125 -0
  453. package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
  454. package/ui/boot/Ui/TextField.qml +58 -0
  455. package/ui/boot/Ui/Toggle.qml +118 -0
  456. package/ui/boot/Ui/ToggleSwitch.qml +115 -0
  457. package/ui/boot/Ui/WidgetButton.qml +172 -0
  458. package/ui/boot/Ui/qmldir +41 -0
  459. package/ui/boot/fleatab.qml +50 -0
  460. package/ui/boot/picker.qml +39 -0
  461. package/ui/boot/shell.qml +131 -0
  462. package/ui/boot/tabtearoff.qml +51 -0
  463. package/ui/js/Anchor.js +379 -0
  464. package/ui/js/AnchorHold.js +162 -0
  465. package/ui/js/Archive.js +157 -0
  466. package/ui/js/ArchiveCard.js +44 -0
  467. package/ui/js/ArchiveOps.js +44 -0
  468. package/ui/js/BackReturn.js +118 -0
  469. package/ui/js/BulkRename.js +100 -0
  470. package/ui/js/Buttons.js +54 -0
  471. package/ui/js/ChromeKeys.js +116 -0
  472. package/ui/js/ClipMarks.js +73 -0
  473. package/ui/js/ClipSelection.js +67 -0
  474. package/ui/js/Clipboard.js +179 -0
  475. package/ui/js/Cloud.js +97 -0
  476. package/ui/js/CodeRuns.js +72 -0
  477. package/ui/js/Collide.js +212 -0
  478. package/ui/js/ColumnFit.js +28 -0
  479. package/ui/js/ColumnMenu.js +111 -0
  480. package/ui/js/Columns.js +298 -0
  481. package/ui/js/ColumnsCarry.js +103 -0
  482. package/ui/js/Compare.js +74 -0
  483. package/ui/js/Contrast.js +157 -0
  484. package/ui/js/ControlReader.js +42 -0
  485. package/ui/js/Convert.js +52 -0
  486. package/ui/js/CopyAs.js +52 -0
  487. package/ui/js/Crumbs.js +178 -0
  488. package/ui/js/Csv.js +231 -0
  489. package/ui/js/Density.js +44 -0
  490. package/ui/js/Devices.js +440 -0
  491. package/ui/js/DirSizes.js +180 -0
  492. package/ui/js/Drag.js +360 -0
  493. package/ui/js/DragOut.js +166 -0
  494. package/ui/js/DropDev.js +52 -0
  495. package/ui/js/Dropbox.js +41 -0
  496. package/ui/js/Eject.js +217 -0
  497. package/ui/js/Errors.js +188 -0
  498. package/ui/js/ExtThumbs.js +115 -0
  499. package/ui/js/Facts.js +402 -0
  500. package/ui/js/FigureDate.js +14 -0
  501. package/ui/js/Filter.js +285 -0
  502. package/ui/js/Find.js +46 -0
  503. package/ui/js/Flash.js +184 -0
  504. package/ui/js/FlashCard.js +79 -0
  505. package/ui/js/FlashEndings.js +125 -0
  506. package/ui/js/FlashPane.js +116 -0
  507. package/ui/js/FleaBin.js +12 -0
  508. package/ui/js/Focus.js +504 -0
  509. package/ui/js/FolderSorts.js +108 -0
  510. package/ui/js/FolderViews.js +44 -0
  511. package/ui/js/Format.js +314 -0
  512. package/ui/js/Fuzzy.js +141 -0
  513. package/ui/js/GlassTag.js +72 -0
  514. package/ui/js/Grid.js +33 -0
  515. package/ui/js/GridGeometry.js +90 -0
  516. package/ui/js/GridNames.js +153 -0
  517. package/ui/js/GvfsBridge.js +200 -0
  518. package/ui/js/HostClipboard.js +29 -0
  519. package/ui/js/Icons.js +218 -0
  520. package/ui/js/Input.js +50 -0
  521. package/ui/js/Jump.js +200 -0
  522. package/ui/js/KeyName.js +64 -0
  523. package/ui/js/Keymap.js +401 -0
  524. package/ui/js/Kinds.js +164 -0
  525. package/ui/js/LICENSES/ISC-lucide.txt +43 -0
  526. package/ui/js/LangMarkPaths.js +47 -0
  527. package/ui/js/LangMarks.js +120 -0
  528. package/ui/js/Lists.js +11 -0
  529. package/ui/js/LocalSend.js +39 -0
  530. package/ui/js/LockedMenu.js +63 -0
  531. package/ui/js/MakeDefault.js +186 -0
  532. package/ui/js/MarkBox.js +7 -0
  533. package/ui/js/Markdown.js +119 -0
  534. package/ui/js/MarkdownLists.js +86 -0
  535. package/ui/js/MarkdownMaths.js +58 -0
  536. package/ui/js/MarkdownPictures.js +32 -0
  537. package/ui/js/MarkdownPrepared.js +139 -0
  538. package/ui/js/MarkdownTableFit.js +34 -0
  539. package/ui/js/Marks.js +148 -0
  540. package/ui/js/Marquee.js +96 -0
  541. package/ui/js/Match.js +93 -0
  542. package/ui/js/Material.js +109 -0
  543. package/ui/js/MdBlocks.js +437 -0
  544. package/ui/js/MdBreak.js +71 -0
  545. package/ui/js/MdChunks.js +70 -0
  546. package/ui/js/MdContainer.js +137 -0
  547. package/ui/js/MdDocument.js +337 -0
  548. package/ui/js/MdEmph.js +97 -0
  549. package/ui/js/MdEntity.js +108 -0
  550. package/ui/js/MdEntityTable.js +223 -0
  551. package/ui/js/MdEscape.js +59 -0
  552. package/ui/js/MdFront.js +37 -0
  553. package/ui/js/MdHold.js +32 -0
  554. package/ui/js/MdHtml.js +307 -0
  555. package/ui/js/MdHtmlBlock.js +290 -0
  556. package/ui/js/MdHtmlHeading.js +53 -0
  557. package/ui/js/MdHtmlImage.js +179 -0
  558. package/ui/js/MdInline.js +154 -0
  559. package/ui/js/MdItems.js +212 -0
  560. package/ui/js/MdLeaf.js +309 -0
  561. package/ui/js/MdLink.js +196 -0
  562. package/ui/js/MdMath.js +67 -0
  563. package/ui/js/MdParagraphs.js +138 -0
  564. package/ui/js/MdRefs.js +232 -0
  565. package/ui/js/MdResolve.js +226 -0
  566. package/ui/js/MdRun.js +300 -0
  567. package/ui/js/MdUrl.js +226 -0
  568. package/ui/js/Menu.js +514 -0
  569. package/ui/js/MenuContext.js +85 -0
  570. package/ui/js/MenuFit.js +13 -0
  571. package/ui/js/MenuRefresh.js +74 -0
  572. package/ui/js/MenuWheel.js +35 -0
  573. package/ui/js/Messages.js +186 -0
  574. package/ui/js/Motion.js +16 -0
  575. package/ui/js/Mounts.js +320 -0
  576. package/ui/js/MouseNav.js +13 -0
  577. package/ui/js/Nav.js +329 -0
  578. package/ui/js/NetFs.js +26 -0
  579. package/ui/js/OpenWith.js +83 -0
  580. package/ui/js/Ops.js +585 -0
  581. package/ui/js/Palette.js +33 -0
  582. package/ui/js/PathBar.js +260 -0
  583. package/ui/js/Permissions.js +179 -0
  584. package/ui/js/Phones.js +112 -0
  585. package/ui/js/Picker.js +353 -0
  586. package/ui/js/PlaceMenu.js +96 -0
  587. package/ui/js/Places.js +265 -0
  588. package/ui/js/PreviewAsk.js +21 -0
  589. package/ui/js/PreviewKeys.js +155 -0
  590. package/ui/js/PreviewSettle.js +29 -0
  591. package/ui/js/PreviewSwap.js +101 -0
  592. package/ui/js/PropertyFacts.js +144 -0
  593. package/ui/js/Protocols.js +296 -0
  594. package/ui/js/QuickLookKinds.js +27 -0
  595. package/ui/js/QuickLookRect.js +24 -0
  596. package/ui/js/RailDrop.js +51 -0
  597. package/ui/js/RailKeys.js +87 -0
  598. package/ui/js/RailMenu.js +133 -0
  599. package/ui/js/Recent.js +135 -0
  600. package/ui/js/RecentMode.js +156 -0
  601. package/ui/js/Reload.js +60 -0
  602. package/ui/js/Renderer.js +9 -0
  603. package/ui/js/RunFile.js +143 -0
  604. package/ui/js/Scripts.js +28 -0
  605. package/ui/js/Scroll.js +304 -0
  606. package/ui/js/ScrollOff.js +69 -0
  607. package/ui/js/Search.js +478 -0
  608. package/ui/js/Selection.js +97 -0
  609. package/ui/js/Settings.js +476 -0
  610. package/ui/js/SettingsAbout.js +97 -0
  611. package/ui/js/SettingsShelf.js +52 -0
  612. package/ui/js/SheetKeys.js +42 -0
  613. package/ui/js/SheetQuery.js +281 -0
  614. package/ui/js/ShelfPile.js +27 -0
  615. package/ui/js/SlowClick.js +53 -0
  616. package/ui/js/SlowOp.js +6 -0
  617. package/ui/js/Sort.js +134 -0
  618. package/ui/js/Startup.js +63 -0
  619. package/ui/js/StateWords.js +17 -0
  620. package/ui/js/Status.js +238 -0
  621. package/ui/js/Swap.js +166 -0
  622. package/ui/js/TabMove.js +39 -0
  623. package/ui/js/Tabs.js +751 -0
  624. package/ui/js/Tags.js +134 -0
  625. package/ui/js/Taildrop.js +128 -0
  626. package/ui/js/Tap.js +180 -0
  627. package/ui/js/TextSize.js +107 -0
  628. package/ui/js/Thumbs.js +158 -0
  629. package/ui/js/Transfer.js +172 -0
  630. package/ui/js/Trash.js +84 -0
  631. package/ui/js/TrashDates.js +47 -0
  632. package/ui/js/TrashDrop.js +64 -0
  633. package/ui/js/UiState.js +438 -0
  634. package/ui/js/Unlock.js +152 -0
  635. package/ui/js/Update.js +130 -0
  636. package/ui/js/UserDirs.js +56 -0
  637. package/ui/qmldir +230 -0
@@ -0,0 +1,254 @@
1
+ import QtQuick
2
+
3
+ // One rendered figure: the backend's SVG (src/figure.js) at its aspect ratio within the pane width, or fenced source when rendering fails.
4
+ import "js/FigureDate.js" as FigureDate
5
+
6
+ Item {
7
+ id: root
8
+
9
+ property string kind: "math"
10
+ property string source: ""
11
+ property bool display: true
12
+ property bool inline: false
13
+ // A bare figure asks and settles but draws nothing: its host puts the SVG in its own text.
14
+ property bool bare: false
15
+ property string bgHex: Theme.color.background
16
+ property string fgHex: Theme.color.foreground
17
+ property string accentHex: Theme.color.accent
18
+ property string mutedHex: ""
19
+ property string surfaceHex: ""
20
+ // The failed figure's fence sits on the code surface of the pane that holds it.
21
+ property color fallbackColor: Theme.color.surface
22
+ property string fontFamily: Theme.font.family
23
+ property int bodyPx: Theme.font.body
24
+ // The body font's x-height at bodyPx: a formula draws its ex at this height, so maths and prose letters stand level.
25
+ property real xHeight: regularMetrics.xHeight
26
+ // The request carries the x-height in hundredths of a pixel, so a font that settles late changes the request.
27
+ readonly property int xHeightRounding: 100
28
+
29
+ // A diagram sizes each label from the font's advance of every printable ASCII character, regular and bold; maths sends none.
30
+ readonly property int advanceFirst: 32
31
+ readonly property int advanceLast: 126
32
+ // The request carries the advances in thousandths of an em, so a font that settles late changes the request.
33
+ readonly property int advanceRounding: 1000
34
+ // The advance of each character from the first to the last, read through the metrics' own font so a font change re-runs the table.
35
+ function advanceTable(metrics) {
36
+ var table = [];
37
+ var px = metrics.font.pixelSize;
38
+ for (var code = root.advanceFirst; code <= root.advanceLast; code++)
39
+ table.push(Math.round(metrics.advanceWidth(String.fromCharCode(code)) / px * root.advanceRounding));
40
+ return table;
41
+ }
42
+ readonly property var advances: root.kind !== "mermaid" ? [] : root.advanceTable(regularMetrics)
43
+ readonly property var boldAdvances: root.kind !== "mermaid" ? [] : root.advanceTable(boldMetrics)
44
+ FontMetrics {
45
+ id: regularMetrics
46
+ font.family: root.fontFamily
47
+ font.pixelSize: root.bodyPx
48
+ }
49
+ FontMetrics {
50
+ id: boldMetrics
51
+ font.family: root.fontFamily
52
+ font.pixelSize: root.bodyPx
53
+ font.bold: true
54
+ }
55
+
56
+ readonly property bool failed: root.kind === "math" || root.error !== ""
57
+ readonly property bool ready: root.svg !== ""
58
+ readonly property bool working: root.ticket > 0
59
+ property string svg: ""
60
+ property string error: ""
61
+ property int ticket: 0
62
+ // The Source view sends no figure requests.
63
+ property bool askArmed: true
64
+ // Offscreen delegates retain settled figures and send no requests.
65
+ property bool inView: true
66
+
67
+ // The theme an ask carries, given the label advances its kind sends; the preview's warm query builds the same one, so its cache keys match.
68
+ function themeWith(advances, boldAdvances) {
69
+ return { bg: root.bgHex, fg: root.fgHex, accent: root.accentHex,
70
+ font: root.fontFamily, bodyPx: root.bodyPx,
71
+ exPx: Math.round(root.xHeight * root.xHeightRounding) / root.xHeightRounding,
72
+ advances: advances, boldAdvances: boldAdvances,
73
+ muted: root.mutedHex, surface: root.surfaceHex };
74
+ }
75
+ function hexTheme() {
76
+ return root.themeWith(root.advances, root.boldAdvances);
77
+ }
78
+ // The theme a figure of `kind` is asked under here, whatever this item's own kind.
79
+ function themeOfKind(kind) {
80
+ return kind === "mermaid" ? root.themeWith(root.advanceTable(regularMetrics), root.advanceTable(boldMetrics)) : root.themeWith([], []);
81
+ }
82
+ // Nothing is asked until the figure is created, so its construction-time assignments cost no request.
83
+ property bool created: false
84
+ // The request this figure last sent; an ask for the same state is dropped, so a burst of changes renders once.
85
+ property string lastRequest: ""
86
+ function ask() {
87
+ if (root.kind === "math") return;
88
+ root.askRuns++;
89
+ // Offscreen property changes invalidate the settled figure until it enters the viewport.
90
+ if (root.kind === "math" || !root.askArmed || root.source === "" || !root.inView) {
91
+ root.ticket = 0;
92
+ root.svg = "";
93
+ root.error = "";
94
+ root.lastRequest = "";
95
+ return;
96
+ }
97
+ // A Gantt chart is asked for today, so its key, its stored entry and its drawing name one day.
98
+ var theme = FigureDate.datedTheme(root.kind, root.source, root.hexTheme());
99
+ var request = JSON.stringify([root.kind, root.source, root.display, theme]);
100
+ if (request === root.lastRequest)
101
+ return;
102
+ root.lastRequest = request;
103
+ root.ticket = FigureService.ask(root.kind, root.source, root.display, theme);
104
+ }
105
+ // The wait, in ms, that lets the list lay the delegate out before the one ask reads its place.
106
+ readonly property int askSettleMs: 50
107
+ // The suite counts ask runs and reads the armed deferred ask, so it waits and asserts without timing.
108
+ property int askRuns: 0
109
+ readonly property bool askPending: askTimer.running
110
+ // Every property change lands on the one deferred ask, so the changes of one burst send one request.
111
+ function schedule() {
112
+ if (root.created && !root.takeRemembered())
113
+ askTimer.restart();
114
+ }
115
+
116
+ onKindChanged: root.schedule()
117
+ onSourceChanged: root.schedule()
118
+ onDisplayChanged: root.schedule()
119
+ onBgHexChanged: root.schedule()
120
+ onFgHexChanged: root.schedule()
121
+ onAccentHexChanged: root.schedule()
122
+ onMutedHexChanged: root.schedule()
123
+ onSurfaceHexChanged: root.schedule()
124
+ onFontFamilyChanged: root.schedule()
125
+ onBodyPxChanged: root.schedule()
126
+ onXHeightChanged: root.schedule()
127
+ onAdvancesChanged: root.schedule()
128
+ onBoldAdvancesChanged: root.schedule()
129
+ onAskArmedChanged: root.schedule()
130
+ // Entering the viewport requests an unsettled figure after layout.
131
+ onInViewChanged: if (root.created && root.inView && root.askArmed && root.source !== "" && root.ticket === 0 && root.svg === "" && root.error === "") root.ask()
132
+ // The service's held answer for this exact request, taken on the change itself, so a formula typeset ahead is drawn in the first frame.
133
+ function takeRemembered() {
134
+ if (root.kind === "math" || !root.askArmed || root.source === "" || !root.inView)
135
+ return false;
136
+ var theme = FigureDate.datedTheme(root.kind, root.source, root.hexTheme());
137
+ var hit = FigureService.cached(root.kind, root.source, theme, root.display);
138
+ if (hit === undefined)
139
+ return false;
140
+ // A held answer drops any older request, so nothing in flight lands over it.
141
+ root.ticket = 0;
142
+ askTimer.stop();
143
+ root.lastRequest = JSON.stringify([root.kind, root.source, root.display, theme]);
144
+ root.svg = hit;
145
+ root.error = "";
146
+ return true;
147
+ }
148
+ Component.onCompleted: {
149
+ root.created = true;
150
+ root.schedule();
151
+ }
152
+
153
+ // ListView places the delegate after it completes, so the one ask waits out layout and inView reads the placed position.
154
+ Timer {
155
+ id: askTimer
156
+ interval: root.askSettleMs
157
+ onTriggered: root.ask()
158
+ }
159
+
160
+ Connections {
161
+ target: FigureService
162
+ function onDone(ticket, svg, error) {
163
+ if (ticket !== root.ticket)
164
+ return;
165
+ root.ticket = 0;
166
+ if (svg !== "") {
167
+ root.svg = svg;
168
+ root.error = "";
169
+ } else {
170
+ root.svg = "";
171
+ root.error = error;
172
+ }
173
+ }
174
+ }
175
+
176
+ // Data URLs deliver figures to Qt SVG without filesystem writes.
177
+ readonly property string dataUrl: root.svg === "" ? ""
178
+ : "data:image/svg+xml," + encodeURIComponent(root.svg)
179
+
180
+ Image {
181
+ id: figure
182
+ visible: !root.inline && root.svg !== ""
183
+ anchors.top: parent.top
184
+ anchors.left: root.centred ? undefined : parent.left
185
+ anchors.horizontalCenter: root.centred ? parent.horizontalCenter : undefined
186
+ // A display figure alone decodes here; an inline one draws through inlineFigure below or in its host's own text.
187
+ source: root.inline ? "" : root.dataUrl
188
+ cache: false
189
+ asynchronous: true
190
+ width: root.fitWidth
191
+ height: root.fitHeight
192
+ fillMode: Image.PreserveAspectFit
193
+ }
194
+
195
+ // An inline formula beside text: line height tall, aspect kept.
196
+ Image {
197
+ id: inlineFigure
198
+ visible: root.inline && root.svg !== ""
199
+ anchors.top: parent.top
200
+ source: root.inline && !root.bare ? root.dataUrl : ""
201
+ cache: false
202
+ asynchronous: true
203
+ height: root.bodyPx
204
+ width: root.inlineWidth
205
+ fillMode: Image.PreserveAspectFit
206
+ }
207
+
208
+ // A failed figure draws bounded source on the code surface.
209
+ readonly property int fallbackChars: 2000
210
+ readonly property string fallbackBody: root.source.length > root.fallbackChars
211
+ ? root.source.slice(0, root.fallbackChars) + "… (" + (root.source.length - root.fallbackChars) + " more)"
212
+ : root.source
213
+ // The fence recipe, so fallback text sits where a fenced block does: the host hands down the preview's own fencePadX and fencePadY.
214
+ property int fencePadX: 0
215
+ property int fencePadY: 0
216
+ Rectangle {
217
+ id: fallback
218
+ visible: root.failed
219
+ anchors.top: parent.top
220
+ anchors.left: parent.left
221
+ anchors.right: parent.right
222
+ height: fallbackItem.implicitHeight + 2 * root.fencePadY
223
+ color: root.fallbackColor
224
+ Text {
225
+ id: fallbackItem
226
+ anchors.fill: parent
227
+ anchors.leftMargin: root.fencePadX
228
+ anchors.rightMargin: root.fencePadX
229
+ anchors.topMargin: root.fencePadY
230
+ anchors.bottomMargin: root.fencePadY
231
+ text: root.failed ? root.fallbackBody : ""
232
+ textFormat: Text.PlainText
233
+ wrapMode: Text.Wrap
234
+ color: Theme.color.foreground
235
+ font.family: root.fontFamily
236
+ font.pixelSize: root.bodyPx
237
+ }
238
+ }
239
+
240
+ readonly property bool centred: root.kind === "math" && root.display && !root.inline
241
+ readonly property real naturalWidth: !root.inline && figure.implicitWidth > 0 ? figure.implicitWidth : 0
242
+ readonly property real naturalHeight: !root.inline && figure.implicitHeight > 0 ? figure.implicitHeight : 0
243
+ // Integer geometry keeps the raster 1:1: a fractional item size would resample the whole figure and blend every flat fill.
244
+ readonly property real fitWidth: root.naturalWidth <= 0 ? 0 : Math.round(Math.min(root.naturalWidth, root.width))
245
+ readonly property real fitHeight: root.naturalWidth <= 0 ? 0 : Math.round(root.naturalHeight * (root.fitWidth / root.naturalWidth))
246
+ readonly property real inlineWidth: root.inline && inlineFigure.implicitHeight > 0
247
+ ? Math.round(inlineFigure.implicitWidth * (root.bodyPx / inlineFigure.implicitHeight)) : 0
248
+
249
+ implicitWidth: root.inline ? (root.failed ? fallbackItem.implicitWidth + 2 * root.fencePadX : root.inlineWidth) : root.width
250
+ // A failed inline still draws its fence, so it sizes to the fence rather than the line it never became.
251
+ implicitHeight: root.inline ? (root.failed ? fallback.height : root.bodyPx)
252
+ : root.failed ? fallback.height : root.fitHeight
253
+ height: root.implicitHeight
254
+ }
@@ -0,0 +1,72 @@
1
+ import QtQuick
2
+ import "js/MdHtmlImage.js" as HtmlImage
3
+
4
+ // A row of local images from one HTML block, wrapped at the pane width with each line centred or left, every image keeping its own link.
5
+ Item {
6
+ id: root
7
+
8
+ // Each image as the parser hands it: { url, alt, width and height (optional), link (optional) }.
9
+ property var images: []
10
+ property bool centred: false
11
+ // The space between neighbours on a line and between lines.
12
+ property int gap: 0
13
+ // The pane's scheme gate for a link around an image, as MarkdownText takes one.
14
+ property var linkGate: null
15
+
16
+ // One { x, y } per image and the total height, read from the sizes the images report as they decode.
17
+ readonly property var arrangement: root.arrange(strip.count, root.width)
18
+ height: root.arrangement.height
19
+
20
+ // Sample input: three images 40, 40 and 90 wide on a 100 wide pane with gap 4 make two lines, the first 84 wide and the third alone.
21
+ function arrange(count, limit) {
22
+ var places = []
23
+ var y = 0
24
+ var from = 0
25
+ while (from < count) {
26
+ var to = from
27
+ var used = 0
28
+ var tall = 0
29
+ while (to < count) {
30
+ var pic = strip.itemAt(to)
31
+ var w = pic ? pic.width : 0
32
+ if (to > from && used + root.gap + w > limit)
33
+ break
34
+ used += (to > from ? root.gap : 0) + w
35
+ tall = Math.max(tall, pic ? pic.height : 0)
36
+ to++
37
+ }
38
+ var x = root.centred ? Math.round((limit - used) / 2) : 0
39
+ for (var k = from; k < to; k++) {
40
+ var one = strip.itemAt(k)
41
+ places.push({ x: x, y: y + tall - (one ? one.height : 0) })
42
+ x += (one ? one.width : 0) + root.gap
43
+ }
44
+ y += tall + root.gap
45
+ from = to
46
+ }
47
+ return { places: places, height: Math.max(0, y - root.gap) }
48
+ }
49
+
50
+ Repeater {
51
+ id: strip
52
+ model: root.images.length
53
+ delegate: Image {
54
+ id: pic
55
+ readonly property var spec: root.images[index]
56
+ // The size rule of a lone picture too (HtmlImage.pictureSize): the HTML width and height are honoured, the pane width caps it.
57
+ readonly property var fit: HtmlImage.pictureSize(pic.spec, pic.implicitWidth, pic.implicitHeight, root.width)
58
+ width: pic.fit.w
59
+ height: pic.fit.h
60
+ x: index < root.arrangement.places.length ? root.arrangement.places[index].x : 0
61
+ y: index < root.arrangement.places.length ? root.arrangement.places[index].y : 0
62
+ fillMode: pic.fit.stretch ? Image.Stretch : Image.PreserveAspectFit
63
+ asynchronous: true
64
+ autoTransform: true
65
+ source: pic.spec.url
66
+
67
+ // A badge wrapped in a link opens it through the pane's link gate.
68
+ TapHandler { enabled: pic.spec.link !== undefined; gesturePolicy: TapHandler.ReleaseWithinBounds; onTapped: if (root.linkGate !== null && root.linkGate(pic.spec.link)) Qt.openUrlExternally(pic.spec.link) }
69
+ HoverHandler { enabled: pic.spec.link !== undefined; cursorShape: Qt.PointingHandCursor }
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,81 @@
1
+ import QtQuick
2
+ import "js/MarkdownLists.js" as Lists
3
+
4
+ // One list block drawn with plain Column and Row, keeping QtQuick.Layouts unloaded: each depth's marker column starts at its parent's text column.
5
+ Column {
6
+ id: root
7
+
8
+ // The parsed list: items, and when nested or loose their depths, markers and gaps.
9
+ property var list: ({ items: [] })
10
+ property int bodyPx: Theme.font.body
11
+ // The paragraph gap a loose list puts between its entries.
12
+ property int gap: 0
13
+ property var linkGate: null
14
+ // The preview that sets the sizes of the blocks an item holds, and whether this list is in view for figures.
15
+ property Item preview: null
16
+ property bool inView: true
17
+
18
+ spacing: 0
19
+
20
+ // Each entry's marker column, marker and gap above it; reading the font's size and family re-lays it out when either changes.
21
+ readonly property var cells: {
22
+ listFont.font.pixelSize
23
+ listFont.font.family
24
+ return Lists.layout(root.list, function (text) { return listFont.advanceWidth(text) }, Theme.spacing.gap)
25
+ }
26
+
27
+ FontMetrics {
28
+ id: listFont
29
+ font.family: Theme.font.family
30
+ font.pixelSize: root.bodyPx
31
+ }
32
+
33
+ Repeater {
34
+ model: root.list.items.length
35
+ delegate: Row {
36
+ objectName: "listRow"
37
+ readonly property var cell: root.cells[index]
38
+ x: cell.x
39
+ width: root.width - cell.x
40
+ topPadding: cell.gap ? root.gap : 0
41
+ spacing: Theme.spacing.gap
42
+
43
+ MarkdownText {
44
+ id: marker
45
+ width: cell.w
46
+ bodyPx: root.bodyPx
47
+ text: cell.marker
48
+ // The marker shares the item's line box and first-line leading.
49
+ textFormat: Text.RichText
50
+ height: marker.box
51
+ wrapMode: Text.NoWrap
52
+ // The marker sits on the item's first drawn baseline, 0 for an ungrown line and for a first block with no run text.
53
+ y: itemParts.active ? (itemParts.item !== null && itemParts.item.firstRunText !== null ? itemParts.item.firstRunText.drawnBaseline - marker.drawnBaseline : 0) : itemText.drawnBaseline - marker.drawnBaseline
54
+ }
55
+
56
+ MarkdownText {
57
+ id: itemText
58
+ visible: !itemParts.active
59
+ linkGate: root.linkGate
60
+ width: parent.width - marker.width - parent.spacing
61
+ bodyPx: root.bodyPx
62
+ markdown: root.list.items[index]
63
+ }
64
+
65
+ // An item that holds more than prose draws its blocks in order; they load by file name since MarkdownBlocks draws lists again.
66
+ Loader {
67
+ id: itemParts
68
+ readonly property var parts: root.list.parts !== undefined && root.list.parts[index] ? root.list.parts[index] : []
69
+ active: itemParts.parts.length > 0
70
+ width: parent.width - marker.width - parent.spacing
71
+ source: itemParts.parts.length > 0 ? "MarkdownBlocks.qml" : ""
72
+ onLoaded: {
73
+ // The preview and the view state come first: the blocks build their delegates the moment they arrive.
74
+ itemParts.item.preview = Qt.binding(function () { return root.preview })
75
+ itemParts.item.inView = Qt.binding(function () { return root.inView })
76
+ itemParts.item.blocks = Qt.binding(function () { return itemParts.parts })
77
+ }
78
+ }
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,97 @@
1
+ import QtQuick
2
+ import "js/MarkdownMaths.js" as Maths
3
+
4
+ // A Markdown text whose inline formulas draw in the line: each asks the figure helper once, and its code span stands until the picture lands.
5
+ MarkdownText {
6
+ id: root
7
+
8
+ // The run's HTML text, and the TeX of its inline formulas in the order of the data-math spans inside it.
9
+ property string source: ""
10
+ property var maths: []
11
+ // The theme and gates a figure takes, handed down by the block's host as the display figures get them.
12
+ property bool askArmed: true
13
+ property bool inView: true
14
+ property string bgHex: Theme.color.background
15
+ property string fgHex: Theme.color.foreground
16
+ property string accentHex: Theme.color.accent
17
+ property string mutedHex: ""
18
+ property string surfaceHex: ""
19
+ // The fence pads a failed formula's source takes, the preview's own.
20
+ property int fencePadX: 0
21
+ property int fencePadY: 0
22
+
23
+ // A formula the parser and the text disagree on is left as its code span, and asks for nothing.
24
+ readonly property bool matched: Maths.spans(root.source).length === root.maths.length
25
+ // Each distinct formula asks once, however often the run repeats it.
26
+ readonly property var formulas: {
27
+ var seen = []
28
+ for (var i = 0; root.matched && i < root.maths.length; i++) {
29
+ if (seen.indexOf(root.maths[i]) < 0)
30
+ seen.push(root.maths[i])
31
+ }
32
+ return seen
33
+ }
34
+ // The SVG of each drawn formula by its TeX, "" while it waits or after it failed.
35
+ property var svgs: ({})
36
+ property var settledSources: ({})
37
+ // Formulas still waiting for their answer; the suite reads it to know the run is done.
38
+ readonly property int unsettled: root.formulas.length - Object.keys(root.settledSources).length
39
+
40
+ // Qt centres a middle-aligned picture above the baseline by a font-dependent amount; a hidden tall picture reports it as its baseline.
41
+ readonly property real anchorHeight: calibration.baselineOffset - Maths.CALIBRATION_HEIGHT / 2
42
+ readonly property real tallestPicture: 2 * root.box
43
+
44
+ function landed(tex, svg, settled) {
45
+ var next = Object.assign({}, root.svgs)
46
+ next[tex] = svg
47
+ root.svgs = next
48
+ var done = Object.assign({}, root.settledSources)
49
+ if (settled)
50
+ done[tex] = true
51
+ else
52
+ delete done[tex]
53
+ root.settledSources = done
54
+ }
55
+
56
+ text: root.matched ? root.padSized(Maths.compose(root.source, root.maths.map(function (tex) {
57
+ return Maths.picture(root.svgs[tex] || "", root.anchorHeight, root.tallestPicture)
58
+ }))) : root.padSized(root.source)
59
+
60
+ Text {
61
+ id: calibration
62
+ visible: false
63
+ font: root.font
64
+ textFormat: Text.MarkdownText
65
+ wrapMode: Text.NoWrap
66
+ text: "H <img src=\"" + Maths.CLEAR + "\" width=\"1\" height=\"" + Maths.CALIBRATION_HEIGHT + "\" style=\"vertical-align: middle\" />"
67
+ }
68
+
69
+ Repeater {
70
+ model: root.formulas
71
+ delegate: MarkdownFigure {
72
+ required property string modelData
73
+ visible: false
74
+ kind: "math"
75
+ source: modelData
76
+ display: false
77
+ inline: true
78
+ bare: true
79
+ askArmed: root.askArmed
80
+ inView: root.inView
81
+ bgHex: root.bgHex
82
+ fgHex: root.fgHex
83
+ accentHex: root.accentHex
84
+ mutedHex: root.mutedHex
85
+ surfaceHex: root.surfaceHex
86
+ fencePadX: root.fencePadX
87
+ fencePadY: root.fencePadY
88
+ fontFamily: root.font.family
89
+ bodyPx: root.font.pixelSize
90
+ onSvgChanged: root.landed(modelData, svg, svg !== "" || error !== "")
91
+ onErrorChanged: root.landed(modelData, svg, svg !== "" || error !== "")
92
+ }
93
+ }
94
+
95
+ // Its formulas are padded to sit on the fixed line's baseline, so a picture beside them keeps that line.
96
+ growsForPictures: false
97
+ }
@@ -0,0 +1,83 @@
1
+ import QtQuick
2
+ import "." as Flea
3
+ import "js/Icons.js" as Icons
4
+
5
+ // The Markdown bar and pane load only for a Markdown file.
6
+ Item {
7
+ id: root
8
+
9
+ property bool active: false
10
+ // flea-qml: the row's icon; an emoji one marks the bar instead of the Markdown glyph.
11
+ property string iconName: ""
12
+ property string path: ""
13
+ property int size: 0
14
+ property string view: "rendered"
15
+ property int maxBytes: 1048576
16
+ property bool truncate: false
17
+ property string blockPath: ""
18
+ // The backend that colours Source and the fences, and the wrap Quick Look's w keeps for Source.
19
+ property var backend: null
20
+ property bool wrap: false
21
+
22
+ // The keyboard is on the close mark; Quick Look's key handler owns the walk, as the PDF viewer's controls do.
23
+ property bool closeFocused: false
24
+
25
+ signal closeRequested
26
+
27
+ readonly property var viewport: doc.shownView === "source" ? doc.sourceItem : doc.viewport
28
+ readonly property var bodyItem: doc.bodyItem
29
+ readonly property var tableWheel: doc.tableWheel
30
+ function tableScroller() { return doc.tableScroller() }
31
+ readonly property real scrollY: doc.scrollY
32
+ function endGap() { return doc.endGap() }
33
+ function closeState() { return bar.closeState() }
34
+ readonly property string rawText: doc.rawText
35
+ readonly property string status: doc.status
36
+ readonly property string lineLabel: doc.lineLabel
37
+ // The view the body draws, which Quick Look's IPC reads rather than the property that asks for it.
38
+ readonly property string shownView: doc.shownView
39
+ // Quick Look's seam reads figures through this pane, so it forwards the document's blocks.
40
+ readonly property var blockList: doc.blockList
41
+ function figureInfo(i) { return doc.figureInfo(i) }
42
+ function blockItem(i) { return doc.blockItem(i) }
43
+ readonly property bool contentReady: doc.contentReady
44
+ readonly property bool firstScreen: doc.firstScreen
45
+
46
+ // The render suite reads the bar's order off these rects; the pane adds what only it knows.
47
+ function barGeometry() {
48
+ var g = bar.geometry()
49
+ g.ready = root.contentReady
50
+ return g
51
+ }
52
+
53
+ Flea.QuickLookBar {
54
+ id: bar
55
+ anchors.top: parent.top
56
+ anchors.left: parent.left
57
+ anchors.right: parent.right
58
+ markName: Icons.isEmoji(root.iconName) ? root.iconName : "markdown"
59
+ name: root.path.substring(root.path.lastIndexOf("/") + 1)
60
+ countLabel: root.contentReady ? root.lineLabel : ""
61
+ closeFocused: root.closeFocused
62
+ onCloseRequested: root.closeRequested()
63
+ }
64
+
65
+ Flea.PreviewMarkdown {
66
+ id: doc
67
+ anchors.fill: parent
68
+ anchors.topMargin: bar.height
69
+ active: root.active
70
+ view: root.view
71
+ path: root.path
72
+ size: root.size
73
+ maxBytes: root.maxBytes
74
+ truncate: root.truncate
75
+ blockPath: root.blockPath
76
+ backend: root.backend
77
+ slot: "look"
78
+ wrap: root.wrap
79
+ shareParse: true
80
+ // The page is the chrome surface, so code sits on the window colour (md_rendered code_bg).
81
+ codeSurface: Theme.color.background
82
+ }
83
+ }
@@ -0,0 +1,41 @@
1
+ // Bound: the hidden images read this helper's root to note their sizes, and only its own Repeater builds them.
2
+ pragma ComponentBehavior: Bound
3
+ import QtQuick
4
+ import "js/MarkdownPictures.js" as Pictures
5
+
6
+ // The pictures one Markdown text holds: their natural sizes from hidden images, and the text with the wide ones scaled to its width; ui/MarkdownText.qml builds it for a text with a picture only.
7
+ Item {
8
+ id: root
9
+
10
+ required property MarkdownText host
11
+
12
+ readonly property var urls: Pictures.urls(root.host.markdown)
13
+ // Each decoded picture's natural size by address, kept after the hidden Image releases its own copy.
14
+ property var known: ({})
15
+ // One address is noted once; replacing the map notifies fitted below, which a mutated key never does.
16
+ function noteSize(url, w, h) {
17
+ if (root.known[url] !== undefined)
18
+ return
19
+ var next = {}
20
+ for (var key in root.known)
21
+ next[key] = root.known[key]
22
+ next[url] = { w: w, h: h }
23
+ root.known = next
24
+ }
25
+ readonly property var fitted: Pictures.fit(root.host.markdown, root.known, Math.floor(root.host.width - root.host.leftPadding - root.host.rightPadding))
26
+ // The text to draw, and the tallest picture in it as it draws, 0 until one is decoded.
27
+ readonly property string shown: root.fitted.text
28
+ readonly property real tallest: root.fitted.tallest
29
+
30
+ Repeater {
31
+ model: root.urls
32
+ delegate: Image {
33
+ required property string modelData
34
+ visible: false
35
+ asynchronous: true
36
+ // An address loads only until its size is known, so no decoded copy outlives the note.
37
+ source: root.known[modelData] === undefined ? modelData : ""
38
+ onStatusChanged: if (status === Image.Ready && implicitWidth > 0) root.noteSize(modelData, implicitWidth, implicitHeight)
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,52 @@
1
+ import QtQuick
2
+
3
+ // One quote block: a 2 px bar per level, each a bar-plus-gap step right of its parent's, then the text or the blocks the quote holds.
4
+ Row {
5
+ id: root
6
+
7
+ property int levels: 1
8
+ property string text: ""
9
+ // The quote's blocks when it holds more than prose, drawn in order in place of the text; the preview sets their sizes.
10
+ property var parts: []
11
+ property Item preview: null
12
+ property bool inView: true
13
+ property int bodyPx: Theme.font.body
14
+ property var linkGate: null
15
+ readonly property int barWidth: 2
16
+ // The width the text or the blocks take beside the bars.
17
+ readonly property real contentWidth: root.width - root.levels * (root.barWidth + root.spacing)
18
+
19
+ spacing: Theme.spacing.gap
20
+
21
+ Repeater {
22
+ model: root.levels
23
+ delegate: Rectangle {
24
+ width: root.barWidth
25
+ height: root.parts.length > 0 ? held.height : quoteText.implicitHeight
26
+ color: Theme.color.mutedFrame
27
+ }
28
+ }
29
+
30
+ MarkdownText {
31
+ id: quoteText
32
+ visible: root.parts.length === 0
33
+ linkGate: root.linkGate
34
+ width: root.contentWidth
35
+ bodyPx: root.bodyPx
36
+ markdown: root.text
37
+ }
38
+
39
+ // The blocks load by file name: MarkdownBlocks draws quotes and lists again, and a type reference would close the cycle.
40
+ Loader {
41
+ id: held
42
+ active: root.parts.length > 0
43
+ width: root.contentWidth
44
+ source: root.parts.length > 0 ? "MarkdownBlocks.qml" : ""
45
+ onLoaded: {
46
+ // The preview and the view state come first: the blocks build their delegates the moment they arrive.
47
+ held.item.preview = Qt.binding(function () { return root.preview })
48
+ held.item.inView = Qt.binding(function () { return root.inView })
49
+ held.item.blocks = Qt.binding(function () { return root.parts })
50
+ }
51
+ }
52
+ }