buninu-linux 0.14.57 → 0.16.59

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 (299) hide show
  1. package/LICENSES/linux-firmware/LICENCE.nvidia +131 -0
  2. package/LICENSES/linux-firmware/LICENSE.amdgpu +51 -0
  3. package/LICENSES/linux-firmware/LICENSE.amdisp +31 -0
  4. package/LICENSES/linux-firmware/LICENSE.i915 +39 -0
  5. package/LICENSES/linux-firmware/LICENSE.radeon +51 -0
  6. package/LICENSES/linux-firmware/LICENSE.xe +39 -0
  7. package/LICENSES/linux-firmware/WHENCE +10280 -0
  8. package/NOTICE.md +64 -46
  9. package/README.md +378 -87
  10. package/README.zh.md +2041 -0
  11. package/build-image.sh +10 -1
  12. package/build-uki.sh +3 -1
  13. package/fetch-alpine.sh +14 -0
  14. package/graphics.md +31 -0
  15. package/index.js +28 -11
  16. package/initramfs/bin/buninu-browser +4 -1
  17. package/initramfs/bin/buninu-land +1 -1
  18. package/initramfs/bin/bunterm +3 -3
  19. package/initramfs/bin/chroot +13 -0
  20. package/initramfs/bin/chvt +11 -0
  21. package/initramfs/bin/mount +4 -0
  22. package/initramfs/bin/umount +6 -0
  23. package/initramfs/bin/xdg-open +33 -0
  24. package/initramfs/buninu/CHANGELOG.md +66 -0
  25. package/initramfs/buninu/apps/bunmsh/CHANGELOG.md +4 -0
  26. package/initramfs/buninu/apps/bunmsh/package.json +1 -1
  27. package/initramfs/buninu/apps/bunmsh/src/main.js +1 -1
  28. package/initramfs/buninu/apps/jsgotty/LICENSES/MIT-jsmdcui.txt +22 -0
  29. package/initramfs/buninu/apps/jsgotty/NOTICE +5 -0
  30. package/initramfs/buninu/apps/jsgotty/README.en.md +61 -0
  31. package/initramfs/buninu/apps/jsgotty/README.md +61 -0
  32. package/initramfs/buninu/apps/jsgotty/client-modes.mjs +117 -0
  33. package/initramfs/buninu/apps/jsgotty/client.mjs +100 -10
  34. package/initramfs/buninu/apps/jsgotty/clipboard-powershell.js +18 -0
  35. package/initramfs/buninu/apps/jsgotty/clipboard.js +148 -0
  36. package/initramfs/buninu/apps/jsgotty/gotty.js +13 -0
  37. package/initramfs/buninu/apps/jsgotty/package-lock.json +2 -2
  38. package/initramfs/buninu/apps/jsgotty/package.json +1 -1
  39. package/initramfs/buninu/apps/jsgotty/static/css/index.css +14 -1
  40. package/initramfs/buninu/apps/jsgotty/static/index.html +1 -0
  41. package/initramfs/buninu/apps/jsgotty/static/js/gotty.js +187 -23
  42. package/initramfs/buninu/apps/jsgotty/static/js/kitty-keyboard.js +193 -0
  43. package/initramfs/buninu/apps/jsgotty/static/js/kitty.js +115 -7
  44. package/initramfs/buninu/apps/jsgotty/terminal-modes.js +332 -0
  45. package/initramfs/buninu/apps/jsgotty/tests/android-alt.test.js +115 -0
  46. package/initramfs/buninu/apps/jsgotty/tests/arrow-modifiers.test.js +80 -0
  47. package/initramfs/buninu/apps/jsgotty/tests/client-exit.test.mjs +45 -0
  48. package/initramfs/buninu/apps/jsgotty/tests/client-modes.test.mjs +105 -0
  49. package/initramfs/buninu/apps/jsgotty/tests/clipboard-browser.test.js +81 -0
  50. package/initramfs/buninu/apps/jsgotty/tests/clipboard.test.js +75 -0
  51. package/initramfs/buninu/apps/jsgotty/tests/kitty-keyboard-browser.test.js +53 -0
  52. package/initramfs/buninu/apps/jsgotty/tests/kitty-keyboard.test.js +102 -0
  53. package/initramfs/buninu/apps/jsgotty/tests/manual/README.md +20 -0
  54. package/initramfs/buninu/apps/jsgotty/tests/manual/keyboard-collector.cjs +55 -0
  55. package/initramfs/buninu/apps/jsgotty/tests/manual/keyboard-debug.js +74 -0
  56. package/initramfs/buninu/apps/jsgotty/tests/manual/kitty-keyboard.js +80 -0
  57. package/initramfs/buninu/apps/jsgotty/tests/manual/zoom-collector.cjs +55 -0
  58. package/initramfs/buninu/apps/jsgotty/tests/manual/zoom-debug.js +39 -0
  59. package/initramfs/buninu/apps/jsgotty/tests/manual-touch-diagnostics.js +33 -0
  60. package/initramfs/buninu/apps/jsgotty/tests/manual-touch-diagnostics.mjs +22 -0
  61. package/initramfs/buninu/apps/jsgotty/tests/nested-cli-pty.test.mjs +116 -0
  62. package/initramfs/buninu/apps/jsgotty/tests/reconnect-modes-browser.test.js +144 -0
  63. package/initramfs/buninu/apps/jsgotty/tests/reconnect-modes.md +44 -0
  64. package/initramfs/buninu/apps/jsgotty/tests/reconnect-modes.test.js +166 -0
  65. package/initramfs/buninu/apps/jsgotty/tests/touch-drag-browser.test.js +106 -0
  66. package/initramfs/buninu/apps/jsgotty/tests/wheel-browser.test.js +60 -0
  67. package/initramfs/buninu/apps/jsmdcui/CHANGELOG.md +44 -0
  68. package/initramfs/buninu/apps/jsmdcui/package.json +1 -1
  69. package/initramfs/buninu/apps/jsmdcui/src/highlight/go-regexp.js +83 -0
  70. package/initramfs/buninu/apps/jsmdcui/src/highlight/highlighter.js +49 -62
  71. package/initramfs/buninu/apps/jsmdcui/src/highlight/parser.js +8 -5
  72. package/initramfs/buninu/apps/jsmdcui/tests/go-regexp.test.js +98 -0
  73. package/initramfs/buninu/apps/jsmdcui/tests/heading-ids.test.js +21 -16
  74. package/initramfs/buninu/apps/jsmdcui/tests/highlight-regions.test.js +73 -0
  75. package/initramfs/buninu/apps/jsmdcui/tests/id-collision.test.js +32 -9
  76. package/initramfs/buninu/apps/jsmdcui/tests/markdown-behavior.mjs +9 -0
  77. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/NORMAL-HTML.md +46 -0
  78. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/README.md +85 -0
  79. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/REPORT.md +328 -0
  80. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/compare.mjs +75 -0
  81. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/go.mod +5 -0
  82. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/normal-html-report.json +619 -0
  83. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/normal-html.html +9 -0
  84. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/oracle.go +49 -0
  85. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/report.json +2174 -0
  86. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/PowerShell.txt +39 -0
  87. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ada.txt +25 -0
  88. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/apacheconf.txt +49 -0
  89. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/arduino.txt +38 -0
  90. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/asciidoc.txt +33 -0
  91. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/asm.txt +77 -0
  92. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ats.txt +48 -0
  93. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/awk.txt +28 -0
  94. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/b.txt +27 -0
  95. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/bat.txt +39 -0
  96. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/c.txt +34 -0
  97. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/caddyfile.txt +14 -0
  98. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/cake.txt +7 -0
  99. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/clojure.txt +18 -0
  100. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/cmake.txt +20 -0
  101. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/coffeescript.txt +32 -0
  102. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/colortest.txt +19 -0
  103. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/conky.txt +12 -0
  104. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/cpp.txt +46 -0
  105. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/crontab.txt +16 -0
  106. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/crystal.txt +28 -0
  107. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/csharp.txt +28 -0
  108. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/css.txt +19 -0
  109. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/csx.txt +7 -0
  110. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/cuda.txt +37 -0
  111. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/cython.txt +22 -0
  112. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/d.txt +52 -0
  113. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/dart.txt +27 -0
  114. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/default.txt +8 -0
  115. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/dockerfile.txt +10 -0
  116. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/dot.txt +15 -0
  117. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/elixir.txt +23 -0
  118. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/elm.txt +20 -0
  119. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/erb.txt +32 -0
  120. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/erlang.txt +23 -0
  121. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/fish.txt +20 -0
  122. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/forth.txt +17 -0
  123. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/fortran.txt +40 -0
  124. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/freebsd-kernel.txt +10 -0
  125. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/fsharp.txt +27 -0
  126. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gdscript.txt +26 -0
  127. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gemini.txt +11 -0
  128. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gentoo-ebuild.txt +28 -0
  129. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gentoo-etc-portage.txt +14 -0
  130. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/git-commit.txt +19 -0
  131. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/git-config.txt +11 -0
  132. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/git-rebase-todo.txt +10 -0
  133. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gleam.txt +44 -0
  134. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/glsl.txt +18 -0
  135. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gnuplot.txt +11 -0
  136. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/go.txt +33 -0
  137. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/godoc.txt +9 -0
  138. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/golo.txt +50 -0
  139. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/gomod.txt +16 -0
  140. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/graphql.txt +20 -0
  141. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/groff.txt +18 -0
  142. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/groovy.txt +42 -0
  143. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/haml.txt +16 -0
  144. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/hare.txt +31 -0
  145. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/haskell.txt +26 -0
  146. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/hc.txt +28 -0
  147. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/html.txt +26 -0
  148. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/html4.txt +20 -0
  149. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/html5.txt +20 -0
  150. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ini.txt +16 -0
  151. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/inputrc.txt +14 -0
  152. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/java.txt +18 -0
  153. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/javascript.txt +41 -0
  154. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/jinja2.txt +13 -0
  155. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/json.txt +21 -0
  156. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/jsonnet.txt +28 -0
  157. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/julia.txt +24 -0
  158. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/justfile.txt +26 -0
  159. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/keymap.txt +15 -0
  160. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/kickstart.txt +16 -0
  161. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/kotlin.txt +30 -0
  162. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/kvlang.txt +37 -0
  163. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ledger.txt +13 -0
  164. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/lfe.txt +17 -0
  165. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/lilypond.txt +15 -0
  166. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/lisp.txt +17 -0
  167. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/log.txt +45 -0
  168. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/lua.txt +48 -0
  169. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/mail.txt +17 -0
  170. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/makefile.txt +25 -0
  171. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/man.txt +12 -0
  172. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/markdown.txt +21 -0
  173. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/mc.txt +11 -0
  174. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/meson.txt +29 -0
  175. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/micro.txt +25 -0
  176. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/mpdconf.txt +13 -0
  177. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/msbuild.txt +7 -0
  178. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nanorc.txt +16 -0
  179. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nftables.txt +22 -0
  180. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nginx.txt +17 -0
  181. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nim.txt +23 -0
  182. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nix.txt +15 -0
  183. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/nu.txt +92 -0
  184. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/objc.txt +36 -0
  185. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ocaml.txt +25 -0
  186. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/octave.txt +35 -0
  187. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/odin.txt +35 -0
  188. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/pascal.txt +22 -0
  189. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/patch.txt +13 -0
  190. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/peg.txt +16 -0
  191. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/perl.txt +27 -0
  192. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/php.txt +44 -0
  193. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/pkg-config.txt +12 -0
  194. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/po.txt +12 -0
  195. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/pony.txt +29 -0
  196. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/pov.txt +17 -0
  197. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/privoxy-action.txt +14 -0
  198. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/privoxy-config.txt +10 -0
  199. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/privoxy-filter.txt +12 -0
  200. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/proto.txt +22 -0
  201. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/prql.txt +42 -0
  202. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/puppet.txt +22 -0
  203. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/python2.txt +24 -0
  204. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/python3.txt +28 -0
  205. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/r.txt +16 -0
  206. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/raku.txt +19 -0
  207. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/reST.txt +18 -0
  208. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/renpy.txt +11 -0
  209. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/rpmspec.txt +31 -0
  210. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/ruby.txt +34 -0
  211. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/rust.txt +27 -0
  212. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/sage.txt +24 -0
  213. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/scad.txt +23 -0
  214. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/scala.txt +16 -0
  215. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/sed.txt +12 -0
  216. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/sh.txt +20 -0
  217. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/sls.txt +15 -0
  218. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/smalltalk.txt +28 -0
  219. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/solidity.txt +26 -0
  220. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/sql.txt +35 -0
  221. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/stata.txt +32 -0
  222. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/svelte.txt +10 -0
  223. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/swift.txt +53 -0
  224. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/systemd.txt +15 -0
  225. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/tcl.txt +17 -0
  226. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/terraform.txt +28 -0
  227. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/tex.txt +15 -0
  228. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/toml.txt +31 -0
  229. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/twig.txt +29 -0
  230. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/typescript.txt +32 -0
  231. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/v.txt +47 -0
  232. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/vala.txt +22 -0
  233. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/verilog.txt +37 -0
  234. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/vhdl.txt +37 -0
  235. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/vi.txt +17 -0
  236. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/vue.txt +29 -0
  237. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/xml.txt +14 -0
  238. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/xresources.txt +14 -0
  239. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/yaml.txt +19 -0
  240. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/yum.txt +12 -0
  241. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/zig.txt +24 -0
  242. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/zscript.txt +31 -0
  243. package/initramfs/buninu/apps/jsmdcui/tests/syntax-parity/samples/zsh.txt +21 -0
  244. package/initramfs/buninu/package.json +1 -1
  245. package/initramfs/init.js +19 -3
  246. package/initramfs/lib/bunterm/clipboard.js +14 -0
  247. package/initramfs/lib/bunterm/commands.js +37 -0
  248. package/initramfs/lib/bunterm/fps.js +38 -0
  249. package/initramfs/lib/bunterm/images.js +14 -6
  250. package/initramfs/lib/bunterm/input.js +58 -15
  251. package/initramfs/lib/bunterm/keyboard.js +62 -0
  252. package/initramfs/lib/bunterm/keycodes.js +104 -0
  253. package/initramfs/lib/bunterm/kitty-keyboard.cjs +195 -0
  254. package/initramfs/lib/bunterm/raw-protocol.js +111 -0
  255. package/initramfs/lib/bunterm/renderer.js +116 -28
  256. package/initramfs/lib/bunterm/selection.js +60 -0
  257. package/initramfs/lib/bunterm/terminal.js +157 -12
  258. package/initramfs/lib/bunterm/vt-menu.js +181 -0
  259. package/initramfs/lib/bunterm/vt.js +27 -1
  260. package/initramfs/lib/canvas.js +99 -0
  261. package/initramfs/lib/chvt.js +31 -0
  262. package/initramfs/lib/fbdev.js +32 -8
  263. package/initramfs/lib/gpu.js +77 -0
  264. package/initramfs/lib/mapped-frame.js +28 -0
  265. package/initramfs/lib/raw-image.js +71 -0
  266. package/initramfs/lib/xdg-open.js +42 -0
  267. package/initramfs/usr/share/doc/buninu-linux/bunterm.md +85 -11
  268. package/initramfs/usr/share/doc/buninu-linux/chvt.md +34 -0
  269. package/initramfs/usr/share/doc/buninu-linux/xdg-open.md +43 -0
  270. package/package.json +1 -1
  271. package/scripts/arch.js +7 -5
  272. package/scripts/arch.sh +5 -5
  273. package/scripts/build.js +16 -3
  274. package/scripts/fetch-gpu.js +105 -0
  275. package/scripts/fetch.js +11 -1
  276. package/scripts/gpu-firmware.json +22 -0
  277. package/scripts/modules.js +4 -1
  278. package/scripts/npm-packages.md +18 -17
  279. package/test/bunterm-fps.test.js +17 -0
  280. package/test/bunterm-image-bytes.test.js +15 -0
  281. package/test/bunterm-keyboard.test.js +116 -0
  282. package/test/bunterm-mapped-lifetime.test.js +147 -0
  283. package/test/bunterm-next-vt.test.js +9 -0
  284. package/test/bunterm-raw-protocol.test.js +39 -0
  285. package/test/bunterm-renderer.test.js +167 -0
  286. package/test/bunterm-selection.test.js +38 -0
  287. package/test/bunterm-vt-menu.test.js +178 -0
  288. package/test/chroot-bind.test.js +40 -2
  289. package/test/chvt.test.js +46 -0
  290. package/test/fbdev-sync.test.js +42 -0
  291. package/test/fetch-npm.test.js +2 -2
  292. package/test/gpu.test.js +155 -0
  293. package/test/image-size.test.js +17 -0
  294. package/test/manual-bunterm-image-paths.js +31 -0
  295. package/test/mount-libc-lifetime.test.js +50 -0
  296. package/test/no-gpu.test.js +43 -0
  297. package/test/readme-cli.test.js +29 -0
  298. package/test/stage-npm.test.js +11 -4
  299. package/test/xdg-open.test.js +55 -0
@@ -0,0 +1,155 @@
1
+ import { test, expect, afterEach } from "bun:test";
2
+ import * as fs from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { configureGpu, framebufferUsers, isGpuPath } from "../initramfs/lib/gpu.js";
6
+ import { extractFirmware, firmwareLinkTarget } from "../scripts/fetch-gpu.js";
7
+ import { readTar } from "../scripts/fetch.js";
8
+ import { requests, select } from "../scripts/modules.js";
9
+
10
+ const dirs = [];
11
+ const temporary = () => { const p = fs.mkdtempSync(join(tmpdir(), "buninu-gpu-test-")); dirs.push(p); return p; };
12
+ afterEach(() => { for (const dir of dirs.splice(0)) fs.rmSync(dir, { recursive: true, force: true }); });
13
+ const archive = (files, links = {}) => ({ entries: () => Object.entries(files).map(([n,b]) => [n, Buffer.from(b)]), links: () => Object.entries(links) });
14
+ const soft = target => ({ target, hard: false });
15
+
16
+ test("firmware preserves directory aliases, cross-package links and hardlinks", () => {
17
+ const root = temporary();
18
+ const files = extractFirmware([
19
+ archive({ "lib/firmware/nvidia/ad102/gsp.bin.zst": "firmware", "lib/firmware/amdgpu/a.bin.zst": "amd" }),
20
+ archive({}, {
21
+ "lib/firmware/nvidia/ad103": soft("ad102"),
22
+ "lib/firmware/nvidia/alias.bin.zst": soft("ad103/gsp.bin.zst"),
23
+ "lib/firmware/radeon/alias.bin.zst": soft("../amdgpu/a.bin.zst"),
24
+ "lib/firmware/nvidia/hard.bin.zst": { target: "lib/firmware/nvidia/ad102/gsp.bin.zst", hard: true },
25
+ }),
26
+ ], root);
27
+ expect(files).toHaveLength(6);
28
+ expect(fs.readFileSync(join(root, "lib/firmware/nvidia/ad103/gsp.bin.zst"), "utf8")).toBe("firmware");
29
+ expect(fs.readFileSync(join(root, "lib/firmware/nvidia/alias.bin.zst"), "utf8")).toBe("firmware");
30
+ expect(fs.readFileSync(join(root, "lib/firmware/nvidia/hard.bin.zst"), "utf8")).toBe("firmware");
31
+ expect(fs.readFileSync(join(root, "lib/firmware/radeon/alias.bin.zst"), "utf8")).toBe("amd");
32
+ });
33
+
34
+ test("firmware rejects escaping, missing and cyclic links before extraction", () => {
35
+ for (const target of ["/etc/passwd", "../../../etc/passwd", "..\\etc\\passwd"])
36
+ expect(() => firmwareLinkTarget("lib/firmware/nvidia/x", soft(target))).toThrow();
37
+ for (const links of [
38
+ { "lib/firmware/a": soft("missing") },
39
+ { "lib/firmware/a": soft("b"), "lib/firmware/b": soft("a") },
40
+ { "lib/firmware/a": soft("a/child") },
41
+ ]) expect(() => extractFirmware([archive({}, links)], temporary())).toThrow();
42
+ expect(() => extractFirmware([archive({"lib/firmware/../../escape": "bad"})], temporary())).toThrow();
43
+ });
44
+
45
+ test.skipIf(!Bun.which("tar"))("APK tar reader retains GNU long symlinks and hardlinks", () => {
46
+ const root = temporary(), tree = join(root, "tree"); fs.mkdirSync(tree);
47
+ const name = "x".repeat(120);
48
+ fs.writeFileSync(join(tree, name), "firmware");
49
+ fs.linkSync(join(tree, name), join(tree, "hard"));
50
+ fs.symlinkSync(name, join(tree, "alias"));
51
+ const pkg = join(root, "package.tar.gz");
52
+ expect(Bun.spawnSync(["tar", "--format=gnu", "-czf", pkg, "-C", tree, name, "hard", "alias"]).exitCode).toBe(0);
53
+ const tar = readTar(pkg), links = new Map(tar.links());
54
+ expect(tar.get(name).toString()).toBe("firmware");
55
+ expect(links.get("alias")).toEqual({ target: name, hard: false });
56
+ expect(links.get("hard")).toEqual({ target: name, hard: true });
57
+ });
58
+
59
+ const runtime = () => {
60
+ const root = temporary(), calls = [], logs = [];
61
+ fs.mkdirSync(join(root, "proc/1/fd"), { recursive:true });
62
+ fs.writeFileSync(join(root, "proc/1/maps"), "");
63
+ fs.mkdirSync(join(root, "dev/dri"), { recursive:true });
64
+ fs.writeFileSync(join(root, "dev/dri/renderD129"), "node");
65
+ fs.writeFileSync(join(root, "dev/fb0"), "node");
66
+ const io = {...fs,
67
+ statSync: path => path.includes("renderD") ? { isCharacterDevice: () => true } : fs.statSync(path),
68
+ chownSync: (path, uid, gid) => calls.push(["chown", uid, gid]),
69
+ chmodSync: (path, mode) => calls.push(["chmod", mode]),
70
+ };
71
+ const options = { root, io, env: {}, log: s => logs.push(s),
72
+ tryModprobe: name => calls.push(["transport", name]),
73
+ autoload: options => {
74
+ const candidates = [ ["amdgpu", "kernel/drivers/gpu/drm/amd/amdgpu/amdgpu.ko"], ["simpledrm", "kernel/drivers/gpu/drm/sysfb/simpledrm.ko"], ["e1000", "kernel/drivers/net/e1000.ko"] ];
75
+ const modules = candidates.filter(x => options.acceptModule(...x)).map(x => x[0]);
76
+ calls.push(["autoload", modules]);
77
+ return [{ bus:"pci", device:"0000:01:00.0", modules, loaded:modules, error:null }];
78
+ },
79
+ };
80
+ return { root, calls, logs, options };
81
+ };
82
+
83
+ test("cfg.gpu matches only GPU leaf drivers and configures actual render node names", () => {
84
+ const { options, calls } = runtime(); options.env.BUNINU_RENDER_GID = "107";
85
+ const result = configureGpu(options);
86
+ expect(result.errors).toEqual([]);
87
+ expect(result.renderNodes).toEqual([{path:"/dev/dri/renderD129", driver:"unknown", gid:107}]);
88
+ expect(calls).toContainEqual(["autoload", ["amdgpu"]]);
89
+ expect(calls).toContainEqual(["chown", 0, 107]);
90
+ expect(calls).toContainEqual(["chmod", 0o660]);
91
+ });
92
+
93
+ test("virtio render nodes report the GPU child driver rather than the PCI transport", () => {
94
+ const { root, options } = runtime();
95
+ const device = join(root, "sys/class/drm/renderD129/device");
96
+ fs.mkdirSync(join(device, "virtio0"), {recursive:true});
97
+ fs.symlinkSync("/sys/bus/pci/drivers/virtio-pci", join(device, "driver"));
98
+ fs.symlinkSync("/sys/bus/virtio/drivers/virtio_gpu", join(device, "virtio0/driver"));
99
+ expect(configureGpu(options).renderNodes[0].driver).toBe("virtio_gpu");
100
+ });
101
+
102
+ test("no matching GPU and no render node is diagnosed without claiming acceleration", () => {
103
+ const { root, options, logs } = runtime();
104
+ fs.unlinkSync(join(root, "dev/dri/renderD129"));
105
+ options.autoload = () => [];
106
+ const result = configureGpu(options);
107
+ expect(result.errors).toEqual([]);
108
+ expect(result.renderNodes).toEqual([]);
109
+ expect(logs.some(s=>s.includes("no accessible render node"))).toBe(true);
110
+ });
111
+
112
+ test("framebuffer fd or surviving mmap prevents GPU takeover before loading anything", () => {
113
+ for (const mapped of [false, true]) {
114
+ const { root, options, calls } = runtime();
115
+ if (mapped) fs.writeFileSync(join(root, "proc/1/maps"), "abc-def rw-s 00000000 00:01 3 /dev/fb0\n");
116
+ else fs.symlinkSync("/dev/fb0", join(root, "proc/1/fd/4"));
117
+ expect(framebufferUsers(options)).toEqual(["1"]);
118
+ expect(configureGpu(options).blocked).toBe(true);
119
+ expect(calls).toEqual([]);
120
+ }
121
+ });
122
+
123
+ test("missing hardware, driver failure and invalid permissions do not escape cfg.gpu", () => {
124
+ const { options, calls } = runtime();
125
+ options.env.BUNINU_RENDER_GID = "bad";
126
+ expect(configureGpu(options).errors.length).toBe(1); expect(calls).toEqual([]);
127
+ options.env = {};
128
+ options.autoload = () => { throw Error("driver failed"); };
129
+ expect(configureGpu(options).errors).toEqual(["driver failed"]);
130
+ options.autoload = () => []; options.io.chownSync = () => { throw Error("permission denied"); };
131
+ expect(configureGpu(options).errors[0]).toContain("permission denied");
132
+ });
133
+
134
+ test("cfg.all's actual loader excludes GPU modules and still loads network/sound", () => {
135
+ const source = fs.readFileSync(new URL("../initramfs/init.js", import.meta.url), "utf8");
136
+ const body = source.match(/const configureModules = \(\) => \{([\s\S]*?)\n\};/)[1];
137
+ const chosen = [];
138
+ const require = () => ({ isGpuPath, modprobeAll: ({accept}) => {
139
+ for (const path of ["kernel/drivers/gpu/drm/amd/amdgpu/amdgpu.ko", "kernel/drivers/net/e1000.ko", "kernel/sound/snd.ko"])
140
+ if (accept("",path)) chosen.push(path);
141
+ return {inserted:chosen,errors:[]};
142
+ }});
143
+ new Function("require", "console", body)(require, {log(){}});
144
+ expect(chosen).toEqual(["kernel/drivers/net/e1000.ko", "kernel/sound/snd.ko"]);
145
+ expect(source).toContain("gpu: { enumerable: true, get: configureGraphics }");
146
+ });
147
+
148
+ test("GPU leaves are optional for kernels without them and their dependencies are selected", () => {
149
+ const target = {arch:"x86_64",flavor:"lts",real:false};
150
+ const dep = requests(target).filter(x=>!x.optional).map(({name})=>`kernel/${name}.ko.gz:`);
151
+ dep.push("kernel/drivers/gpu/drm/amd/amdgpu/amdgpu.ko.gz: kernel/drivers/gpu/drm/ttm/ttm.ko.gz", "kernel/drivers/gpu/drm/ttm/ttm.ko.gz:");
152
+ const result = select({...target,dep:dep.join("\n"),builtin:"",packageName:"test"});
153
+ expect(result.selected).toContain("kernel/drivers/gpu/drm/ttm/ttm.ko.gz");
154
+ expect(result.notes.some(x=>x.includes("i915"))).toBe(true);
155
+ });
@@ -0,0 +1,17 @@
1
+ import { test, expect } from "bun:test";
2
+ import { imageBytes } from "../scripts/build.js";
3
+ import { layout } from "../initramfs/lib/fat.js";
4
+ const MiB = 1024 * 1024;
5
+ test("image sizing preserves small images and fits GPU firmware payloads plus FAT metadata", () => {
6
+ expect(imageBytes(80 * MiB)).toBe(128 * MiB);
7
+ // Actual no-gpu EFI: the former 16 MiB reserve incorrectly made this 192 MiB.
8
+ expect(imageBytes(113646592)).toBe(128 * MiB);
9
+ expect(imageBytes(266 * MiB)).toBe(320 * MiB);
10
+ for (const payload of [0, 100 * MiB, 120 * MiB, 240 * MiB, 266 * MiB, 512 * MiB, 0xffffffff]) {
11
+ const size = imageBytes(payload);
12
+ const geometry = layout(size / 512 - 34 - 2048 + 1);
13
+ expect((geometry.clusters - 3) * geometry.perCluster * 512).toBeGreaterThan(payload);
14
+ expect(size % (64 * MiB)).toBe(0);
15
+ }
16
+ expect(() => imageBytes(0x100000000)).toThrow("FAT32");
17
+ });
@@ -0,0 +1,31 @@
1
+ import {runGraphics} from '/lib/fbdev.js';
2
+ import {loadCanvasKit,openCanvas} from '/lib/canvas.js';
3
+ import {claimVirtualConsole} from '/lib/bunterm/vt.js';
4
+ // Manual native Linux benchmark; takes over tty6 temporarily.
5
+ // bun test/manual-bunterm-image-paths.js /path/to/1920x1080.png
6
+ if(!process.argv[2])throw Error('Pass a 1920x1080 PNG filename');
7
+ const CK=await loadCanvasKit(), results=[];
8
+ await runGraphics(async(display,{onRelease,onAcquire})=>{
9
+ const screen=openCanvas(CK,display);let active=true;onRelease(()=>active=false);onAcquire(()=>active=true);
10
+ const bytes=await Bun.file(process.argv[2]).bytes();
11
+ const image=CK.MakeImageFromEncoded(bytes),w=image.width(),h=image.height();
12
+ if(w!==1920||h!==1080||display.width!==1920||display.height!==1080||display.bitsPerPixel!==32)throw Error("This comparison requires a 1920x1080 image and 32-bit 1920x1080 framebuffer");
13
+ const src=CK.LTRBRect(0,0,w,h), native=CK.LTRBRect(0,0,w,h),scaled=CK.LTRBRect(0,26,1920,1066);
14
+ const info={width:w,height:h,colorType:CK.ColorType.RGBA_8888,alphaType:CK.AlphaType.Unpremul,colorSpace:CK.ColorSpace.SRGB};
15
+ const start=performance.now(),pixels=image.readPixels(0,0,info);
16
+ if(!pixels)throw Error('readPixels failed');
17
+ if(screen.colorType===CK.ColorType.BGRA_8888)for(let i=0;i<pixels.length;i+=4){const r=pixels[i];pixels[i]=pixels[i+2];pixels[i+2]=r;}results.push({readPixelsMs:performance.now()-start,width:w,height:h,bytes:pixels?.length});
18
+ const actions={
19
+ 'rows-scaled':()=>{for(let y=0;y<1080;y+=26){screen.canvas.save();screen.canvas.clipRect(CK.LTRBRect(0,y,1920,Math.min(1080,y+26)),CK.ClipOp.Intersect,false);screen.canvas.drawImageRectOptions(image,src,scaled,CK.FilterMode.Linear,CK.MipmapMode.Linear,null);screen.canvas.restore();}},
20
+ 'single-scaled':()=>screen.canvas.drawImageRectOptions(image,src,scaled,CK.FilterMode.Linear,CK.MipmapMode.Linear,null),
21
+ 'single-1to1':()=>screen.canvas.drawImageRectOptions(image,src,native,CK.FilterMode.Linear,CK.MipmapMode.Linear,null),
22
+ 'drawImage-1to1':()=>screen.canvas.drawImage(image,0,0),
23
+ 'decode-copy-1to1':()=>{const fresh=CK.MakeImageFromEncoded(bytes);try{const p=fresh.readPixels(0,0,info);if(!p)throw Error('decode failed');if(screen.colorType===CK.ColorType.BGRA_8888)for(let i=0;i<p.length;i+=4){const r=p[i];p[i]=p[i+2];p[i+2]=r;}screen.restoreRegion({x:0,y:0,height:Math.min(h,1080),rowBytes:w*4,pixels:p});}finally{fresh.delete();}},
24
+ 'copy-1to1':()=>screen.restoreRegion({x:0,y:0,height:Math.min(h,1080),rowBytes:w*4,pixels}),
25
+ };
26
+ try {for(const [name,draw] of Object.entries(actions)){
27
+ screen.canvas.clear(CK.BLACK);draw();screen.flush();
28
+ const t=performance.now();let count=0,total=0;while(performance.now()-t<2500){if(!active)throw Error('VT switched');const t0=performance.now();draw();screen.flush();total+=performance.now()-t0;count++;await Bun.sleep(16);}
29
+ results.push({name,ms:total/count,count});await Bun.write('/tmp/bunterm-image-paths.json',JSON.stringify(results,null,2));
30
+ }}finally{image.delete();screen.close();}
31
+ },{console:['/dev/tty6'],prepareConsole:claimVirtualConsole});process.exit(0);
@@ -0,0 +1,50 @@
1
+ import {test,expect} from 'bun:test';
2
+ import {mkdtempSync,writeFileSync,readFileSync,rmSync} from 'node:fs';
3
+ import {tmpdir} from 'node:os';
4
+ import {join} from 'node:path';
5
+
6
+ // Run the real command with a libc whose path disappears after the first
7
+ // successful mount change. Never mount or unmount anything on the host.
8
+ async function invoke(name,args){
9
+ const dir=mkdtempSync(join(tmpdir(),'buninu-mount-libc-'));
10
+ const mock=join(dir,'libc.mjs');
11
+ writeFileSync(mock,`
12
+ let hidden=false;
13
+ const bound=new Map();
14
+ const functions={mount:()=>{if(hidden)return -1;hidden=true;return 0;},
15
+ umount2:()=>{if(hidden)return -1;hidden=true;return 0;},
16
+ errno:()=>5,strerror:()=> 'mock I/O error'};
17
+ export const libc={symbols:new Proxy({}, {get(_target,name){
18
+ if(!bound.has(name)){
19
+ if(hidden)throw Error('Cannot load libc symbol '+name);
20
+ bound.set(name,functions[name]);
21
+ }
22
+ return bound.get(name);
23
+ }})};
24
+ export const ptr=x=>x,cString=x=>x,errno=()=>libc.symbols.errno(),
25
+ strerror=code=>libc.symbols.strerror(code),Errno={},SysError=class extends Error{};
26
+ `);
27
+ const source=readFileSync(new URL('../initramfs/bin/'+name,import.meta.url),'utf8')
28
+ .replace('"../lib/dlopen.js"',JSON.stringify(mock))
29
+ .replace('import { showDocument } from "../lib/document.js";','const showDocument=async()=>{};')
30
+ .replace('import { modprobe, tryModprobe, modulesDirectory, ModuleNotFound } from "../lib/modprobe.js";',
31
+ 'const modprobe=()=>[],tryModprobe=()=>[],modulesDirectory=()=>"";class ModuleNotFound extends Error{}');
32
+ const entry=join(dir,'command.mjs');writeFileSync(entry,source);
33
+ try{
34
+ const child=Bun.spawn([process.execPath,entry,...args],{stdout:'pipe',stderr:'pipe'});
35
+ const stderr=new Response(child.stderr).text();
36
+ return {status:await child.exited,stderr:await stderr};
37
+ }finally{rmSync(dir,{recursive:true,force:true});}
38
+ }
39
+
40
+ test('read-only bind reports remount failure after the libc path is hidden',async()=>{
41
+ const r=await invoke('mount',['--bind','-o','ro','/fake-source','/fake-target']);
42
+ expect(r.status).toBe(32);expect(r.stderr).toContain('mount: mock I/O error');
43
+ expect(r.stderr).not.toContain('Cannot load libc symbol');
44
+ });
45
+
46
+ test('later unmount failure reports strerror after an earlier target hides libc',async()=>{
47
+ const r=await invoke('umount',['/fake-lib','/fake-missing']);
48
+ expect(r.status).toBe(32);expect(r.stderr).toContain('umount: /fake-missing: mock I/O error.');
49
+ expect(r.stderr).not.toContain('Cannot load libc symbol');
50
+ });
@@ -0,0 +1,43 @@
1
+ import {test,expect} from "bun:test";
2
+ import {mkdtempSync,mkdirSync,writeFileSync,existsSync,rmSync} from "node:fs";
3
+ import {tmpdir} from "node:os";
4
+ import {join} from "node:path";
5
+ import {requests,select} from "../scripts/modules.js";
6
+ import {config} from "../scripts/arch.js";
7
+ import {fetchGpuFirmware,gpuReady} from "../scripts/fetch-gpu.js";
8
+ const additions=new Set(["virtio-gpu","vmwgfx","i915","xe","amdgpu","radeon","nouveau"]);
9
+ test("no-gpu only removes new explicit requests across target configurations",()=>{
10
+ for(const arch of ["x86_64","aarch64"])for(const flavor of ["lts","virt"])for(const real of [true,false]){
11
+ const cfg={arch,flavor,real};
12
+ expect(requests({...cfg,noGpu:true})).toEqual(requests(cfg).filter(r=>!additions.has(r.name)));
13
+ }
14
+ expect(config({noGpu:true}).noGpu).toBe(true);
15
+ });
16
+ test("no-gpu retains a GPU-directory dependency when an original module needs it",()=>{
17
+ const cfg={arch:"x86_64",flavor:"lts",real:false,noGpu:true};
18
+ const dep=requests(cfg).map(({name})=>`kernel/test/${name}.ko.gz:${name==="snd-hda-intel"?" kernel/drivers/gpu/drm/shared.ko.gz":""}`).join("\n")+"\nkernel/drivers/gpu/drm/shared.ko.gz:";
19
+ expect(select({...cfg,dep,builtin:"",packageName:"test"}).selected).toContain("kernel/drivers/gpu/drm/shared.ko.gz");
20
+ });
21
+ test("no-gpu clears generated firmware and caches cannot cross GPU modes",async()=>{
22
+ const root=mkdtempSync(join(tmpdir(),"no-gpu-"));
23
+ try{
24
+ const cfg={...config({arch:"x86_64",flavor:"lts",real:true,noGpu:true}),nativeDir:root,modulesRoot:join(root,"modules")};
25
+ mkdirSync(cfg.modulesRoot,{recursive:true});
26
+ writeFileSync(join(cfg.modulesRoot,"modules.dep"),"");
27
+ writeFileSync(join(cfg.modulesRoot,"modules.builtin"),"kernel/drivers/gpu/drm/i915/i915.ko\n");
28
+ mkdirSync(join(root,"lib/firmware"),{recursive:true});
29
+ writeFileSync(join(root,"lib/firmware/stale"),"old firmware");
30
+ await fetchGpuFirmware(cfg);
31
+ expect(existsSync(join(root,"lib/firmware"))).toBe(false);
32
+ expect(gpuReady(cfg)).toBe(true);
33
+ expect(gpuReady({...cfg,noGpu:false})).toBe(false);
34
+ mkdirSync(join(root,"lib/firmware"));
35
+ expect(gpuReady(cfg)).toBe(false);
36
+ }finally{rmSync(root,{recursive:true,force:true});}
37
+ });
38
+ test("launcher documents no-gpu and rejects it without fetch/build",()=>{
39
+ const help=Bun.spawnSync([process.execPath,"index.js","--help"]);
40
+ expect(help.exitCode).toBe(0);expect(help.stdout.toString()).toContain("--no-gpu");
41
+ const invalid=Bun.spawnSync([process.execPath,"index.js","-r","--no-gpu"]);
42
+ expect(invalid.exitCode).not.toBe(0);expect(invalid.stderr.toString()).toContain("only make sense");
43
+ });
@@ -0,0 +1,29 @@
1
+ import { expect, test } from "bun:test";
2
+ import { fileURLToPath } from "node:url";
3
+
4
+ const entry = fileURLToPath(new URL("../index.js", import.meta.url));
5
+
6
+ for (const [flag, filename] of [
7
+ ["--readme", "README.md"],
8
+ ["--readme-zh", "README.zh.md"],
9
+ ["--docs", "README.zh.md"],
10
+ ]) {
11
+ test(`${flag} flushes the complete document to a pipe before exiting`, async () => {
12
+ const markdown = await Bun.file(new URL(`../${filename}`, import.meta.url)).text();
13
+ const rendered = Bun.markdown.ansi(markdown, { hyperlinks: true });
14
+ const expected = rendered.endsWith("\n") ? rendered : `${rendered}\n`;
15
+ // Both real documents exceed the pipe chunk that was previously truncated.
16
+ expect(Buffer.byteLength(expected)).toBeGreaterThan(65536);
17
+ const child = Bun.spawn([process.execPath, entry, flag], {
18
+ stdout: "pipe", stderr: "pipe",
19
+ });
20
+ const [output, errors, status] = await Promise.all([
21
+ new Response(child.stdout).text(),
22
+ new Response(child.stderr).text(),
23
+ child.exited,
24
+ ]);
25
+ expect(status).toBe(0);
26
+ expect(errors).toBe("");
27
+ expect(output).toBe(expected);
28
+ });
29
+ }
@@ -101,9 +101,16 @@ test("distribution launcher ensures resources then forwards to local casty witho
101
101
  `);
102
102
  writeFileSync(join(root, "usr/lib/node_modules/@drxiaozhi/casty/index.js"),
103
103
  "console.log(JSON.stringify({args:process.argv.slice(2),engine:process.env.CASTY_BROWSER}));");
104
- const result = spawnSync(process.execPath, [join(root, "bin/buninu-browser"), "--casty", "https://example.test", "--", "--chromium"], { encoding: "utf8" });
105
- expect(result.status).toBe(0);
106
- expect(JSON.parse(result.stdout)).toEqual({ args: ["https://example.test", "--", "--chromium"], engine: join(browser, "buninu-browser.js") });
104
+ for (const args of [
105
+ ["https://example.test", "--", "--chromium"],
106
+ ["--", "--help"],
107
+ ["--", "--version"],
108
+ ["--", "--window-size=160,90"],
109
+ ]) {
110
+ const result = spawnSync(process.execPath, [join(root, "bin/buninu-browser"), "--casty", ...args], { encoding: "utf8" });
111
+ expect(result.status).toBe(0);
112
+ expect(JSON.parse(result.stdout)).toEqual({ args, engine: join(browser, "buninu-browser.js") });
113
+ }
107
114
  });
108
115
 
109
116
  test("land launcher selects bundled casty and preserves package frontend dispatch", async () => {
@@ -130,7 +137,7 @@ test("land launcher selects bundled casty and preserves package frontend dispatc
130
137
  });
131
138
  expect(result.status).toBe(0);
132
139
  expect(JSON.parse(result.stdout)).toEqual({
133
- args: args[0] === '--casty' ? args.slice(1) : args,
140
+ args: ['--no-shortcuts', ...(args[0] === '--casty' ? args.slice(1) : args)],
134
141
  engine: join(land, "compositor.js"),
135
142
  });
136
143
  }
@@ -0,0 +1,55 @@
1
+ import {afterAll, expect, test} from 'bun:test';
2
+ import {mkdtempSync,writeFileSync,symlinkSync,rmSync,chmodSync} from 'node:fs';
3
+ import {tmpdir} from 'node:os';
4
+ import {join} from 'node:path';
5
+ import {pathToFileURL} from 'node:url';
6
+ import {browserTarget,parseOpenArgs} from '../initramfs/lib/xdg-open.js';
7
+ const dir=mkdtempSync(join(tmpdir(),'buninu-xdg-open-'));
8
+ afterAll(()=>rmSync(dir,{recursive:true,force:true}));
9
+ const file=join(dir,'中文 # %.html');writeFileSync(file,'<p>test</p>');
10
+ symlinkSync(file,join(dir,'alias.html'));
11
+ test('HTTP and HTTPS remain browser URLs',()=>{
12
+ expect(browserTarget('https://buninu.org/path?q=one#two')).toBe('https://buninu.org/path?q=one#two');
13
+ expect(browserTarget('http://localhost:8080')).toBe('http://localhost:8080/');
14
+ expect(()=>browserTarget('http://')).toThrow();
15
+ });
16
+ test('local files resolve symlinks and escape URL-special characters',()=>{
17
+ expect(browserTarget('alias.html',dir)).toBe(pathToFileURL(file).href);
18
+ expect(browserTarget(pathToFileURL(file).href)).toBe(pathToFileURL(file).href);
19
+ expect(()=>browserTarget('missing',dir)).toThrow();
20
+ expect(()=>browserTarget(dir)).toThrow('regular file');
21
+ expect(()=>browserTarget('javascript:alert(1)')).toThrow('Unsupported');
22
+ expect(()=>browserTarget('mailto:test@example.com')).toThrow('Unsupported');
23
+ });
24
+ test('argument validation',()=>{
25
+ expect(parseOpenArgs(['--help'])).toEqual({help:true});
26
+ expect(()=>parseOpenArgs([])).toThrow('Usage');
27
+ expect(()=>parseOpenArgs(['a','b'])).toThrow('Usage');
28
+ });
29
+ test('launcher passes a single URL argument to a new bunterm and maps launch failure to status 4',async()=>{
30
+ const stub=join(dir,'bunterm');writeFileSync(stub,`#!${process.execPath}\nconsole.log(JSON.stringify(process.argv.slice(2)));process.exit(7);`);chmodSync(stub,0o755);
31
+ const browser=join(dir,'buninu-browser');writeFileSync(browser,'#!/bin/sh\nexit 0');chmodSync(browser,0o755);
32
+ const url='https://example.test/?q=$(touch%20bad)&x=1';
33
+ const p=Bun.spawn([process.execPath,new URL('../initramfs/bin/xdg-open',import.meta.url).pathname,url],{env:{...process.env,PATH:dir+':'+process.env.PATH},stdout:'pipe',stderr:'pipe'});
34
+ expect(await p.exited).toBe(4);
35
+ expect(JSON.parse(await new Response(p.stdout).text())).toEqual(['-e','buninu-browser',url]);
36
+ expect(await new Response(p.stderr).text()).toBe('');
37
+ });
38
+
39
+ test('about URLs pass through; Markdown remains a browser file URL',()=>{
40
+ for(const url of ['about:blank','about:audio','about:custom?x=1#part'])
41
+ expect(browserTarget(url)).toBe(url);
42
+ const markdown=join(dir,'note.md');writeFileSync(markdown,'# Note');
43
+ expect(browserTarget(markdown)).toBe(pathToFileURL(markdown).href);
44
+ });
45
+
46
+ test('manual aliases, version and standard failure codes work through the command',async()=>{
47
+ const run=async args=>{const p=Bun.spawn([process.execPath,new URL('../initramfs/bin/xdg-open',import.meta.url).pathname,...args],{env:{...process.env,PATH:'/nonexistent'},stdout:'pipe',stderr:'pipe'});return {code:await p.exited,out:await new Response(p.stdout).text()}};
48
+ for(const flag of ['-h','--help','--manual']){const r=await run([flag]);expect(r.code).toBe(0);expect(r.out).toContain('Exit codes');}
49
+ const v=await run(['--version']);expect(v.code).toBe(0);expect(v.out).toContain('xdg-open (Buninu Linux)');
50
+ expect((await run([])).code).toBe(1);
51
+ expect((await run(['http://'])).code).toBe(1);
52
+ expect((await run([join(dir,'absent')])).code).toBe(2);
53
+ expect((await run(['https://buninu.org'])).code).toBe(3);
54
+ expect((await run(['mailto:a@example.com'])).code).toBe(4);
55
+ });