buninu-browser 0.3.0 → 0.5.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 (296) hide show
  1. package/LICENSES/jsmdcui.txt +22 -0
  2. package/README.md +40 -4
  3. package/frontends/wayland/LICENSE-land +21 -0
  4. package/frontends/wayland/README.md +152 -0
  5. package/frontends/wayland/casty/LICENSE +21 -0
  6. package/frontends/wayland/casty/bookmarks.js +32 -0
  7. package/frontends/wayland/casty/click.js +96 -0
  8. package/frontends/wayland/casty/commands.js +61 -0
  9. package/frontends/wayland/casty/config.js +45 -0
  10. package/frontends/wayland/casty/download-directory.js +28 -0
  11. package/frontends/wayland/casty/download.js +49 -0
  12. package/frontends/wayland/casty/hints.js +334 -0
  13. package/frontends/wayland/casty/keys.js +56 -0
  14. package/frontends/wayland/casty/page-commands.js +80 -0
  15. package/frontends/wayland/casty/prompt-width.js +148 -0
  16. package/frontends/wayland/casty/urlbar.js +606 -0
  17. package/frontends/wayland/client.js +88 -0
  18. package/frontends/wayland/clipboard.js +80 -0
  19. package/frontends/wayland/index.js +130 -0
  20. package/frontends/wayland/input.js +75 -0
  21. package/frontends/wayland/protocol.js +55 -0
  22. package/frontends/wayland/protocols/wayland.xml +3248 -0
  23. package/frontends/wayland/protocols/xdg-shell.xml +1415 -0
  24. package/frontends/wayland/transport.js +120 -0
  25. package/frontends/wayland/urlbar.js +162 -0
  26. package/index.js +28 -1
  27. package/lib/audio/shared-connection.js +31 -0
  28. package/lib/cdp-server.js +15 -2
  29. package/lib/clipboard-command.js +10 -0
  30. package/lib/clipboard-powershell.js +22 -0
  31. package/lib/clipboard.js +37 -2
  32. package/lib/document-types.js +11 -0
  33. package/lib/headless-shell.js +54 -12
  34. package/lib/layout/text-layout.js +17 -9
  35. package/lib/paint/display-list.js +6 -1
  36. package/lib/qml/README.md +1427 -0
  37. package/lib/qml/builtins.js +771 -0
  38. package/lib/qml/canvas-dom.js +115 -0
  39. package/lib/qml/canvas.js +76 -0
  40. package/lib/qml/document.js +1199 -0
  41. package/lib/qml/fonts.js +69 -0
  42. package/lib/qml/format.js +9 -0
  43. package/lib/qml/host.js +352 -0
  44. package/lib/qml/images.js +199 -0
  45. package/lib/qml/launcher.js +132 -0
  46. package/lib/qml/loader.js +521 -0
  47. package/lib/qml/media-renderer.js +49 -0
  48. package/lib/qml/media.js +86 -0
  49. package/lib/qml/models.js +622 -0
  50. package/lib/qml/parser.js +381 -0
  51. package/lib/qml/qs +5 -0
  52. package/lib/qml/qscasty +3 -0
  53. package/lib/qml/qsheadless +3 -0
  54. package/lib/qml/qswayland +3 -0
  55. package/lib/qml/reactive.js +182 -0
  56. package/lib/qml/runtime.js +3603 -0
  57. package/lib/qml/shader/fragment.js +83 -0
  58. package/lib/qml/shader/qsb.js +27 -0
  59. package/lib/qml/shader/renderer.js +39 -0
  60. package/lib/qml/shader/runtime.js +61 -0
  61. package/lib/qml/shapes.js +251 -0
  62. package/lib/qml/shortcuts.js +65 -0
  63. package/lib/qml/text.js +109 -0
  64. package/lib/qml/textures.js +126 -0
  65. package/lib/qml/wayland-clipboard.js +32 -0
  66. package/lib/qml/window-constraints.js +16 -0
  67. package/lib/qml/worker-thread.js +70 -0
  68. package/lib/render-tree/index.js +16 -1
  69. package/lib/renderer/bindings.js +16 -1
  70. package/lib/renderer/canvas-2d.js +29 -0
  71. package/lib/renderer/document-selection.js +19 -0
  72. package/lib/renderer/host.js +45 -17
  73. package/lib/renderer/main.js +21 -6
  74. package/lib/renderer/page-realm.js +20 -10
  75. package/lib/renderer/page-renderer.js +497 -42
  76. package/lib/renderer/pointer-move.js +5 -3
  77. package/lib/renderer/render-interval.js +9 -0
  78. package/lib/renderer/text-input-paint.js +54 -0
  79. package/lib/renderer/text-input.js +57 -0
  80. package/lib/style/computed-style.js +10 -4
  81. package/package.json +1 -1
  82. package/test/audio-connection-lifetime.test.js +46 -0
  83. package/test/canvas-paint.test.js +8 -0
  84. package/test/clipboard.test.js +19 -0
  85. package/test/computed-style.test.js +12 -0
  86. package/test/document-selection.test.js +27 -0
  87. package/test/double-click.test.js +85 -0
  88. package/test/fixtures/canvas-damage.js +40 -0
  89. package/test/fixtures/fake-renderer.js +1 -0
  90. package/test/fixtures/flea-helpers/Dockerfile +36 -0
  91. package/test/fixtures/flea-helpers/bat.mjs +43 -0
  92. package/test/fixtures/flea-helpers/bin/bat +3 -0
  93. package/test/fixtures/flea-helpers/bin/bwrap +10 -0
  94. package/test/fixtures/flea-helpers/bin/bwrap-real-filter +9 -0
  95. package/test/fixtures/flea-helpers/bin/glow +3 -0
  96. package/test/fixtures/flea-helpers/bin/qs +3 -0
  97. package/test/fixtures/flea-helpers/bin/unsupported +3 -0
  98. package/test/fixtures/flea-helpers/check-highlighting.mjs +47 -0
  99. package/test/fixtures/flea-helpers/check-media.mjs +29 -0
  100. package/test/fixtures/flea-helpers/check-preview.mjs +27 -0
  101. package/test/fixtures/flea-helpers/check.mjs +36 -0
  102. package/test/fixtures/flea-helpers/highlight-cases.json +227 -0
  103. package/test/fixtures/flea-helpers/source-mime.xml +28 -0
  104. package/test/fixtures/flea-helpers/syntax-compat.mjs +23 -0
  105. package/test/fixtures/flea-thumbnail-stub/flea-placeholder.thumbnailer +4 -0
  106. package/test/fixtures/flea-thumbnail-stub/flea-thumbnail-stub +3 -0
  107. package/test/fixtures/omastorm-helpers/Dockerfile +35 -0
  108. package/test/fixtures/omastorm-helpers/check.mjs +56 -0
  109. package/test/fixtures/omastorm-helpers/launch.mjs +24 -0
  110. package/test/fixtures/omastorm-helpers/prepare.mjs +17 -0
  111. package/test/fixtures/omastorm-helpers/runtime.mjs +32 -0
  112. package/test/fixtures/pointer-paint-batching.js +23 -0
  113. package/test/fixtures/qml/flea/EscapeHint.qml +11 -0
  114. package/test/fixtures/qml/flea/LICENSE +21 -0
  115. package/test/fixtures/qml/flea/README.md +25 -0
  116. package/test/fixtures/qml/flea/Theme.qml +8 -0
  117. package/test/fixtures/qml/flea/demo.qml +24 -0
  118. package/test/fixtures/qml/flea/qmldir +3 -0
  119. package/test/fixtures/qml/flea-theme/LICENSE-Flea +21 -0
  120. package/test/fixtures/qml/flea-theme/LICENSE-Omarchy +20 -0
  121. package/test/fixtures/qml/flea-theme/README.md +70 -0
  122. package/test/fixtures/qml/flea-theme/button.qml +17 -0
  123. package/test/fixtures/qml/flea-theme/demo.qml +27 -0
  124. package/test/fixtures/qml/flea-theme/field.qml +21 -0
  125. package/test/fixtures/qml/flea-theme/imports/qs/Commons/BorderGeometry.js +373 -0
  126. package/test/fixtures/qml/flea-theme/imports/qs/Commons/Color.qml +258 -0
  127. package/test/fixtures/qml/flea-theme/imports/qs/Commons/I18n.qml +118 -0
  128. package/test/fixtures/qml/flea-theme/imports/qs/Commons/Numbers.js +19 -0
  129. package/test/fixtures/qml/flea-theme/imports/qs/Commons/Plural.js +91 -0
  130. package/test/fixtures/qml/flea-theme/imports/qs/Commons/Style.qml +561 -0
  131. package/test/fixtures/qml/flea-theme/imports/qs/Commons/Util.qml +188 -0
  132. package/test/fixtures/qml/flea-theme/imports/qs/Commons/qmldir +13 -0
  133. package/test/fixtures/qml/flea-theme/segment.qml +17 -0
  134. package/test/fixtures/qml/flea-theme/settings.qml +58 -0
  135. package/test/fixtures/qml/flea-theme/text-metrics.qml +10 -0
  136. package/test/fixtures/qml/flea-theme/ui/DialogButton.qml +150 -0
  137. package/test/fixtures/qml/flea-theme/ui/DialogField.qml +147 -0
  138. package/test/fixtures/qml/flea-theme/ui/EscapeHint.qml +11 -0
  139. package/test/fixtures/qml/flea-theme/ui/Glass.qml +114 -0
  140. package/test/fixtures/qml/flea-theme/ui/Glyph.qml +54 -0
  141. package/test/fixtures/qml/flea-theme/ui/GlyphSolid.qml +22 -0
  142. package/test/fixtures/qml/flea-theme/ui/Reveal.qml +54 -0
  143. package/test/fixtures/qml/flea-theme/ui/SettingsRuler.qml +85 -0
  144. package/test/fixtures/qml/flea-theme/ui/SettingsSegment.qml +85 -0
  145. package/test/fixtures/qml/flea-theme/ui/StableModel.qml +89 -0
  146. package/test/fixtures/qml/flea-theme/ui/Theme.qml +460 -0
  147. package/test/fixtures/qml/flea-theme/ui/ThemeColors.qml +43 -0
  148. package/test/fixtures/qml/flea-theme/ui/ViewState.qml +565 -0
  149. package/test/fixtures/qml/flea-theme/ui/js/Anchor.js +379 -0
  150. package/test/fixtures/qml/flea-theme/ui/js/AnchorHold.js +162 -0
  151. package/test/fixtures/qml/flea-theme/ui/js/Archive.js +157 -0
  152. package/test/fixtures/qml/flea-theme/ui/js/BackReturn.js +110 -0
  153. package/test/fixtures/qml/flea-theme/ui/js/Buttons.js +54 -0
  154. package/test/fixtures/qml/flea-theme/ui/js/ColumnMenu.js +111 -0
  155. package/test/fixtures/qml/flea-theme/ui/js/Columns.js +298 -0
  156. package/test/fixtures/qml/flea-theme/ui/js/Contrast.js +157 -0
  157. package/test/fixtures/qml/flea-theme/ui/js/Density.js +44 -0
  158. package/test/fixtures/qml/flea-theme/ui/js/DirSizes.js +129 -0
  159. package/test/fixtures/qml/flea-theme/ui/js/ExtThumbs.js +115 -0
  160. package/test/fixtures/qml/flea-theme/ui/js/Filter.js +284 -0
  161. package/test/fixtures/qml/flea-theme/ui/js/FolderSorts.js +108 -0
  162. package/test/fixtures/qml/flea-theme/ui/js/Format.js +305 -0
  163. package/test/fixtures/qml/flea-theme/ui/js/Icons.js +206 -0
  164. package/test/fixtures/qml/flea-theme/ui/js/Input.js +39 -0
  165. package/test/fixtures/qml/flea-theme/ui/js/KeyName.js +64 -0
  166. package/test/fixtures/qml/flea-theme/ui/js/Keymap.js +370 -0
  167. package/test/fixtures/qml/flea-theme/ui/js/Kinds.js +145 -0
  168. package/test/fixtures/qml/flea-theme/ui/js/Lists.js +11 -0
  169. package/test/fixtures/qml/flea-theme/ui/js/MakeDefault.js +186 -0
  170. package/test/fixtures/qml/flea-theme/ui/js/Match.js +27 -0
  171. package/test/fixtures/qml/flea-theme/ui/js/Material.js +109 -0
  172. package/test/fixtures/qml/flea-theme/ui/js/Menu.js +513 -0
  173. package/test/fixtures/qml/flea-theme/ui/js/Motion.js +16 -0
  174. package/test/fixtures/qml/flea-theme/ui/js/Mounts.js +320 -0
  175. package/test/fixtures/qml/flea-theme/ui/js/MouseNav.js +13 -0
  176. package/test/fixtures/qml/flea-theme/ui/js/Nav.js +328 -0
  177. package/test/fixtures/qml/flea-theme/ui/js/Palette.js +33 -0
  178. package/test/fixtures/qml/flea-theme/ui/js/Places.js +236 -0
  179. package/test/fixtures/qml/flea-theme/ui/js/Protocols.js +296 -0
  180. package/test/fixtures/qml/flea-theme/ui/js/RecentMode.js +154 -0
  181. package/test/fixtures/qml/flea-theme/ui/js/Search.js +396 -0
  182. package/test/fixtures/qml/flea-theme/ui/js/Settings.js +476 -0
  183. package/test/fixtures/qml/flea-theme/ui/js/SettingsAbout.js +99 -0
  184. package/test/fixtures/qml/flea-theme/ui/js/SettingsShelf.js +52 -0
  185. package/test/fixtures/qml/flea-theme/ui/js/Sort.js +127 -0
  186. package/test/fixtures/qml/flea-theme/ui/js/StateWords.js +42 -0
  187. package/test/fixtures/qml/flea-theme/ui/js/Swap.js +166 -0
  188. package/test/fixtures/qml/flea-theme/ui/js/TextSize.js +107 -0
  189. package/test/fixtures/qml/flea-theme/ui/js/Thumbs.js +158 -0
  190. package/test/fixtures/qml/flea-theme/ui/js/UiState.js +438 -0
  191. package/test/fixtures/qml/flea-theme/ui/js/Update.js +132 -0
  192. package/test/fixtures/qml/flea-theme/ui/js/UserDirs.js +56 -0
  193. package/test/fixtures/qml/flea-theme/ui/qmldir +227 -0
  194. package/test/fixtures/qml/hello.qml +26 -0
  195. package/test/fixtures/qml/imports/Demo/Toolkit/VersionLabel.qml +2 -0
  196. package/test/fixtures/qml/imports/Demo/Toolkit/VersionLabelNew.qml +2 -0
  197. package/test/fixtures/qml/imports/Demo/Toolkit/qmldir +3 -0
  198. package/test/fixtures/qml/imports/components/Badge.qml +15 -0
  199. package/test/fixtures/qml/imports/logic/base.js +2 -0
  200. package/test/fixtures/qml/imports/logic/counter.js +4 -0
  201. package/test/fixtures/qml/imports/logic/math.js +3 -0
  202. package/test/fixtures/qml/imports/logic/shared.js +3 -0
  203. package/test/fixtures/qml/imports/main.qml +21 -0
  204. package/test/fixtures/qml/imports/theme/Theme.qml +8 -0
  205. package/test/fixtures/qml/imports/theme/qmldir +2 -0
  206. package/test/fixtures/qml/multiply.qml +61 -0
  207. package/test/fixtures/qml-canvas-dom.js +90 -0
  208. package/test/fixtures/qml-fonts/main.qml +10 -0
  209. package/test/fixtures/qml-locale/check.mjs +6 -0
  210. package/test/fixtures/qml-locale/main.qml +8 -0
  211. package/test/fixtures/qml-media-audio.js +39 -0
  212. package/test/fixtures/qml-shader/grab.qml +14 -0
  213. package/test/fixtures/qml-shader/gradient.frag +5 -0
  214. package/test/fixtures/qml-shader/main.qml +14 -0
  215. package/test/fixtures/qml-shader/texture-grab.qml +25 -0
  216. package/test/fixtures/qml-shader/texture-size.frag +5 -0
  217. package/test/fixtures/qml-shader-check.mjs +24 -0
  218. package/test/fixtures/title-no-paint.js +20 -0
  219. package/test/helpers/flea-sandbox.js +48 -0
  220. package/test/helpers/quickshell-fixture.js +125 -0
  221. package/test/html-clipboard-wayland.test.js +47 -0
  222. package/test/index.test.js +13 -0
  223. package/test/manual-casty-without-qml.js +87 -0
  224. package/test/manual-double-click.html +21 -0
  225. package/test/manual-flea-application.js +49 -0
  226. package/test/manual-flea-binary.js +62 -0
  227. package/test/manual-flea-qml.js +9 -0
  228. package/test/manual-flea-settings.js +40 -0
  229. package/test/manual-flea-theme.js +40 -0
  230. package/test/manual-mouse-buttons.html +18 -0
  231. package/test/manual-omastorm-engine.mjs +19 -0
  232. package/test/manual-omastorm-shaders.mjs +28 -0
  233. package/test/manual-omastorm-software.mjs +25 -0
  234. package/test/manual-pointer-scroll.html +43 -0
  235. package/test/manual-qml-removal.js +46 -0
  236. package/test/manual-without-qml.js +45 -0
  237. package/test/pointer-drag.test.js +104 -0
  238. package/test/qml-canvas-dom.test.js +37 -0
  239. package/test/qml-canvas.test.js +21 -0
  240. package/test/qml-clipboard-bridge.test.js +25 -0
  241. package/test/qml-clipboard-wayland.test.js +40 -0
  242. package/test/qml-connections-timing.test.js +95 -0
  243. package/test/qml-controls-window.test.js +182 -0
  244. package/test/qml-dynamic.test.js +401 -0
  245. package/test/qml-flea-app.test.js +146 -0
  246. package/test/qml-flea-backend.test.js +78 -0
  247. package/test/qml-flea-columns-backend.test.js +38 -0
  248. package/test/qml-flea-compile.test.js +78 -0
  249. package/test/qml-flea-launcher.test.js +88 -0
  250. package/test/qml-flea-markdown-backend.test.js +31 -0
  251. package/test/qml-flea-media.test.js +28 -0
  252. package/test/qml-flea-navigation-backend.test.js +35 -0
  253. package/test/qml-flea-navigation-timing.test.js +147 -0
  254. package/test/qml-flea-preview-backend.test.js +53 -0
  255. package/test/qml-flea-previews.test.js +163 -0
  256. package/test/qml-flea-rows.test.js +101 -0
  257. package/test/qml-flea-textures.test.js +59 -0
  258. package/test/qml-flea-view-switch.test.js +33 -0
  259. package/test/qml-flea-wayland.test.js +68 -0
  260. package/test/qml-flea.test.js +34 -0
  261. package/test/qml-fonts.test.js +31 -0
  262. package/test/qml-grid-multiline.test.js +48 -0
  263. package/test/qml-host.test.js +238 -0
  264. package/test/qml-imports.test.js +102 -0
  265. package/test/qml-inherited-handlers.test.js +51 -0
  266. package/test/qml-input-selection.test.js +66 -0
  267. package/test/qml-interactions.test.js +309 -0
  268. package/test/qml-language.test.js +167 -0
  269. package/test/qml-launcher.test.js +54 -0
  270. package/test/qml-layout-text.test.js +205 -0
  271. package/test/qml-locale.test.js +45 -0
  272. package/test/qml-media.test.js +63 -0
  273. package/test/qml-nonvisual-visible.test.js +19 -0
  274. package/test/qml-persisted-delegates.test.js +45 -0
  275. package/test/qml-quickshell-controls.test.js +65 -0
  276. package/test/qml-quickshell-settings.test.js +62 -0
  277. package/test/qml-repeater.test.js +72 -0
  278. package/test/qml-shader-runtime.test.js +6 -0
  279. package/test/qml-shortcuts.test.js +39 -0
  280. package/test/qml-socket.test.js +60 -0
  281. package/test/qml-software-shader.test.js +55 -0
  282. package/test/qml-style-updates.test.js +124 -0
  283. package/test/qml-textures.test.js +66 -0
  284. package/test/qml-views.test.js +332 -0
  285. package/test/qml-window-update.test.js +36 -0
  286. package/test/qml-worker.test.js +69 -0
  287. package/test/qml.test.js +83 -0
  288. package/test/render-interval.test.js +33 -0
  289. package/test/renderer-host.test.js +11 -0
  290. package/test/text-input-pointer.test.js +31 -0
  291. package/test/text-input-scroll.test.js +29 -0
  292. package/test/text-input.test.js +47 -0
  293. package/test/title-no-paint.test.js +6 -0
  294. package/test/wayland-frontend.test.js +83 -0
  295. package/test/wayland-scroll.test.js +40 -0
  296. package/test/wayland-urlbar.test.js +61 -0
@@ -0,0 +1,145 @@
1
+ .pragma library
2
+
3
+ .import "Archive.js" as Archive
4
+ .import "Format.js" as Format
5
+
6
+ // How a row is classified: which of the twelve preview states it is, and the extension families that
7
+ // decide the three the backend's icon cannot. Split out of Facts.js, which owns the fact tables.
8
+
9
+ var IMAGE = "image"
10
+ var VIDEO = "video"
11
+ var AUDIO = "audio"
12
+ var PDF = "pdf"
13
+ var TEXT = "text"
14
+ var CODE = "code"
15
+ var ARCHIVE = "archive"
16
+ var SYMLINK = "symlink"
17
+ var MULTI = "multi"
18
+ var LOADING = "loading"
19
+ var ERROR = "error"
20
+ var UNSUPPORTED = "unsupported"
21
+ var FONT = "font"
22
+
23
+ // src/backend/rows.rs's own UNKNOWN_KIND: the Kind a row gets when nothing could describe its type.
24
+ var UNKNOWN_KIND = "Data"
25
+
26
+ var CODE_EXTENSIONS = [
27
+ ".rs", ".py", ".js", ".ts", ".jsx", ".tsx", ".c", ".h", ".cpp", ".hpp", ".cc", ".go", ".rb",
28
+ ".java", ".kt", ".swift", ".lua", ".pl", ".php", ".sh", ".bash", ".zsh", ".fish", ".vim",
29
+ ".qml", ".css", ".scss", ".html", ".xml", ".json", ".toml", ".yaml", ".yml", ".ini", ".conf",
30
+ ".sql", ".mjs", ".cjs"
31
+ ]
32
+
33
+ function isCode(name) {
34
+ var lower = String(name).toLowerCase()
35
+ for (var i = 0; i < CODE_EXTENSIONS.length; i++) {
36
+ var e = CODE_EXTENSIONS[i]
37
+ if (lower.length > e.length && lower.indexOf(e, lower.length - e.length) !== -1) {
38
+ return true
39
+ }
40
+ }
41
+ return false
42
+ }
43
+
44
+ var MARKDOWN_EXTENSIONS = [".md", ".markdown", ".mkd"]
45
+
46
+ function isMarkdown(name) {
47
+ var lower = String(name).toLowerCase()
48
+ for (var i = 0; i < MARKDOWN_EXTENSIONS.length; i++) {
49
+ var e = MARKDOWN_EXTENSIONS[i]
50
+ if (lower.length > e.length && lower.indexOf(e, lower.length - e.length) !== -1) {
51
+ return true
52
+ }
53
+ }
54
+ return false
55
+ }
56
+
57
+ function isHtml(name) { return /\.(html|htm)$/i.test(String(name)) }
58
+
59
+ // TrueType, OpenType and collections (font/ttf, font/otf, font/collection); the backend checks the MIME type again.
60
+ var FONT_EXTENSIONS = [".ttf", ".otf", ".ttc"]
61
+
62
+ function isFont(name) {
63
+ var lower = String(name).toLowerCase()
64
+ return FONT_EXTENSIONS.some(function (e) { return lower.length > e.length && lower.indexOf(e, lower.length - e.length) !== -1 })
65
+ }
66
+
67
+ // Quick Look's font sample: one sentence at three sizes, in board pixels before the text-size ratio and the pixel ratio.
68
+ var SAMPLE_TEXT = "The quick brown fox jumps over the lazy dog"
69
+ var SAMPLE_SIZES = [22, 15, 12]
70
+
71
+ // One count for every font pane, so an answer meant for an earlier pane never carries a later pane's id.
72
+ var lookSeq = 0
73
+ function nextLookId() { lookSeq += 1; return lookSeq }
74
+
75
+ // "Inter · Bold · 312.0 kB · 2,548 glyphs"; a table the font lacks drops its part, and the size is always known.
76
+ // pluralWord is Ops.pluralWord, handed in because Ops reaches Sort.js and RecentMode.js, which import this file.
77
+ function fontLine(family, style, bytes, glyphs, pluralWord) {
78
+ var parts = [family, style, Format.size(bytes)].filter(function (p) { return p })
79
+ if (glyphs > 0)
80
+ parts.push(pluralWord(glyphs, "%1 glyph", "%1 glyphs").replace("%1", Format.count(glyphs)))
81
+ return parts.join(" \u00b7 ")
82
+ }
83
+
84
+ // The eleven camera RAW types the backend copies a preview out of, told apart by extension like a PDF; Sample input: "IMG_0412.CR3" is true.
85
+ function isRaw(name) {
86
+ return /\.(cr[23]|nef|nrw|arw|sr2|dng|raf|orf|rw2|pef)$/i.test(String(name))
87
+ }
88
+
89
+ function isPdf(name) {
90
+ var lower = String(name).toLowerCase()
91
+ return lower.length > 4 && lower.indexOf(".pdf", lower.length - 4) !== -1
92
+ }
93
+
94
+ // The MIME icon table files 3D models under image-x-generic, so they route as images, but no Qt image plugin decodes one.
95
+ function isModel(name) {
96
+ return /\.(stl|3mf|obj|mtl|gltf|glb)$/i.test(String(name))
97
+ }
98
+
99
+ // The icon name is the classification the backend already made, so the column never re-derives one.
100
+ // Its first segment is the freedesktop family, and the family is what classifies: this box's
101
+ // generic-icons table maps text/* to five different text- names, and a list of the names seen so
102
+ // far is exactly how the Quick Look refused every image for as long as it kept one.
103
+ function kindState(icon) {
104
+ var name = String(icon)
105
+ switch (name) {
106
+ case "text-x-script":
107
+ case "text-html":
108
+ case "application-xml": return CODE
109
+ case "package-x-generic": return ARCHIVE
110
+ }
111
+ if (name.indexOf("image-") === 0) return IMAGE
112
+ if (name.indexOf("video-") === 0) return VIDEO
113
+ if (name.indexOf("audio-") === 0) return AUDIO
114
+ if (name.indexOf("text-") === 0) return TEXT
115
+ // A .doc or .odt shares the office icon with a PDF, and a PDF was already told apart by its
116
+ // extension. What is left is binary, so it is Unsupported rather than a newline count over a blob.
117
+ return UNSUPPORTED
118
+ }
119
+
120
+ // A directory is not a preview subject: the column shows what is inside it instead.
121
+ function isPreviewable(row) {
122
+ return row !== null && row !== undefined && row.d !== true
123
+ }
124
+
125
+ // A name the icon cannot route, told apart by its own extension: a PDF shares x-office-document, and widened archives draw other marks.
126
+ function stateByExtension(name) {
127
+ if (isPdf(name)) return PDF
128
+ if (Archive.isArchive(name)) return ARCHIVE
129
+ if (/\.(csv|tsv)$/i.test(String(name))) return TEXT
130
+ return ""
131
+ }
132
+
133
+ // Quick Look's kind from the icon, the name and a served thumbnail, Facts.state's row-free tests; code and markdown read as text.
134
+ function quickLookKind(icon, name, thumbnailed) {
135
+ if (isPdf(name)) return PDF
136
+ if (isFont(name)) return FONT
137
+ if (isMarkdown(name)) return TEXT
138
+ if (/\.(csv|tsv)$/i.test(String(name))) return TEXT
139
+ // The client's own extension rule, because the backend's icon cannot name the widened formats.
140
+ if (Archive.isArchive(name)) return ARCHIVE
141
+ var byIcon = kindState(icon)
142
+ // A model no thumbnailer serves has nothing to draw, so it takes the generic file pane.
143
+ if (byIcon === IMAGE && isModel(name) && !thumbnailed) return UNSUPPORTED
144
+ return byIcon === CODE ? TEXT : byIcon
145
+ }
@@ -0,0 +1,11 @@
1
+ .pragma library
2
+
3
+ // The largest length an ECMAScript array can hold, 2^32 - 1.
4
+ var MAX_LENGTH = 4294967295
5
+
6
+ // QVariant sequences crossing a QML var signal expose list methods without being JavaScript Arrays.
7
+ function isList(value) {
8
+ return Array.isArray(value) || (value !== null && typeof value === "object"
9
+ && Number.isInteger(value.length) && value.length >= 0 && value.length <= MAX_LENGTH
10
+ && typeof value.every === "function")
11
+ }
@@ -0,0 +1,186 @@
1
+ .pragma library
2
+
3
+ // Settings > About's Make Flea the default: which state the row is in, the note under it and what a press runs; ui/DefaultClaim.qml runs the processes.
4
+
5
+ .import "Format.js" as Format
6
+
7
+ // Whole sentences with "%1" for the program that never started, its name and not its command line.
8
+ var WORDS = {
9
+ unstarted: "%1 could not start"
10
+ }
11
+
12
+ // The row's id, which ui/SettingsPanel.qml routes to the run instead of writing it into ui.json.
13
+ var ROW_ID = "makeDefault"
14
+ // The entry flea --default points the desktop at; the box is ticked exactly when xdg-mime answers it.
15
+ var DESKTOP_ID = "com.thisisgm.flea.desktop"
16
+ // src/main.rs claim_both() says this and still exits 0 when a build has no flea.portal to route file dialogs to.
17
+ var SKIPPED = "no file chooser service is installed, so Flea could not become the file chooser"
18
+ // src/defaults.rs EXIT_UNINSTALLED: the status claim() exits with when the running binary has no desktop entry to point at.
19
+ var UNINSTALLED_STATUS = 3
20
+ // The portal reads its routing once, at startup; try-restart leaves a portal that is not running alone.
21
+ var RESTART = ["systemctl", "--user", "try-restart", "xdg-desktop-portal.service"]
22
+ // flea's own stderr lines start with its name, which the note drops.
23
+ var OWN_PREFIX = "flea: "
24
+
25
+ // Nothing run in this process yet; an entry is assumed until the probe or a refusal says otherwise.
26
+ function idle() {
27
+ return { running: false, claiming: false, reading: false, readFrom: 0, restarting: false, outcome: "", error: "", packaged: true }
28
+ }
29
+
30
+ // A run in flight, or a build with no entry, takes no press.
31
+ function inert(claim) {
32
+ return claim.running || claim.packaged === false
33
+ }
34
+
35
+ // flea's arguments for a press, or null while the row is inert.
36
+ function press(handler, claim) {
37
+ if (inert(claim))
38
+ return null
39
+ return handler === DESKTOP_ID ? ["--default", "off"] : ["--default"]
40
+ }
41
+
42
+ // A new run drops the last one's outcome; which way it goes picks the working note.
43
+ function started(claim, args) {
44
+ return { running: true, claiming: args.length === 1, reading: false, readFrom: 0, restarting: false, outcome: "", error: "",
45
+ packaged: claim.packaged }
46
+ }
47
+
48
+ // Still running until a handler read numbered nextRead or later lands and a switch that went through has restarted the portal.
49
+ // Sample stderr: "flea: no file chooser service is installed, so Flea could not become the file chooser\n"
50
+ function finished(claim, code, stderr, nextRead) {
51
+ var text = stderr || ""
52
+ var next = Object.assign({}, claim, { reading: true, readFrom: nextRead, restarting: code === 0 })
53
+ if (code === 0) {
54
+ next.outcome = text.indexOf(SKIPPED) >= 0 ? "partly" : ""
55
+ return next
56
+ }
57
+ if (code === UNINSTALLED_STATUS) {
58
+ next.packaged = false
59
+ return next
60
+ }
61
+ next.outcome = "failed"
62
+ next.error = errorLine(text, code, claim.claiming)
63
+ return next
64
+ }
65
+
66
+ // xdg-mime's stderr reaches flea's own, so flea's line is the one that starts with its name.
67
+ // Sample stderr: "xdg-mime: no method available\nflea: xdg-mime default exited 3\n"
68
+ function errorLine(stderr, code, claiming) {
69
+ var lines = stderr.split("\n").map(function (line) { return line.trim() })
70
+ var own = lines.filter(function (line) { return line.indexOf(OWN_PREFIX) === 0 })[0]
71
+ if (own !== undefined)
72
+ return own.substring(OWN_PREFIX.length)
73
+ var first = lines.filter(function (line) { return line.length > 0 })[0]
74
+ return first !== undefined ? first : (claiming ? "flea --default" : "flea --default off") + " exited " + code
75
+ }
76
+
77
+ // The handler read numbered read has landed; only one begun after the run exited ends it, and only once the portal restart has answered too.
78
+ function settled(claim, read) {
79
+ if (!claim.reading || read < claim.readFrom)
80
+ return claim
81
+ return Object.assign({}, claim, { reading: false, running: claim.restarting })
82
+ }
83
+
84
+ // A Process's exit and its collector's text land in either order (AGENTS.md "The state file"), so an answer is read once it holds both.
85
+ // Sample: landed(landed({}, { code: 0 }), { text: "com.thisisgm.flea.desktop\n" }) is { code: 0, text: "com.thisisgm.flea.desktop\n" }
86
+ function landed(answer, half) {
87
+ return Object.assign({}, answer, half)
88
+ }
89
+
90
+ // An empty text is an answer too: a run that says nothing has still finished saying it.
91
+ function whole(answer) {
92
+ return answer.code !== undefined && answer.text !== undefined
93
+ }
94
+
95
+ // The whole answer a program that never started is given: no real exit status is negative.
96
+ var NEVER_RAN = { code: -1, text: "" }
97
+
98
+ // ui/ViewState.qml's writer rule, measured on Quickshell 0.3.1: a program that cannot start raises no exited, only running going false, and a real exit lands its status before that false.
99
+ function neverRan(answer, running) {
100
+ return !running && answer.code === undefined
101
+ }
102
+
103
+ // The handler an answer states; any other status, a read that never ran among them, states none, which About shows as Not reported.
104
+ function handlerOf(answer) {
105
+ return answer.code === 0 ? answer.text.trim() : ""
106
+ }
107
+
108
+ // A run whose program never started wrote nothing, so it is over at once, failed, naming what could not start.
109
+ // Sample command: ["/usr/bin/flea", "--default"]
110
+ function unstarted(claim, command) {
111
+ return Object.assign({}, claim, { running: false, reading: false, restarting: false, outcome: "failed",
112
+ error: Format.fill(WORDS.unstarted, String(command[0]).split("/").pop()) })
113
+ }
114
+
115
+ // A portal that would not restart keeps the switch as it went; partly keeps its own note, whose dialogs never follow.
116
+ function restarted(claim, ok) {
117
+ var outcome = !ok && claim.outcome === "" ? "portal" : claim.outcome
118
+ return Object.assign({}, claim, { restarting: false, running: claim.reading, outcome: outcome })
119
+ }
120
+
121
+ // restarted() clears restarting on a real exit before running goes false, so a stop that finds it still set is a systemctl that never ran.
122
+ function restartStopped(claim, running) {
123
+ return !running && claim.restarting ? restarted(claim, false) : claim
124
+ }
125
+
126
+ function probed(claim, found) {
127
+ return Object.assign({}, claim, { packaged: found })
128
+ }
129
+
130
+ // One of off, on, working, partly, portal, failed, unpackaged.
131
+ function state(handler, claim) {
132
+ if (claim.packaged === false)
133
+ return "unpackaged"
134
+ if (claim.running)
135
+ return "working"
136
+ if (claim.outcome === "failed")
137
+ return "failed"
138
+ if (handler === DESKTOP_ID && claim.outcome === "partly")
139
+ return "partly"
140
+ if (claim.outcome === "portal")
141
+ return "portal"
142
+ return handler === DESKTOP_ID ? "on" : "off"
143
+ }
144
+
145
+ // [words, role] for the one line under the row, or null when off says nothing.
146
+ function note(handler, claim) {
147
+ var now = state(handler, claim)
148
+ if (now === "on")
149
+ return ["Folders, Show in folder and file dialogs open Flea.", "foreground"]
150
+ if (now === "working")
151
+ return [claim.claiming ? "Making Flea the default" : "Handing folders back", "muted"]
152
+ if (now === "partly")
153
+ return ["File dialogs need the flea package's portal files.", "foreground"]
154
+ if (now === "portal")
155
+ return ["File dialogs follow after xdg-desktop-portal restarts.", "foreground"]
156
+ if (now === "failed")
157
+ return [claim.error, "error"]
158
+ if (now === "unpackaged")
159
+ return ["Install a Flea package to make it the default.", "foreground"]
160
+ return null
161
+ }
162
+
163
+ // The check row and its note for About's This box group; the note elides on one line rather than wrapping.
164
+ function rows(handler, claim) {
165
+ var live = claim || idle()
166
+ var out = [{ kind: "check", id: ROW_ID, label: "Make Flea the default", on: handler === DESKTOP_ID, inert: inert(live) }]
167
+ var line = note(handler, live)
168
+ if (line !== null)
169
+ out.push({ kind: "hint", label: line[0], role: line[1], elide: "right" })
170
+ return out
171
+ }
172
+
173
+ // src/userfile.rs data_file()'s ladder: the data home, then every data dir, an empty variable read as unset.
174
+ // Sample env: { HOME: "/home/gm", XDG_DATA_HOME: "", XDG_DATA_DIRS: "/usr/local/share:/usr/share" }
175
+ function entryPaths(env) {
176
+ var home = env.XDG_DATA_HOME || (env.HOME ? env.HOME + "/.local/share" : "")
177
+ var dirs = (env.XDG_DATA_DIRS || "/usr/local/share:/usr/share").split(":")
178
+ return [home].concat(dirs)
179
+ .filter(function (dir) { return dir.length > 0 })
180
+ .map(function (dir) { return dir + "/applications/" + DESKTOP_ID })
181
+ }
182
+
183
+ // data_file()'s regular-file test; each path is an argument, so no path reaches the shell as code.
184
+ function probeCommand(paths) {
185
+ return ["sh", "-c", "for f; do [ -f \"$f\" ] && exit 0; done; exit 1", "sh"].concat(paths)
186
+ }
@@ -0,0 +1,27 @@
1
+ .pragma library
2
+
3
+ // A search row's name is its path relative to the search root, so the display splits it here and
4
+ // the wire never carries a second shape; see docs/protocol.md "search".
5
+ function base(path) {
6
+ var i = String(path).lastIndexOf("/")
7
+ return i < 0 ? String(path) : String(path).substring(i + 1)
8
+ }
9
+
10
+ // The location column: the parent path relative to the scope, empty for a match in the root itself.
11
+ function location(path) {
12
+ var i = String(path).lastIndexOf("/")
13
+ return i < 0 ? "" : String(path).substring(0, i)
14
+ }
15
+
16
+ // Where to paint the accent run inside a name, mirroring the backend's own case-insensitive match.
17
+ // corner: a character whose lowercase form is a different length (Turkish dotted capital I) can
18
+ // shift the run by one; the name still renders whole, and the backend alone decides what matched.
19
+ function run(hay, needle) {
20
+ var h = String(hay)
21
+ var n = String(needle)
22
+ if (n.length === 0) {
23
+ return { start: -1, length: 0 }
24
+ }
25
+ var at = h.toLowerCase().indexOf(n.toLowerCase())
26
+ return at < 0 ? { start: -1, length: 0 } : { start: at, length: n.length }
27
+ }
@@ -0,0 +1,109 @@
1
+ .pragma library
2
+ .import "Contrast.js" as Contrast
3
+
4
+ // Omarchy Glassy dims its blurred backdrop to 0.75; channels and alpha use whole 8-bit steps.
5
+ var STEPS = 255
6
+ var MIN_ALPHA = Math.ceil(0.75 * STEPS)
7
+ var INK_STEP = 1.25
8
+ // Twenty bisections resolve lightness more finely than one 8-bit colour channel.
9
+ var LIGHTNESS_SEARCH_STEPS = 20
10
+ // Half an 8-bit channel step repairs rounding without skipping the first passing colour.
11
+ var ROUNDING_REPAIR_STEPS = 512
12
+
13
+ function ground(plane, a, backdrop) {
14
+ return Contrast.hexOf(Contrast.over(String(plane), a / STEPS, backdrop))
15
+ }
16
+
17
+ function worst(ink, c, a, planes) {
18
+ var least = Infinity
19
+ var grounds = planes || [c.background, c.surface]
20
+ var brightness = c.blurBrightness === undefined ? 0.75 : c.blurBrightness
21
+ var white = Contrast.hexOf([brightness, brightness, brightness])
22
+ var backdrops = [white, "#000000"]
23
+ for (var p = 0; p < grounds.length; p++)
24
+ for (var b = 0; b < backdrops.length; b++)
25
+ least = Math.min(least, Contrast.ratio(String(ink), ground(grounds[p], a, backdrops[b])))
26
+ return least
27
+ }
28
+
29
+ function direction(c) {
30
+ var fg = Contrast.parse(String(c.foreground)), bg = Contrast.parse(String(c.background))
31
+ return Contrast.luminance(fg[0], fg[1], fg[2]) > Contrast.luminance(bg[0], bg[1], bg[2]) ? [1, 1, 1] : [0, 0, 0]
32
+ }
33
+
34
+ // The R3 lightness walk, including its rounding repair, applied to the live palette rather than a theme-name table.
35
+ function inkHolds(ink, c, a, need, quiet) {
36
+ if (worst(ink, c, a) < need) return false
37
+ if (quiet === undefined) return true
38
+ var x = Contrast.parse(String(ink)), q = Contrast.parse(String(quiet))
39
+ var lx = Contrast.luminance(x[0], x[1], x[2]), lq = Contrast.luminance(q[0], q[1], q[2])
40
+ return direction(c)[0] === 1 ? lx >= lq : lx <= lq
41
+ }
42
+
43
+ function liftInk(ink, c, a, need, quiet) {
44
+ if (inkHolds(ink, c, a, need, quiet)) return String(ink)
45
+ var from = Contrast.parse(String(ink)), to = direction(c), lo = 0, hi = 1
46
+ for (var i = 0; i < LIGHTNESS_SEARCH_STEPS; i++) {
47
+ var mid = (lo + hi) / 2
48
+ if (inkHolds(Contrast.hexOf(Contrast.mix(from, to, mid)), c, a, need, quiet)) hi = mid
49
+ else lo = mid
50
+ }
51
+ for (var t = hi; t <= 1; t += 1 / ROUNDING_REPAIR_STEPS) {
52
+ var hex = Contrast.hexOf(Contrast.mix(from, to, t))
53
+ if (inkHolds(hex, c, a, need, quiet)) return hex
54
+ }
55
+ return Contrast.hexOf(to)
56
+ }
57
+
58
+ function quieter(ink, primary, c) {
59
+ var x = Contrast.parse(String(ink)), fg = Contrast.parse(String(primary))
60
+ var lx = Contrast.luminance(x[0], x[1], x[2]), lf = Contrast.luminance(fg[0], fg[1], fg[2])
61
+ return (direction(c)[0] === 1 ? lx < lf : lx > lf) && Contrast.ratio(String(ink), String(primary)) >= INK_STEP
62
+ }
63
+
64
+ function primaryHolds(primary, c, a, need, muted, metadata) {
65
+ return worst(primary, c, a) >= need && quieter(muted, primary, c) && quieter(metadata, primary, c)
66
+ }
67
+
68
+ // A mode may lift primary ink too, so legible secondary ink never becomes the primary rung.
69
+ function primaryInk(c, a, need, muted, metadata) {
70
+ if (primaryHolds(c.foreground, c, a, need, muted, metadata)) return String(c.foreground)
71
+ var from = Contrast.parse(String(c.foreground)), to = direction(c), lo = 0, hi = 1
72
+ for (var i = 0; i < LIGHTNESS_SEARCH_STEPS; i++) {
73
+ var mid = (lo + hi) / 2
74
+ if (primaryHolds(Contrast.hexOf(Contrast.mix(from, to, mid)), c, a, need, muted, metadata)) hi = mid
75
+ else lo = mid
76
+ }
77
+ for (var t = hi; t <= 1; t += 1 / ROUNDING_REPAIR_STEPS) {
78
+ var hex = Contrast.hexOf(Contrast.mix(from, to, t))
79
+ if (primaryHolds(hex, c, a, need, muted, metadata)) return hex
80
+ }
81
+ return Contrast.hexOf(to)
82
+ }
83
+
84
+ function inks(c, a, need) {
85
+ var muted = liftInk(c.muted, c, a, need), metadata = liftInk(c.metadata, c, a, need)
86
+ var meta = Contrast.parse(metadata), fg = Contrast.parse(String(c.foreground))
87
+ var lm = Contrast.luminance(meta[0], meta[1], meta[2]), lf = Contrast.luminance(fg[0], fg[1], fg[2])
88
+ // Darkening a light palette's foreground put metadata beyond primary, or on it in White; reuse its muted rung.
89
+ if (direction(c)[0] === 1 ? lm >= lf : lm <= lf) metadata = muted
90
+ var primary = primaryInk(c, a, need, muted, metadata)
91
+ return {foreground: primary, muted: muted, metadata: metadata}
92
+ }
93
+
94
+ // One alpha for every main plane in A, raised only if its ink cannot hold the two text rungs.
95
+ function floor(c, need) {
96
+ for (var a = MIN_ALPHA; a < STEPS; a++) {
97
+ var ink = inks(c, a, need)
98
+ if (primaryHolds(ink.foreground, c, a, need, ink.muted, ink.metadata)
99
+ && worst(ink.muted, c, a) >= need && worst(ink.metadata, c, a) >= need) return a
100
+ }
101
+ return STEPS
102
+ }
103
+
104
+ // B keeps the unlifted listing text legible on its own background plane, never thinner than A.
105
+ function listFloor(c, need) {
106
+ var a = STEPS
107
+ while (a > 0 && Math.min(worst(c.muted, c, a - 1, [c.background]), worst(c.metadata, c, a - 1, [c.background])) >= need) a--
108
+ return a
109
+ }