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.
- package/LICENSE +22 -0
- package/README.md +511 -2
- package/THIRD-PARTY-NOTICES.md +29 -0
- package/demos/App.java +5 -0
- package/demos/Dockerfile +4 -0
- package/demos/Main.kt +3 -0
- package/demos/Program.cs +1 -0
- package/demos/README.md +12 -0
- package/demos/app.dart +3 -0
- package/demos/app.deb +0 -0
- package/demos/app.js +1 -0
- package/demos/backup.tar +0 -0
- package/demos/budget.xlsx +0 -0
- package/demos/build.sh +2 -0
- package/demos/bundle.zip +0 -0
- package/demos/clip.mp4 +0 -0
- package/demos/data.sqlite +0 -0
- package/demos/disk.iso +0 -0
- package/demos/engine.cpp +5 -0
- package/demos/firmware.bin +0 -0
- package/demos/flake.nix +4 -0
- package/demos/folder/inside.txt +1 -0
- package/demos/font.ttf +0 -0
- package/demos/index.html +5 -0
- package/demos/index.php +2 -0
- package/demos/init.lua +1 -0
- package/demos/letter.docx +0 -0
- package/demos/lib.rs +3 -0
- package/demos/main.c +6 -0
- package/demos/main.h +3 -0
- package/demos/math-and-diagrams.md +200 -0
- package/demos/notes.tar.gz +0 -0
- package/demos/notes.txt +3 -0
- package/demos/photo.png +0 -0
- package/demos/program +2 -0
- package/demos/report.pdf +32 -0
- package/demos/script.py +1 -0
- package/demos/server.go +7 -0
- package/demos/settings.json +4 -0
- package/demos/slides.pptx +0 -0
- package/demos/song.mp3 +0 -0
- package/demos/style.css +4 -0
- package/demos/tool.rb +1 -0
- package/demos/types.ts +2 -0
- package/docs/pele.md +23 -0
- package/docs/protocol.md +3420 -0
- package/docs/temml.md +63 -0
- package/index.js +107 -0
- package/package.json +34 -4
- package/src/archive.js +407 -0
- package/src/archiveops.js +728 -0
- package/src/backend.js +369 -0
- package/src/bulkrename.js +95 -0
- package/src/clip-host.js +76 -0
- package/src/clip.js +462 -0
- package/src/code.js +168 -0
- package/src/compare.js +74 -0
- package/src/create.js +128 -0
- package/src/dirsize.js +147 -0
- package/src/figure-svg.js +530 -0
- package/src/figure-thread.js +23 -0
- package/src/figure.js +132 -0
- package/src/find.js +55 -0
- package/src/flea.js +39 -0
- package/src/fsinfo.js +39 -0
- package/src/highlight.js +141 -0
- package/src/html.js +52 -0
- package/src/kinds.js +89 -0
- package/src/listing.js +130 -0
- package/src/markdown-html.js +317 -0
- package/src/mathml.js +186 -0
- package/src/menu.js +180 -0
- package/src/meta.js +135 -0
- package/src/office.js +810 -0
- package/src/order.js +100 -0
- package/src/peek.js +49 -0
- package/src/pele-wrapper.js +695 -0
- package/src/permissions.js +180 -0
- package/src/places.js +313 -0
- package/src/preview-language.js +10 -0
- package/src/terminal-server.js +95 -0
- package/src/terminal-shell.js +26 -0
- package/src/transfer.js +669 -0
- package/src/trash-record.js +41 -0
- package/src/trash.js +210 -0
- package/src/trashbrowse.js +327 -0
- package/src/uistate.js +393 -0
- package/src/uistore.js +168 -0
- package/src/vendor/LICENSES/Apache-2.0.txt +202 -0
- package/src/vendor/LICENSES/MIT-katex-2015.txt +27 -0
- package/src/vendor/LICENSES/MIT-katex.txt +21 -0
- package/src/vendor/LICENSES/MIT-mermaid.txt +21 -0
- package/src/vendor/LICENSES/MIT-pele.txt +40 -0
- package/src/vendor/LICENSES/MIT-perseus.txt +18 -0
- package/src/vendor/LICENSES/MIT-temml.txt +21 -0
- package/src/vendor/pele.js +145 -0
- package/src/vendor/temml.mjs +14708 -0
- package/src/watch.js +98 -0
- package/src/wayland/client.js +109 -0
- package/src/wayland/protocol.js +55 -0
- package/src/wayland/protocols/ext-data-control-v1.xml +276 -0
- package/src/wayland/protocols/wayland.xml +3248 -0
- package/src/wayland/protocols/wlr-data-control-unstable-v1.xml +278 -0
- package/src/wayland/resource-io.js +6 -0
- package/src/wayland/socket-discovery.js +26 -0
- package/src/wayland/transport-posix.js +120 -0
- package/src/wayland/transport-win32.js +11 -0
- package/src/wayland/transport.js +3 -0
- package/src/wayland/win32-resources.js +80 -0
- package/src/wayland/win32-wire.js +62 -0
- package/test/archive.test.js +80 -0
- package/test/bench-markdown-scroll.mjs +190 -0
- package/test/clip-host.test.js +113 -0
- package/test/code-preview.test.js +35 -0
- package/test/compare-ui-paths.test.js +24 -0
- package/test/compare.test.js +54 -0
- package/test/delete-trash.test.js +67 -0
- package/test/dirsize.test.js +138 -0
- package/test/file-ops.test.js +307 -0
- package/test/file-url.test.js +24 -0
- package/test/find-contents.test.js +161 -0
- package/test/find-input.test.js +66 -0
- package/test/fixtures/pele-parity.json +1006 -0
- package/test/highlight-launcher.test.js +35 -0
- package/test/html-preview.test.js +22 -0
- package/test/input.test.js +15 -0
- package/test/keymap.test.js +26 -0
- package/test/language-icons.test.js +36 -0
- package/test/launcher.test.js +51 -0
- package/test/manual-archive-here-ui.mjs +47 -0
- package/test/manual-code-scroll.mjs +28 -0
- package/test/manual-column-scroll.mjs +24 -0
- package/test/manual-compare-ui.mjs +20 -0
- package/test/manual-find-status.mjs +37 -0
- package/test/manual-folder-focus.mjs +63 -0
- package/test/manual-html-security.mjs +23 -0
- package/test/manual-html-ui.mjs +30 -0
- package/test/manual-syntax-preview.mjs +26 -0
- package/test/manual-terminal-lifecycle.mjs +42 -0
- package/test/manual-terminal-navigation.mjs +48 -0
- package/test/manual-terminal-ui.mjs +47 -0
- package/test/manual-trash-ui.mjs +86 -0
- package/test/markdown-diagrams.test.js +93 -0
- package/test/markdown-html.test.js +105 -0
- package/test/mathml.test.js +92 -0
- package/test/menu-transfer.test.js +57 -0
- package/test/office-preview.test.js +154 -0
- package/test/pele-parity.test.js +28 -0
- package/test/places.test.js +134 -0
- package/test/preview-keys.test.js +60 -0
- package/test/preview-language.test.js +22 -0
- package/test/status-filename.test.js +20 -0
- package/test/transfer-replace-merge.test.js +187 -0
- package/test/trash-address.test.js +23 -0
- package/test/trash-view.test.js +37 -0
- package/test/trashbrowse.test.js +135 -0
- package/ui/AboutFacts.qml +78 -0
- package/ui/ArchiveCards.qml +95 -0
- package/ui/ArchiveCompressDialog.qml +378 -0
- package/ui/ArchiveHereConfirm.qml +127 -0
- package/ui/ArchivePasswordDialog.qml +257 -0
- package/ui/Backend.qml +775 -0
- package/ui/BulkOldNames.qml +47 -0
- package/ui/BulkRenameDialog.qml +380 -0
- package/ui/CardFrame.qml +67 -0
- package/ui/CardScroll.qml +79 -0
- package/ui/CheckBox.qml +73 -0
- package/ui/ChromeBar.qml +360 -0
- package/ui/ChromeButton.qml +131 -0
- package/ui/ChromeModes.qml +43 -0
- package/ui/CodeLines.qml +256 -0
- package/ui/CodeRefusal.qml +52 -0
- package/ui/CollideConfirm.qml +147 -0
- package/ui/CollideHost.qml +167 -0
- package/ui/ColumnPane.qml +525 -0
- package/ui/ColumnRow.qml +380 -0
- package/ui/ColumnsArea.qml +594 -0
- package/ui/ColumnsLanding.qml +147 -0
- package/ui/CompareView.qml +321 -0
- package/ui/ContextMenu.qml +743 -0
- package/ui/ConvertDialog.qml +456 -0
- package/ui/CountedWorker.qml +7 -0
- package/ui/Crumb.qml +64 -0
- package/ui/CrumbDrop.qml +25 -0
- package/ui/CsvTable.qml +394 -0
- package/ui/CursorMark.qml +41 -0
- package/ui/DefaultClaim.qml +130 -0
- package/ui/DeviceLock.qml +47 -0
- package/ui/DeviceMounts.qml +540 -0
- package/ui/DialogButton.qml +150 -0
- package/ui/DialogField.qml +147 -0
- package/ui/DialogHeader.qml +31 -0
- package/ui/DialogScrim.qml +20 -0
- package/ui/DialogTitle.qml +37 -0
- package/ui/Divider.qml +9 -0
- package/ui/DropInto.qml +126 -0
- package/ui/DropTarget.qml +35 -0
- package/ui/DropboxMark.qml +60 -0
- package/ui/EmptyState.qml +150 -0
- package/ui/EscapeHint.qml +11 -0
- package/ui/FactsTable.qml +54 -0
- package/ui/FastScrollHandler.qml +476 -0
- package/ui/FatNamesConfirm.qml +157 -0
- package/ui/Favourites.qml +143 -0
- package/ui/FigureService.qml +120 -0
- package/ui/FileDrag.qml +267 -0
- package/ui/FilterStrip.qml +133 -0
- package/ui/FitMetrics.qml +22 -0
- package/ui/FlashDriveRows.qml +137 -0
- package/ui/FlashHost.qml +72 -0
- package/ui/FlashImageRow.qml +104 -0
- package/ui/FlashRunner.qml +119 -0
- package/ui/FlashStepRow.qml +172 -0
- package/ui/FlashStrip.qml +38 -0
- package/ui/FlashView.qml +397 -0
- package/ui/FleaMark.qml +88 -0
- package/ui/FlyoutFade.qml +23 -0
- package/ui/FontPane.qml +170 -0
- package/ui/Glass.qml +114 -0
- package/ui/GlassTagger.qml +59 -0
- package/ui/Glyph.qml +64 -0
- package/ui/GlyphSolid.qml +22 -0
- package/ui/GridArea.qml +664 -0
- package/ui/GridTile.qml +325 -0
- package/ui/GvfsBridge.qml +164 -0
- package/ui/Header.qml +433 -0
- package/ui/HoverTimers.qml +39 -0
- package/ui/HtmlClip.qml +30 -0
- package/ui/HtmlPane.qml +63 -0
- package/ui/HyprlandMark.qml +45 -0
- package/ui/Ipc.qml +1005 -0
- package/ui/IpcControls.qml +7 -0
- package/ui/IpcMenuState.qml +48 -0
- package/ui/IpcPreviewState.qml +185 -0
- package/ui/JumpPath.qml +51 -0
- package/ui/KeymapSheet.qml +561 -0
- package/ui/KeymapSheetResult.qml +89 -0
- package/ui/KindStack.qml +40 -0
- package/ui/LangMark.qml +51 -0
- package/ui/LangMarkLoader.qml +26 -0
- package/ui/List.qml +480 -0
- package/ui/LoadingState.qml +54 -0
- package/ui/LocalSend.qml +56 -0
- package/ui/LocalSendMark.qml +73 -0
- package/ui/MarkdownBlockView.qml +311 -0
- package/ui/MarkdownBlocks.qml +35 -0
- package/ui/MarkdownFigure.qml +254 -0
- package/ui/MarkdownImages.qml +72 -0
- package/ui/MarkdownList.qml +81 -0
- package/ui/MarkdownMathsText.qml +97 -0
- package/ui/MarkdownPane.qml +83 -0
- package/ui/MarkdownPictures.qml +41 -0
- package/ui/MarkdownQuote.qml +52 -0
- package/ui/MarkdownRemote.qml +82 -0
- package/ui/MarkdownSource.qml +155 -0
- package/ui/MarkdownTable.qml +222 -0
- package/ui/MarkdownTableScroll.qml +64 -0
- package/ui/MarkdownTableWheel.qml +126 -0
- package/ui/MarkdownText.qml +87 -0
- package/ui/MarkdownWorker.js +132 -0
- package/ui/MatchText.qml +99 -0
- package/ui/MediaSession.qml +38 -0
- package/ui/MediaSound.qml +26 -0
- package/ui/MediaStrip.qml +191 -0
- package/ui/MediaTrack.qml +36 -0
- package/ui/MediaVolume.qml +54 -0
- package/ui/MenuActionDialog.qml +396 -0
- package/ui/MenuEdgeFade.qml +24 -0
- package/ui/MenuHost.qml +227 -0
- package/ui/MenuRow.qml +351 -0
- package/ui/MountListing.qml +100 -0
- package/ui/NetworkDialog.qml +435 -0
- package/ui/NetworkForm.qml +426 -0
- package/ui/NetworkMounts.qml +913 -0
- package/ui/NetworkPlaces.qml +127 -0
- package/ui/OpenWithDialog.qml +613 -0
- package/ui/Opener.qml +95 -0
- package/ui/Pane.qml +1320 -0
- package/ui/PaneMenuActions.qml +527 -0
- package/ui/PanePath.qml +90 -0
- package/ui/PaneRail.qml +268 -0
- package/ui/PaneStates.qml +88 -0
- package/ui/PaneSwap.qml +339 -0
- package/ui/PaneWire.qml +601 -0
- package/ui/ParkedWait.qml +9 -0
- package/ui/PathEntry.qml +186 -0
- package/ui/PathJump.qml +400 -0
- package/ui/PdfViewer.qml +297 -0
- package/ui/PermissionsDialog.qml +658 -0
- package/ui/PermissionsHeadings.qml +31 -0
- package/ui/PhoneMounts.qml +67 -0
- package/ui/PickerAnswers.qml +75 -0
- package/ui/PickerBox.qml +26 -0
- package/ui/PickerChrome.qml +295 -0
- package/ui/PickerFilter.qml +97 -0
- package/ui/PickerGrid.qml +308 -0
- package/ui/PickerHeader.qml +28 -0
- package/ui/PickerLifecycle.qml +27 -0
- package/ui/PickerList.qml +218 -0
- package/ui/PickerListing.qml +149 -0
- package/ui/PickerPathBar.qml +127 -0
- package/ui/PickerPlaces.qml +189 -0
- package/ui/PickerRecent.qml +92 -0
- package/ui/PickerSave.qml +101 -0
- package/ui/PickerSelection.qml +155 -0
- package/ui/PickerWindow.qml +846 -0
- package/ui/PowerSectorsReader.qml +10 -0
- package/ui/PrebuildDriver.qml +146 -0
- package/ui/Preview.qml +1005 -0
- package/ui/PreviewAnimation.qml +24 -0
- package/ui/PreviewArchive.qml +91 -0
- package/ui/PreviewColumn.qml +553 -0
- package/ui/PreviewEdge.qml +63 -0
- package/ui/PreviewFacts.qml +30 -0
- package/ui/PreviewFactsLine.qml +34 -0
- package/ui/PreviewHtml.qml +233 -0
- package/ui/PreviewImage.qml +253 -0
- package/ui/PreviewImagePan.qml +13 -0
- package/ui/PreviewImageSharp.qml +32 -0
- package/ui/PreviewLines.qml +106 -0
- package/ui/PreviewMarkdown.qml +706 -0
- package/ui/PreviewMedia.qml +250 -0
- package/ui/PreviewPdf.qml +482 -0
- package/ui/PreviewScroll.qml +201 -0
- package/ui/PreviewSwap.qml +335 -0
- package/ui/PreviewText.qml +149 -0
- package/ui/ProtocolChip.qml +18 -0
- package/ui/QuickLookArchive.qml +41 -0
- package/ui/QuickLookBar.qml +103 -0
- package/ui/QuickLookPrepare.qml +355 -0
- package/ui/QuickLookSwap.qml +10 -0
- package/ui/QuickLookWarm.qml +65 -0
- package/ui/RailDrop.qml +155 -0
- package/ui/RailHeading.qml +19 -0
- package/ui/RailPlaces.qml +38 -0
- package/ui/RailTrashRow.qml +67 -0
- package/ui/RenameField.qml +353 -0
- package/ui/RendererRetry.qml +11 -0
- package/ui/ResizeHandle.qml +52 -0
- package/ui/Reveal.qml +54 -0
- package/ui/Row.qml +476 -0
- package/ui/RowDrag.qml +213 -0
- package/ui/RowDropTarget.qml +27 -0
- package/ui/RunCard.qml +286 -0
- package/ui/Scripts.qml +65 -0
- package/ui/SearchStrip.qml +232 -0
- package/ui/SelectionBand.qml +140 -0
- package/ui/SelectionPreview.qml +370 -0
- package/ui/SettingsFavourite.qml +122 -0
- package/ui/SettingsGroup.qml +96 -0
- package/ui/SettingsHint.qml +12 -0
- package/ui/SettingsMetrics.qml +29 -0
- package/ui/SettingsPane.qml +178 -0
- package/ui/SettingsPanel.qml +547 -0
- package/ui/SettingsRail.qml +128 -0
- package/ui/SettingsRow.qml +409 -0
- package/ui/SettingsRuler.qml +85 -0
- package/ui/SettingsSegment.qml +85 -0
- package/ui/ShareBrowser.qml +113 -0
- package/ui/ShareLink.qml +67 -0
- package/ui/ShelfPins.qml +101 -0
- package/ui/Sidebar.qml +728 -0
- package/ui/SidebarRow.qml +358 -0
- package/ui/Spinner.qml +60 -0
- package/ui/StableModel.qml +89 -0
- package/ui/StateMessage.qml +84 -0
- package/ui/StatusBar.qml +512 -0
- package/ui/StatusFileName.qml +27 -0
- package/ui/TabBar.qml +673 -0
- package/ui/TabDragGeometry.qml +60 -0
- package/ui/TagMenuMark.qml +52 -0
- package/ui/TagRailSection.qml +53 -0
- package/ui/TagSlot.qml +40 -0
- package/ui/TagState.qml +150 -0
- package/ui/TagSwatch.qml +28 -0
- package/ui/Taildrop.qml +86 -0
- package/ui/TailscaleMark.qml +50 -0
- package/ui/TerminalService.qml +69 -0
- package/ui/TerminalTab.qml +48 -0
- package/ui/TerminalTabs.qml +27 -0
- package/ui/Theme.qml +460 -0
- package/ui/ThemeColors.qml +43 -0
- package/ui/TransferCard.qml +239 -0
- package/ui/TrashConfirm.qml +129 -0
- package/ui/TrashDropHandler.qml +11 -0
- package/ui/TrashHost.qml +202 -0
- package/ui/TrashMonitor.qml +30 -0
- package/ui/TrashToolbar.qml +19 -0
- package/ui/TrashView.qml +492 -0
- package/ui/UnlockDialog.qml +450 -0
- package/ui/UnlockHost.qml +206 -0
- package/ui/UpdateCheck.qml +97 -0
- package/ui/UserDirs.qml +25 -0
- package/ui/ViewState.qml +565 -0
- package/ui/ViewportScrollBar.qml +195 -0
- package/ui/ViewportScrollBars.qml +25 -0
- package/ui/WebPreview.qml +33 -0
- package/ui/WebPreviewView.qml +26 -0
- package/ui/WindowBody.qml +829 -0
- package/ui/WindowDrag.qml +35 -0
- package/ui/boot/Commons/AudioNodes.qml +50 -0
- package/ui/boot/Commons/AudioNodesModel.js +96 -0
- package/ui/boot/Commons/Border.qml +243 -0
- package/ui/boot/Commons/BorderGeometry.js +373 -0
- package/ui/boot/Commons/Color.qml +258 -0
- package/ui/boot/Commons/I18n.qml +118 -0
- package/ui/boot/Commons/InputDevices.qml +112 -0
- package/ui/boot/Commons/InputMethodState.qml +38 -0
- package/ui/boot/Commons/IpcRegistry.qml +77 -0
- package/ui/boot/Commons/Numbers.js +19 -0
- package/ui/boot/Commons/Plural.js +91 -0
- package/ui/boot/Commons/ShellIpc.qml +12 -0
- package/ui/boot/Commons/Style.qml +561 -0
- package/ui/boot/Commons/Translations.qml +100 -0
- package/ui/boot/Commons/UntypedInput.qml +152 -0
- package/ui/boot/Commons/Util.qml +188 -0
- package/ui/boot/Commons/qmldir +13 -0
- package/ui/boot/LICENSE-omarchy +20 -0
- package/ui/boot/Ui/BackgroundMedia.qml +49 -0
- package/ui/boot/Ui/BarIconButton.qml +106 -0
- package/ui/boot/Ui/BarIconContent.qml +38 -0
- package/ui/boot/Ui/BarIndicator.qml +53 -0
- package/ui/boot/Ui/BarWidget.qml +50 -0
- package/ui/boot/Ui/BorderOverlay.qml +54 -0
- package/ui/boot/Ui/BorderSurface.qml +40 -0
- package/ui/boot/Ui/Button.qml +224 -0
- package/ui/boot/Ui/ButtonGroup.qml +131 -0
- package/ui/boot/Ui/ConfirmDialog.qml +134 -0
- package/ui/boot/Ui/CursorSurface.qml +42 -0
- package/ui/boot/Ui/Dropdown.qml +245 -0
- package/ui/boot/Ui/FilterInput.qml +26 -0
- package/ui/boot/Ui/IconContentBounds.qml +141 -0
- package/ui/boot/Ui/KeyboardPanel.qml +453 -0
- package/ui/boot/Ui/MultiSelect.qml +624 -0
- package/ui/boot/Ui/NumberField.qml +86 -0
- package/ui/boot/Ui/OpticalGlyph.qml +68 -0
- package/ui/boot/Ui/OverlayWindow.qml +102 -0
- package/ui/boot/Ui/Panel.qml +60 -0
- package/ui/boot/Ui/PanelActionButton.qml +105 -0
- package/ui/boot/Ui/PanelController.qml +16 -0
- package/ui/boot/Ui/PanelHero.qml +112 -0
- package/ui/boot/Ui/PanelKeyCatcher.qml +100 -0
- package/ui/boot/Ui/PanelSectionHeader.qml +31 -0
- package/ui/boot/Ui/PanelSeparator.qml +19 -0
- package/ui/boot/Ui/PanelSlider.qml +156 -0
- package/ui/boot/Ui/PanelToolTip.qml +50 -0
- package/ui/boot/Ui/PluginBarApi.qml +89 -0
- package/ui/boot/Ui/PointerMoveGate.qml +54 -0
- package/ui/boot/Ui/PopupCard.qml +181 -0
- package/ui/boot/Ui/ScreenMoveRemap.qml +43 -0
- package/ui/boot/Ui/SearchableDropdown.qml +354 -0
- package/ui/boot/Ui/SizedImage.qml +125 -0
- package/ui/boot/Ui/SpeedTestOverlay.qml +412 -0
- package/ui/boot/Ui/TextField.qml +58 -0
- package/ui/boot/Ui/Toggle.qml +118 -0
- package/ui/boot/Ui/ToggleSwitch.qml +115 -0
- package/ui/boot/Ui/WidgetButton.qml +172 -0
- package/ui/boot/Ui/qmldir +41 -0
- package/ui/boot/fleatab.qml +50 -0
- package/ui/boot/picker.qml +39 -0
- package/ui/boot/shell.qml +131 -0
- package/ui/boot/tabtearoff.qml +51 -0
- package/ui/js/Anchor.js +379 -0
- package/ui/js/AnchorHold.js +162 -0
- package/ui/js/Archive.js +157 -0
- package/ui/js/ArchiveCard.js +44 -0
- package/ui/js/ArchiveOps.js +44 -0
- package/ui/js/BackReturn.js +118 -0
- package/ui/js/BulkRename.js +100 -0
- package/ui/js/Buttons.js +54 -0
- package/ui/js/ChromeKeys.js +116 -0
- package/ui/js/ClipMarks.js +73 -0
- package/ui/js/ClipSelection.js +67 -0
- package/ui/js/Clipboard.js +179 -0
- package/ui/js/Cloud.js +97 -0
- package/ui/js/CodeRuns.js +72 -0
- package/ui/js/Collide.js +212 -0
- package/ui/js/ColumnFit.js +28 -0
- package/ui/js/ColumnMenu.js +111 -0
- package/ui/js/Columns.js +298 -0
- package/ui/js/ColumnsCarry.js +103 -0
- package/ui/js/Compare.js +74 -0
- package/ui/js/Contrast.js +157 -0
- package/ui/js/ControlReader.js +42 -0
- package/ui/js/Convert.js +52 -0
- package/ui/js/CopyAs.js +52 -0
- package/ui/js/Crumbs.js +178 -0
- package/ui/js/Csv.js +231 -0
- package/ui/js/Density.js +44 -0
- package/ui/js/Devices.js +440 -0
- package/ui/js/DirSizes.js +180 -0
- package/ui/js/Drag.js +360 -0
- package/ui/js/DragOut.js +166 -0
- package/ui/js/DropDev.js +52 -0
- package/ui/js/Dropbox.js +41 -0
- package/ui/js/Eject.js +217 -0
- package/ui/js/Errors.js +188 -0
- package/ui/js/ExtThumbs.js +115 -0
- package/ui/js/Facts.js +402 -0
- package/ui/js/FigureDate.js +14 -0
- package/ui/js/Filter.js +285 -0
- package/ui/js/Find.js +46 -0
- package/ui/js/Flash.js +184 -0
- package/ui/js/FlashCard.js +79 -0
- package/ui/js/FlashEndings.js +125 -0
- package/ui/js/FlashPane.js +116 -0
- package/ui/js/FleaBin.js +12 -0
- package/ui/js/Focus.js +504 -0
- package/ui/js/FolderSorts.js +108 -0
- package/ui/js/FolderViews.js +44 -0
- package/ui/js/Format.js +314 -0
- package/ui/js/Fuzzy.js +141 -0
- package/ui/js/GlassTag.js +72 -0
- package/ui/js/Grid.js +33 -0
- package/ui/js/GridGeometry.js +90 -0
- package/ui/js/GridNames.js +153 -0
- package/ui/js/GvfsBridge.js +200 -0
- package/ui/js/HostClipboard.js +29 -0
- package/ui/js/Icons.js +218 -0
- package/ui/js/Input.js +50 -0
- package/ui/js/Jump.js +200 -0
- package/ui/js/KeyName.js +64 -0
- package/ui/js/Keymap.js +401 -0
- package/ui/js/Kinds.js +164 -0
- package/ui/js/LICENSES/ISC-lucide.txt +43 -0
- package/ui/js/LangMarkPaths.js +47 -0
- package/ui/js/LangMarks.js +120 -0
- package/ui/js/Lists.js +11 -0
- package/ui/js/LocalSend.js +39 -0
- package/ui/js/LockedMenu.js +63 -0
- package/ui/js/MakeDefault.js +186 -0
- package/ui/js/MarkBox.js +7 -0
- package/ui/js/Markdown.js +119 -0
- package/ui/js/MarkdownLists.js +86 -0
- package/ui/js/MarkdownMaths.js +58 -0
- package/ui/js/MarkdownPictures.js +32 -0
- package/ui/js/MarkdownPrepared.js +139 -0
- package/ui/js/MarkdownTableFit.js +34 -0
- package/ui/js/Marks.js +148 -0
- package/ui/js/Marquee.js +96 -0
- package/ui/js/Match.js +93 -0
- package/ui/js/Material.js +109 -0
- package/ui/js/MdBlocks.js +437 -0
- package/ui/js/MdBreak.js +71 -0
- package/ui/js/MdChunks.js +70 -0
- package/ui/js/MdContainer.js +137 -0
- package/ui/js/MdDocument.js +337 -0
- package/ui/js/MdEmph.js +97 -0
- package/ui/js/MdEntity.js +108 -0
- package/ui/js/MdEntityTable.js +223 -0
- package/ui/js/MdEscape.js +59 -0
- package/ui/js/MdFront.js +37 -0
- package/ui/js/MdHold.js +32 -0
- package/ui/js/MdHtml.js +307 -0
- package/ui/js/MdHtmlBlock.js +290 -0
- package/ui/js/MdHtmlHeading.js +53 -0
- package/ui/js/MdHtmlImage.js +179 -0
- package/ui/js/MdInline.js +154 -0
- package/ui/js/MdItems.js +212 -0
- package/ui/js/MdLeaf.js +309 -0
- package/ui/js/MdLink.js +196 -0
- package/ui/js/MdMath.js +67 -0
- package/ui/js/MdParagraphs.js +138 -0
- package/ui/js/MdRefs.js +232 -0
- package/ui/js/MdResolve.js +226 -0
- package/ui/js/MdRun.js +300 -0
- package/ui/js/MdUrl.js +226 -0
- package/ui/js/Menu.js +514 -0
- package/ui/js/MenuContext.js +85 -0
- package/ui/js/MenuFit.js +13 -0
- package/ui/js/MenuRefresh.js +74 -0
- package/ui/js/MenuWheel.js +35 -0
- package/ui/js/Messages.js +186 -0
- package/ui/js/Motion.js +16 -0
- package/ui/js/Mounts.js +320 -0
- package/ui/js/MouseNav.js +13 -0
- package/ui/js/Nav.js +329 -0
- package/ui/js/NetFs.js +26 -0
- package/ui/js/OpenWith.js +83 -0
- package/ui/js/Ops.js +585 -0
- package/ui/js/Palette.js +33 -0
- package/ui/js/PathBar.js +260 -0
- package/ui/js/Permissions.js +179 -0
- package/ui/js/Phones.js +112 -0
- package/ui/js/Picker.js +353 -0
- package/ui/js/PlaceMenu.js +96 -0
- package/ui/js/Places.js +265 -0
- package/ui/js/PreviewAsk.js +21 -0
- package/ui/js/PreviewKeys.js +155 -0
- package/ui/js/PreviewSettle.js +29 -0
- package/ui/js/PreviewSwap.js +101 -0
- package/ui/js/PropertyFacts.js +144 -0
- package/ui/js/Protocols.js +296 -0
- package/ui/js/QuickLookKinds.js +27 -0
- package/ui/js/QuickLookRect.js +24 -0
- package/ui/js/RailDrop.js +51 -0
- package/ui/js/RailKeys.js +87 -0
- package/ui/js/RailMenu.js +133 -0
- package/ui/js/Recent.js +135 -0
- package/ui/js/RecentMode.js +156 -0
- package/ui/js/Reload.js +60 -0
- package/ui/js/Renderer.js +9 -0
- package/ui/js/RunFile.js +143 -0
- package/ui/js/Scripts.js +28 -0
- package/ui/js/Scroll.js +304 -0
- package/ui/js/ScrollOff.js +69 -0
- package/ui/js/Search.js +478 -0
- package/ui/js/Selection.js +97 -0
- package/ui/js/Settings.js +476 -0
- package/ui/js/SettingsAbout.js +97 -0
- package/ui/js/SettingsShelf.js +52 -0
- package/ui/js/SheetKeys.js +42 -0
- package/ui/js/SheetQuery.js +281 -0
- package/ui/js/ShelfPile.js +27 -0
- package/ui/js/SlowClick.js +53 -0
- package/ui/js/SlowOp.js +6 -0
- package/ui/js/Sort.js +134 -0
- package/ui/js/Startup.js +63 -0
- package/ui/js/StateWords.js +17 -0
- package/ui/js/Status.js +238 -0
- package/ui/js/Swap.js +166 -0
- package/ui/js/TabMove.js +39 -0
- package/ui/js/Tabs.js +751 -0
- package/ui/js/Tags.js +134 -0
- package/ui/js/Taildrop.js +128 -0
- package/ui/js/Tap.js +180 -0
- package/ui/js/TextSize.js +107 -0
- package/ui/js/Thumbs.js +158 -0
- package/ui/js/Transfer.js +172 -0
- package/ui/js/Trash.js +84 -0
- package/ui/js/TrashDates.js +47 -0
- package/ui/js/TrashDrop.js +64 -0
- package/ui/js/UiState.js +438 -0
- package/ui/js/Unlock.js +152 -0
- package/ui/js/Update.js +130 -0
- package/ui/js/UserDirs.js +56 -0
- 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
|
+
}
|