diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5f1c013 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +*.jpg filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.mp4 filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index 381f5fb..dfd7bf9 100755 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ *.deb *.zip .DS_Store -\#* \ No newline at end of file +\#* + +# Non open source packages +kiosk-browser \ No newline at end of file diff --git a/compositor/media/picom-thumbnail.png b/compositor/media/picom-thumbnail.png new file mode 100644 index 0000000..6702988 --- /dev/null +++ b/compositor/media/picom-thumbnail.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e72fb141603d47563e04dfbacbf36ba3bb45e42e0f0d61abc30bf7390d67c890 +size 229 diff --git a/compositor/package/DEBIAN/control b/compositor/package/DEBIAN/control new file mode 100755 index 0000000..a656622 --- /dev/null +++ b/compositor/package/DEBIAN/control @@ -0,0 +1,19 @@ +Package: tooloop-compositor +Version: 1.0.0 +Maintainer: Tooloop Multimedia +Homepage: https://www.tooloop.de +Section: tooloop/addon +Architecture: all +Name: picom Compositor +Depends: picom +Recommends: picom-conf +Thumbnail: picom-thumbnail.png +Description: Installs the picom compositor to eliminate screen tearing. + [picom](https://github.com/yshui/picom) is a compositor for X, and a fork of Compton. + It has many features but we are primarily using it to fight screen tearing. + . + There is a graphical tool to configure picom: + . + ```bash + picom-conf /home/tooloop/.config/picom.conf + ``` diff --git a/compositor/package/DEBIAN/postinst b/compositor/package/DEBIAN/postinst new file mode 100755 index 0000000..cb9f77a --- /dev/null +++ b/compositor/package/DEBIAN/postinst @@ -0,0 +1,6 @@ +#!/bin/bash +set -e + +picom & + +exit 0 \ No newline at end of file diff --git a/compositor/package/DEBIAN/postrm b/compositor/package/DEBIAN/postrm new file mode 100755 index 0000000..941b965 --- /dev/null +++ b/compositor/package/DEBIAN/postrm @@ -0,0 +1,3 @@ +#!/bin/bash + +rm -f /assets/logs/picom.log \ No newline at end of file diff --git a/compositor/package/home/tooloop/.config/picom.conf b/compositor/package/home/tooloop/.config/picom.conf new file mode 100644 index 0000000..82229c1 --- /dev/null +++ b/compositor/package/home/tooloop/.config/picom.conf @@ -0,0 +1,54 @@ +# Example with all options at +# /usr/share/picom-conf/picom.conf.example + + +################################# +# General Settings # +################################# + +# Specify the backend to use: `xrender`, `glx`, or `xr_glx_hybrid`. +# `xrender` is the default one. +# +backend = "glx"; +# backend = "xrender"; + +# Enable/disable VSync. +# vsync = false +vsync = true; + +# GLX backend: Avoid using stencil buffer, useful if you don't have a stencil buffer. +# Might cause incorrect opacity when rendering transparent content (but never +# practically happened) and may not work with blur-background. +# My tests show a 15% performance boost. Recommended. +# +glx-no-stencil = true; + +# GLX backend: Avoid rebinding pixmap on window damage. +# Probably could improve performance on rapid window content changes, +# but is known to break things on some drivers (LLVMpipe, xf86-video-intel, etc.). +# Recommended if it works. +# +glx-no-rebind-pixmap = false; + +# Use X Sync fence to sync clients' draw calls, to make sure all draw +# calls are finished before picom starts drawing. Needed on nvidia-drivers +# with GLX backend for some users. +# +# xrender-sync-fence = false; + +# Set the log level. Possible values are: +# "trace", "debug", "info", "warn", "error" +# in increasing level of importance. Case doesn't matter. +# If using the "TRACE" log level, it's better to log into a file +# using *--log-file*, since it can generate a huge stream of logs. +# +# log-level = "debug" +log-level = "warn"; + +# Set the log file. +# If *--log-file* is never specified, logs will be written to stderr. +# Otherwise, logs will to written to the given file, though some of the early +# logs might still be written to the stderr. +# When setting this option from the config file, it is recommended to use an absolute path. +# +log-file = "/assets/logs/picom.log"; \ No newline at end of file diff --git a/deploy.sh b/deploy.sh index 92e842b..b6be3c7 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,4 +1,7 @@ #!/bin/bash +echo "-------------------------------------------------------------------------" +echo "Copying packages to local repository" +echo "" # move them to the repository for archive in *; do @@ -13,9 +16,4 @@ done # update local package repository /opt/tooloop/scripts/tooloop-update-packages -sudo systemctl restart tooloop-control.service - -# list available packages -#apt list tooloop* - -tree /assets/packages/ +sudo systemctl restart tooloop-control.service \ No newline at end of file diff --git a/glmark2/media/glmark2-buffer.jpg b/glmark2/media/glmark2-buffer.jpg deleted file mode 100644 index 36bde14..0000000 Binary files a/glmark2/media/glmark2-buffer.jpg and /dev/null differ diff --git a/glmark2/media/glmark2-jellyfish.jpg b/glmark2/media/glmark2-jellyfish.jpg deleted file mode 100644 index 973a4d4..0000000 Binary files a/glmark2/media/glmark2-jellyfish.jpg and /dev/null differ diff --git a/glmark2/media/glmark2-refract.jpg b/glmark2/media/glmark2-refract.jpg deleted file mode 100644 index 1a517fa..0000000 Binary files a/glmark2/media/glmark2-refract.jpg and /dev/null differ diff --git a/glmark2/media/glmark2-shadow.jpg b/glmark2/media/glmark2-shadow.jpg deleted file mode 100644 index 50d88dc..0000000 Binary files a/glmark2/media/glmark2-shadow.jpg and /dev/null differ diff --git a/glmark2/media/glmark2-thumbnail.jpg b/glmark2/media/glmark2-thumbnail.jpg deleted file mode 100644 index ac2b2f7..0000000 Binary files a/glmark2/media/glmark2-thumbnail.jpg and /dev/null differ diff --git a/gpu-benchmark/media/glmark2-buffer.jpg b/gpu-benchmark/media/glmark2-buffer.jpg new file mode 100644 index 0000000..b8d2b83 --- /dev/null +++ b/gpu-benchmark/media/glmark2-buffer.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:970193b3d54262603b07ab6e8f4d55f0bc777a6c614375138ac236bb78166399 +size 349512 diff --git a/gpu-benchmark/media/glmark2-jellyfish.jpg b/gpu-benchmark/media/glmark2-jellyfish.jpg new file mode 100644 index 0000000..e2a818b --- /dev/null +++ b/gpu-benchmark/media/glmark2-jellyfish.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ecb143fc67a9b17006f77e5494155920b06f5623db08ec150a208fb21c00cb6c +size 164399 diff --git a/gpu-benchmark/media/glmark2-refract.jpg b/gpu-benchmark/media/glmark2-refract.jpg new file mode 100644 index 0000000..d068c40 --- /dev/null +++ b/gpu-benchmark/media/glmark2-refract.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:573e3ae0015f10c60e716d0aea2e22b0633ffc8f0519e0ea48c378ed21aabf54 +size 155151 diff --git a/gpu-benchmark/media/glmark2-shadow.jpg b/gpu-benchmark/media/glmark2-shadow.jpg new file mode 100644 index 0000000..dd72ad2 --- /dev/null +++ b/gpu-benchmark/media/glmark2-shadow.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbee082a0e60d1cf9d9efd9ccad3a16fff529fea16b6faa88c338df9b3b8273f +size 63246 diff --git a/gpu-benchmark/media/glmark2-thumbnail.jpg b/gpu-benchmark/media/glmark2-thumbnail.jpg new file mode 100644 index 0000000..5663f73 --- /dev/null +++ b/gpu-benchmark/media/glmark2-thumbnail.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05218a1f5ea5a0a3f104baddaec28eded1bb1f7118ec5e6aa243150e614f9b0c +size 29798 diff --git a/glmark2/package/DEBIAN/control b/gpu-benchmark/package/DEBIAN/control similarity index 94% rename from glmark2/package/DEBIAN/control rename to gpu-benchmark/package/DEBIAN/control index 31129e4..db8fbe3 100644 --- a/glmark2/package/DEBIAN/control +++ b/gpu-benchmark/package/DEBIAN/control @@ -1,12 +1,12 @@ -Package: tooloop-glmark2 +Package: tooloop-gpu-benchmark Version: 1.0.0 Maintainer: Tooloop Multimedia Homepage: https://www.tooloop.de Bugs: https://github.com/glmark2/glmark2 Section: tooloop/presentation Depends: glmark2 -Architecture: amd64 -Name: glmark2 +Architecture: all +Name: GPU Benchmark Thumbnail: glmark2-thumbnail.jpg Media: glmark2-jellyfish.jpg, glmark2-buffer.jpg, glmark2-refract.jpg, glmark2-shadow.jpg Description: OpenGL 2.0 and ES 2.0 benchmark diff --git a/glmark2/package/DEBIAN/postinst b/gpu-benchmark/package/DEBIAN/postinst similarity index 100% rename from glmark2/package/DEBIAN/postinst rename to gpu-benchmark/package/DEBIAN/postinst diff --git a/glmark2/package/assets/presentation/start-presentation.sh b/gpu-benchmark/package/assets/presentation/start-presentation.sh similarity index 100% rename from glmark2/package/assets/presentation/start-presentation.sh rename to gpu-benchmark/package/assets/presentation/start-presentation.sh diff --git a/glmark2/package/assets/presentation/stop-presentation.sh b/gpu-benchmark/package/assets/presentation/stop-presentation.sh similarity index 100% rename from glmark2/package/assets/presentation/stop-presentation.sh rename to gpu-benchmark/package/assets/presentation/stop-presentation.sh diff --git a/image-slideshow/media/image-slideshow-thumbnail.jpg b/image-slideshow/media/image-slideshow-thumbnail.jpg deleted file mode 100644 index 8f9452f..0000000 Binary files a/image-slideshow/media/image-slideshow-thumbnail.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image1.jpg b/image-slideshow/package/assets/data/image1.jpg deleted file mode 100644 index 22f8710..0000000 Binary files a/image-slideshow/package/assets/data/image1.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image10.jpg b/image-slideshow/package/assets/data/image10.jpg deleted file mode 100644 index 87eb84c..0000000 Binary files a/image-slideshow/package/assets/data/image10.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image11.jpg b/image-slideshow/package/assets/data/image11.jpg deleted file mode 100644 index 91c5dba..0000000 Binary files a/image-slideshow/package/assets/data/image11.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image12.jpg b/image-slideshow/package/assets/data/image12.jpg deleted file mode 100644 index 1801c5c..0000000 Binary files a/image-slideshow/package/assets/data/image12.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image2.jpg b/image-slideshow/package/assets/data/image2.jpg deleted file mode 100644 index f4495db..0000000 Binary files a/image-slideshow/package/assets/data/image2.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image3.jpg b/image-slideshow/package/assets/data/image3.jpg deleted file mode 100644 index c32211d..0000000 Binary files a/image-slideshow/package/assets/data/image3.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image4.jpg b/image-slideshow/package/assets/data/image4.jpg deleted file mode 100644 index 773ea44..0000000 Binary files a/image-slideshow/package/assets/data/image4.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image5.jpg b/image-slideshow/package/assets/data/image5.jpg deleted file mode 100644 index 536bee6..0000000 Binary files a/image-slideshow/package/assets/data/image5.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image6.jpg b/image-slideshow/package/assets/data/image6.jpg deleted file mode 100644 index c1e9425..0000000 Binary files a/image-slideshow/package/assets/data/image6.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image7.jpg b/image-slideshow/package/assets/data/image7.jpg deleted file mode 100644 index b932e4c..0000000 Binary files a/image-slideshow/package/assets/data/image7.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image8.jpg b/image-slideshow/package/assets/data/image8.jpg deleted file mode 100644 index 45cfb61..0000000 Binary files a/image-slideshow/package/assets/data/image8.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/data/image9.jpg b/image-slideshow/package/assets/data/image9.jpg deleted file mode 100644 index a00d20f..0000000 Binary files a/image-slideshow/package/assets/data/image9.jpg and /dev/null differ diff --git a/image-slideshow/package/assets/presentation/slideshow.html b/image-slideshow/package/assets/presentation/slideshow.html deleted file mode 100755 index ccdcd91..0000000 --- a/image-slideshow/package/assets/presentation/slideshow.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - Slideshow - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
- - - - - - \ No newline at end of file diff --git a/image-slideshow/package/assets/presentation/start-presentation.sh b/image-slideshow/package/assets/presentation/start-presentation.sh deleted file mode 100644 index f3edaef..0000000 --- a/image-slideshow/package/assets/presentation/start-presentation.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -COMMAND="chromium-browser --noerrdialogs --kiosk --incognito /media/assets/presentation/slideshow.html" - -if [ $EUID == 0 ]; then - su tooloop -c "$COMMAND" & -else - $COMMAND & -fi - -exit 0 diff --git a/image-slideshow/package/assets/presentation/stop-presentation.sh b/image-slideshow/package/assets/presentation/stop-presentation.sh deleted file mode 100644 index d1f4f73..0000000 --- a/image-slideshow/package/assets/presentation/stop-presentation.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -killall chrome - -exit 0 diff --git a/intel-media-va-driver/media/intel-media-va-driver.png b/intel-media-va-driver/media/intel-media-va-driver.png new file mode 100644 index 0000000..06260ad --- /dev/null +++ b/intel-media-va-driver/media/intel-media-va-driver.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:58445d365410ab42a0e9d8768e2c795f169ad26fdb2508e741543f550c7056ce +size 8893 diff --git a/intel-media-va-driver/package/DEBIAN/control b/intel-media-va-driver/package/DEBIAN/control new file mode 100644 index 0000000..fabdebd --- /dev/null +++ b/intel-media-va-driver/package/DEBIAN/control @@ -0,0 +1,20 @@ +Package: tooloop-intel-media-va-driver-non-free +Version: 1.0.0 +Maintainer: Tooloop Multimedia +Homepage: https://www.tooloop.de +Bugs: https://www.github.com/Tooloop/Tooloop-Packages +Section: tooloop/addon +Architecture: amd64 +Depends: intel-media-va-driver-non-free +Name: Intel Hardware Video Acceleration +Thumbnail: intel-media-va-driver.png +Description: Installs the Intel Media Driver for VAAPI + The [Intel Media Driver for VAAPI](https://github.com/intel/media-driver) is a + new VA-API (Video Acceleration API) user mode driver supporting hardware + accelerated decoding, encoding, and video post processing for GEN based + graphics hardware. + . + Installing this will reduce CPU load when decoding e. g. h.264 video if + supported by the playback software. As result your video will run smoother and + your device produces less heat. + \ No newline at end of file diff --git a/kiosk-browser/media/kiosk-browser-thumbnail.jpg b/kiosk-browser/media/kiosk-browser-thumbnail.jpg deleted file mode 100644 index 6480c2a..0000000 Binary files a/kiosk-browser/media/kiosk-browser-thumbnail.jpg and /dev/null differ diff --git a/media-player/media/video-player-thumbnail.jpg b/media-player/media/video-player-thumbnail.jpg new file mode 100644 index 0000000..c06b23a --- /dev/null +++ b/media-player/media/video-player-thumbnail.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:32f7d9a9d2547f8a49fde3edc6ec6cda3f9cf7310136d9615f97c2e588ee93d6 +size 20376 diff --git a/media-player/package/DEBIAN/control b/media-player/package/DEBIAN/control new file mode 100644 index 0000000..5802bc4 --- /dev/null +++ b/media-player/package/DEBIAN/control @@ -0,0 +1,13 @@ +Package: tooloop-media-player +Version: 1.0.0 +Maintainer: Tooloop Multimedia +Homepage: https://www.tooloop.de +Bugs: https://github.com/Tooloop/Tooloop-Packages +Section: tooloop/presentation +Architecture: all +Depends: mpv +Name: Media Player +Description: A simple image and video player + The tooloop media player is using [mpv](https://mpv.io/) to loop over all images and videos in `/assets/data`. +Thumbnail: video-player-thumbnail.jpg + diff --git a/media-player/package/assets/data/Tooloop Greeter Intro.mp4 b/media-player/package/assets/data/Tooloop Greeter Intro.mp4 new file mode 100644 index 0000000..076b836 --- /dev/null +++ b/media-player/package/assets/data/Tooloop Greeter Intro.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:17b2639ace8a11e1233884ac20064e4a723266740a23c7ce2fe92f172f5d9f39 +size 5885065 diff --git a/media-player/package/assets/data/Tooloop Greeter Loop.mp4 b/media-player/package/assets/data/Tooloop Greeter Loop.mp4 new file mode 100644 index 0000000..288ca63 --- /dev/null +++ b/media-player/package/assets/data/Tooloop Greeter Loop.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48d9d99246c401473d954ce2ead407b3c7bbbe3fb61aa916957d5651f21f28af +size 2309614 diff --git a/media-player/package/assets/presentation/LICENSE.md b/media-player/package/assets/presentation/LICENSE.md new file mode 100644 index 0000000..e7a43f9 --- /dev/null +++ b/media-player/package/assets/presentation/LICENSE.md @@ -0,0 +1,76 @@ +# mpv + +mpv is a fork of mplayer2, which is a fork of MPlayer. + +mpv as a whole is licensed under the GNU General Public License GPL version 2 +or later (called GPLv2+ in this document, see LICENSE.GPL for full license +text) by default, or the GNU Lesser General Public License LGPL version 2 or +later (LGPLv2.1+ in this document, see LICENSE.LGPL for full license text) if +built with the --enable-lgpl configure switch. + +Most source files are LGPLv2.1+ or GPLv2+, but some files are available under +more liberal licenses, such as BSD, MIT, ISC, and possibly others. Look at the +copyright header of each source file, and grep the sources for "Copyright" if +you need to know details. C source files without Copyright notice are usually +licensed as LGPLv2.1+. Also see the list of files with specific licenses below +(not all files can have a standard license header). + +All new contributions must be LGPLv2.1+ licensed. Using a more liberal license +compatible to LGPLv2.1+ is also ok. + +Changes done to GPL code must come with the implicit/explicit agreement that the +project can relicense the changes to LGPLv2.1+ at a later point without asking +the contributor. This is a safeguard for making potential relicensing of +remaining GPL code to LGPLv2.1+ easier. + +See DOCS/contribute.md for binding rules wrt. licensing for contributions. + +For information about authors and contributors, consult the git log, which +contains the complete SVN and CVS history as well. + +"v2.1+" in this context means "version 2.1 or later". + +Some libraries are GPLv2+ or GPLv3+ only. Building mpv with Samba support makes +it GPLv3+. + +mpv can be built as LGPLv2.1+ with the --enable-lgpl configure option. To add +a LGPL mode to mpv, MPlayer code had to be relicensed from GPLv2+ to LGPLv2.1+ +by asking the MPlayer authors for permission. Since permission could not be +obtained from everyone, LGPL mode disables the following features, some of +them quite central: +- Linux X11 video output +- BSD audio output via OSS +- NVIDIA/Linux hardware decoding (vdpau, although nvdec usually works) +- Linux TV input +- minor features: jack, DVD, CDDA, SMB, CACA, legacy direct3d VO +Some of these will be fixed in the future. The intended use for LGPL mode is +with libmpv, and currently it's not recommended to build mpv CLI in LGPL mode +at all. + +The following files are still GPL only (--enable-lgpl disables them): + + audio/out/ao_jack.c will stay GPL + audio/out/ao_oss.c will stay GPL + stream/dvb* must stay GPL + stream/stream_cdda.c unknown + stream/stream_dvb.* must stay GPL + stream/stream_dvdnav.c unknown + video/out/vo_caca.c unknown + video/out/vo_direct3d.c unknown + video/out/vo_vaapi.c probably impossible (some company's code) + video/out/vo_vdpau.c probably impossible (nVidia's code) + video/out/vo_x11.c probably impossible + video/out/vo_xv.c probably impossible + video/out/x11_common.* probably impossible + video/vdpau.c hard (GPL-only parts must be ifdefed) + video/vdpau.h unknown + video/vdpau_mixer.* actual code must be rewritten + DOCS/man/ GPLv2+ + bootstrap.py unknown license, probably GPLv2+ or LGPLv2+ + etc/mplayer-input.conf unknown license, probably GPLv2+ + mpv.desktop unknown license, probably GPLv2+ + etc/restore-old-bindings.conf unknown license, probably GPLv2+ + +None of the cases listed above affect the final binary if it's built as +LGPL. Linked libraries still can affect the final license (for example if +FFmpeg was built as GPL). diff --git a/media-player/package/assets/presentation/README.md b/media-player/package/assets/presentation/README.md new file mode 100644 index 0000000..3dcdc77 --- /dev/null +++ b/media-player/package/assets/presentation/README.md @@ -0,0 +1,7 @@ +# A simple image and video player + +The tooloop media player is using [mpv](https://mpv.io/) to loop over all images and videos in `/assets/data`. + +## Customizing + +Check out the start script if you want to fiddle with some mpv options. [Here's the reference manual](https://mpv.io/manual/). diff --git a/media-player/package/assets/presentation/start-presentation.sh b/media-player/package/assets/presentation/start-presentation.sh new file mode 100644 index 0000000..a57b9ff --- /dev/null +++ b/media-player/package/assets/presentation/start-presentation.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +mpv \ +--fullscreen \ +--image-display-duration=5 \ +--loop-playlist \ +--no-osc \ +--no-osd-bar \ +--video-sync=display-resample \ +/assets/data & + +exit 0 diff --git a/video-player/package/assets/presentation/stop-presentation.sh b/media-player/package/assets/presentation/stop-presentation.sh similarity index 88% rename from video-player/package/assets/presentation/stop-presentation.sh rename to media-player/package/assets/presentation/stop-presentation.sh index 0e122f2..6306f27 100644 --- a/video-player/package/assets/presentation/stop-presentation.sh +++ b/media-player/package/assets/presentation/stop-presentation.sh @@ -3,6 +3,6 @@ # here comes everything, you need to stop the running presentation # basically kill or stop everything you started in `start-presentation.sh` -kill $(pidof mplayer) +killall mpv exit 0 diff --git a/nginx/media/nginx-thumbnail.png b/nginx/media/nginx-thumbnail.png new file mode 100755 index 0000000..c0fea2e --- /dev/null +++ b/nginx/media/nginx-thumbnail.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:447dd65b8cbbe638b586ca85ffdedfecc8c7173e6277301553ad323853ad60b1 +size 85099 diff --git a/tooloop-nginx/package/DEBIAN/control b/nginx/package/DEBIAN/control similarity index 96% rename from tooloop-nginx/package/DEBIAN/control rename to nginx/package/DEBIAN/control index 1957f6c..2eb611e 100755 --- a/tooloop-nginx/package/DEBIAN/control +++ b/nginx/package/DEBIAN/control @@ -3,7 +3,7 @@ Version: 1.0.0 Maintainer: Tooloop Multimedia Homepage: https://www.tooloop.de Section: tooloop/addon -Architecture: amd64 +Architecture: all Name: nginx Webserver Depends: nginx, php-fpm, php-mbstring, php-curl, php-xml, php-gd Recommends: tooloop-transparent-cursor diff --git a/tooloop-nginx/package/DEBIAN/postinst b/nginx/package/DEBIAN/postinst similarity index 100% rename from tooloop-nginx/package/DEBIAN/postinst rename to nginx/package/DEBIAN/postinst diff --git a/tooloop-nginx/package/DEBIAN/postrm b/nginx/package/DEBIAN/postrm similarity index 100% rename from tooloop-nginx/package/DEBIAN/postrm rename to nginx/package/DEBIAN/postrm diff --git a/tooloop-nginx/package/assets/data/index.default.php b/nginx/package/assets/data/index.default.php similarity index 100% rename from tooloop-nginx/package/assets/data/index.default.php rename to nginx/package/assets/data/index.default.php diff --git a/tooloop-nginx/package/etc/nginx/sites-available/tooloop b/nginx/package/etc/nginx/sites-available/tooloop similarity index 94% rename from tooloop-nginx/package/etc/nginx/sites-available/tooloop rename to nginx/package/etc/nginx/sites-available/tooloop index 1474ff9..d87ff28 100755 --- a/tooloop-nginx/package/etc/nginx/sites-available/tooloop +++ b/nginx/package/etc/nginx/sites-available/tooloop @@ -21,7 +21,7 @@ server { location ~* \.php$ { try_files $uri =404; - fastcgi_pass unix:/var/run/php/php8.1-fpm-tooloop.sock; + fastcgi_pass unix:/var/run/php/php8.3-fpm-tooloop.sock; include fastcgi.conf; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param PATH_INFO $fastcgi_path_info; diff --git a/tooloop-nginx/package/etc/php/8.1/fpm/pool.d/tooloop.conf b/nginx/package/etc/php/8.3/fpm/pool.d/tooloop.conf similarity index 99% rename from tooloop-nginx/package/etc/php/8.1/fpm/pool.d/tooloop.conf rename to nginx/package/etc/php/8.3/fpm/pool.d/tooloop.conf index 8535c26..de9be87 100755 --- a/tooloop-nginx/package/etc/php/8.1/fpm/pool.d/tooloop.conf +++ b/nginx/package/etc/php/8.3/fpm/pool.d/tooloop.conf @@ -33,7 +33,7 @@ group = tooloop ; (IPv6 and IPv4-mapped) on a specific port; ; '/path/to/unix/socket' - to listen on a unix socket. ; Note: This value is mandatory. -listen = /var/run/php/php8.1-fpm-tooloop.sock +listen = /var/run/php/php8.3-fpm-tooloop.sock ; Set listen(2) backlog. ; Default Value: 511 (-1 on FreeBSD and OpenBSD) @@ -238,7 +238,7 @@ pm.max_spare_servers = 3 ; last request memory: 0 ; ; Note: There is a real-time FPM status monitoring sample web page available -; It's available in: /usr/share/php/8.1/fpm/status.html +; It's available in: /usr/share/php/8.3/fpm/status.html ; ; Note: The value must start with a leading slash (/). The value can be ; anything, but it may not be a good idea to use the .php extension or it diff --git a/onboarding/media/onboarding-thumbnail.png b/onboarding/media/onboarding-thumbnail.png new file mode 100644 index 0000000..5149592 --- /dev/null +++ b/onboarding/media/onboarding-thumbnail.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:32da4e11c4c47de4f1947e41de413a41b6b87e621e4ac58421f386cccf6be6cf +size 11562 diff --git a/onboarding/package/DEBIAN/control b/onboarding/package/DEBIAN/control new file mode 100644 index 0000000..7734a68 --- /dev/null +++ b/onboarding/package/DEBIAN/control @@ -0,0 +1,13 @@ +Package: tooloop-onboarding +Version: 1.0.0 +Maintainer: Tooloop Multimedia +Homepage: https://www.tooloop.de +Bugs: https://github.com/Tooloop/Tooloop-Packages +Section: tooloop/presentation +Architecture: all +Depends: chromium-browser +Name: Onboarding +Description: Tipps and first steps + Learn how to find your way in Tooloop OS. +Thumbnail: onboarding-thumbnail.png + diff --git a/onboarding/package/assets/data/css/styles.css b/onboarding/package/assets/data/css/styles.css new file mode 100644 index 0000000..73e52dc --- /dev/null +++ b/onboarding/package/assets/data/css/styles.css @@ -0,0 +1,214 @@ +:root { + --font-size: 18px; + --light-grey: #f2f2f2; + --medium-grey: #999999; + --dark-grey: #333333; + --pink: #E6004C; + --width: 800px; + --height: 600px; + --scale: 1.0; + --slide-duration: 10s; +} + +@font-face { + font-family: "Clear Sans"; + src: url("../fonts/ClearSans-Regular.ttf"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: "Clear Sans"; + src: url("../fonts/ClearSans-Italic.ttf"); + font-weight: normal; + font-style: italic; +} + +@font-face { + font-family: "Clear Sans"; + src: url("../fonts/ClearSans-Bold.ttf"); + font-weight: bold; + font-style: normal; +} + +@font-face { + font-family: "Clear Sans"; + src: url("../fonts/ClearSans-BoldItalic.ttf"); + font-weight: bold; + font-style: italic; +} + +html { + background-color: var(--dark-grey); +} + +body { + width: var(--width); + height: var(--height); + transform: scale(var(--scale)); + transform-origin: 0 0; + + background-color: black; + + margin: 0; + padding: 0; + font-size: var(--font-size); + position: absolute; + inset: 0; + + font-family: "Clear Sans", system-ui, sans-serif; +} + +nav { + position: absolute; + inset: 0; + pointer-events: none; +} + +button { + pointer-events: all; + position: absolute; + padding: 0; + width: 2rem; + height: 2rem; + border: none; + background: none; + display: flex; + align-items: center; + justify-content: center; +} + +button:hover { + background: var(--light-grey); +} + +button:active { + background: var(--medium-grey); +} + +button.close-button { + top: 1rem; + right: 1rem; +} +button.close-button:hover { + background-color: rgba(255,255,255, 0.1); +} + +button.close-button svg { + stroke: white; +} + +button.slide-button { + bottom: calc((var(--height) / 4 - 2rem) / 2); +} + +button.slide-button svg { + stroke: var(--pink); +} + +button.slide-button.previous { + left: 1rem; +} + +button.slide-button.next { + right: 1rem; +} + +#slider { + display: flex; + flex-direction: row; + overflow-x: auto; + overflow-y: none; + scroll-snap-type: x mandatory; + scroll-behavior: smooth; + + -ms-overflow-style: none; + scrollbar-width: none; +} + +#slider::-webkit-scrollbar { + display: none; +} + +.slide { + scroll-snap-align: center; + display: flex; + flex-direction: column; + flex-shrink: 0; + width: var(--width); + height: var(--height); +} + +.slide .image { + background-color: var(--light-grey); + height: calc(var(--height) * 3 / 4); +} +.slide.no-text .image { + height: var(--height); +} + +.slide .image img, +.slide .image video { + display: block; + width: 100%; + height: 100%; + object-fit: cover; +} + +.slide.no-text .description { + display: none; +} +.slide .description { + position: relative; + padding: 0.5rem 8rem 1rem; + height: calc(var(--height) / 4); + background-color: white; + overflow: auto; + display: flex; + flex-direction: column; + justify-content: center; +} + +.slide .description h1, +.slide .description p { + margin: 0 0 0.5rem 0; +} +.slide .description p:last-child { + margin-bottom: 0; +} + +.slide .description h1 { + font-size: 1.5rem; +} + + +.slide .description h1:first-child { + margin-top: 0; +} + +.slide .description code { + background-color: #ddd; + padding: 0.1rem 0.3rem; + color: var(--dark-grey); + font-size: 0.888rem; + border-radius: 2px; +} + +.progressBar { + position: fixed; + height: .333rem; + width: 0%; + background-color: #ccc; + mix-blend-mode: multiply; + /* opacity: 0.5; */ + bottom: 0px; + + transition: width; + transition-duration: 0s; + transition-timing-function: linear; +} + +.progressBar.playing { + width: 100%; + transition-duration: var(--slide-duration); +} \ No newline at end of file diff --git a/onboarding/package/assets/data/fonts/ClearSans-Bold.ttf b/onboarding/package/assets/data/fonts/ClearSans-Bold.ttf new file mode 100755 index 0000000..dd2d051 --- /dev/null +++ b/onboarding/package/assets/data/fonts/ClearSans-Bold.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e95b1274e575a12d4f9ed0293c359f92a2a1b73bda862b2432ecc567b330bfeb +size 269792 diff --git a/onboarding/package/assets/data/fonts/ClearSans-BoldItalic.ttf b/onboarding/package/assets/data/fonts/ClearSans-BoldItalic.ttf new file mode 100755 index 0000000..b4b6536 --- /dev/null +++ b/onboarding/package/assets/data/fonts/ClearSans-BoldItalic.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89531e842c8b61efad634b6210a725a38fa3f2ac1a736d48a14af89b47361a70 +size 287460 diff --git a/onboarding/package/assets/data/fonts/ClearSans-Italic.ttf b/onboarding/package/assets/data/fonts/ClearSans-Italic.ttf new file mode 100755 index 0000000..e2ab881 --- /dev/null +++ b/onboarding/package/assets/data/fonts/ClearSans-Italic.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac2f34c28ea1f755f0660033f50f615c0a30b0f80763b73363cc142113136c43 +size 282800 diff --git a/onboarding/package/assets/data/fonts/ClearSans-Regular.ttf b/onboarding/package/assets/data/fonts/ClearSans-Regular.ttf new file mode 100755 index 0000000..bc61bbd --- /dev/null +++ b/onboarding/package/assets/data/fonts/ClearSans-Regular.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb811af889b6a3984944678f04b033a4805c49a66f06cde62ef29902e8f0f06f +size 304516 diff --git a/onboarding/package/assets/data/index.html b/onboarding/package/assets/data/index.html new file mode 100644 index 0000000..6eb8b8f --- /dev/null +++ b/onboarding/package/assets/data/index.html @@ -0,0 +1,61 @@ + + + + + + + Welcome to Tooloop OS + + + + + +
+ + + + + + + + + + + + + + \ No newline at end of file diff --git a/onboarding/package/assets/data/js/Slider.js b/onboarding/package/assets/data/js/Slider.js new file mode 100644 index 0000000..f4756aa --- /dev/null +++ b/onboarding/package/assets/data/js/Slider.js @@ -0,0 +1,155 @@ +class Slider { + + imageTypes = ["png", "gif", "webp", "jpg"]; + videoTypes = ["mp4", "webm"]; + + data; + element; + progressBar; + template; + slides = []; + activeSlide = 0; + slideDuration; + slideTimeout; + + constructor(element, template, data, slideDuration = 10000) { + this.element = document.querySelector(element); + this.template = document.querySelector(template); + this.data = data; + this.slideDuration = slideDuration; + this.ip = location.host; + + // append slides + for (let i = 0; i < this.data.length; i++) { + let slide = this.template.content.cloneNode(true); + let type = this.getType(i); + + switch (type) { + // image + case "image": + let img = document.createElement("img"); + img.src = "./slides/" + this.data[i].image; + slide.querySelector(".image").appendChild(img); + break; + + case "video": + let video = document.createElement("video"); + video.autoplay = true; + video.loop = true; + video.muted = true; + video.src = "./slides/" + this.data[i].image; + slide.querySelector(".image").appendChild(video); + break; + + default: + break; + } + + // texts + let hasText = this.data[i].title || this.data[i].description; + if (hasText) { + // let title = slide.querySelector(".description h1"); + // title.textContent = this.data[i].title; + let description = slide.querySelector(".description"); + description.innerHTML = marked.parse(this.data[i].description); + + let title = document.createElement("h1"); + title.textContent = this.data[i].title; + description.prepend(title); + } + + // slide + this.element.appendChild(slide); + + let slideNode = document.querySelector(element + " .slide:last-child"); + slideNode.id = "slide-" + i; + slideNode.classList.toggle("no-text", !hasText); + this.slides.push(slideNode); + } + + // append progress bar + let progressBar = document.createElement("div"); + progressBar.classList.add("progressBar"); + this.progressBar = this.element.appendChild(progressBar); + document.querySelector(":root").style.setProperty("--slide-duration", this.slideDuration / 1000 + "s"); + + + // observe scroll position + this.element.onscroll = e => this.onScroll(e); + + // keyboard shortcuts + document.addEventListener("keydown", (e) => { + if (e.code === "ArrowLeft" || e.code === "ArrowRight") + e.preventDefault(); + }); + document.addEventListener("keyup", (e) => { + if (e.code === "ArrowLeft") this.previous(); + if (e.code === "ArrowRight") this.next(); + }); + + // start auto play + this.startTimeout(); + } + + onScroll(e) { + let newSlide = Math.round(e.target.scrollLeft / 800); + if (this.activeSlide != newSlide) { + this.handleVideoPlayback(this.activeSlide, newSlide); + this.activeSlide = newSlide; + this.startTimeout(); + } + } + + next() { + // scroll to next slide + let targetSlide = this.activeSlide >= (this.data.length - 1) ? 0 : this.activeSlide + 1; + this.element.scrollTo(targetSlide * 800, 0); + + this.handleVideoPlayback(this.activeSlide, targetSlide); + + } + + handleVideoPlayback(oldSlideIndex, newSlideIndex) { + + // stop old video + if (this.getType(oldSlideIndex) == "video") { + this.slides[oldSlideIndex].querySelector("video").pause(); + } + + // start new video and timeout + if (this.getType(newSlideIndex) == "video") { + let video = this.slides[newSlideIndex].querySelector("video"); + video.currentTime = 0 + video.play(); + } + + } + + previous() { + let targetSlide = this.activeSlide <= 0 ? (this.data.length - 1) : this.activeSlide - 1 + this.element.scrollTo(targetSlide * 800, 0); + + this.handleVideoPlayback(this.activeSlide, targetSlide); + } + + startTimeout(timeout = this.slideDuration) { + clearTimeout(this.slideTimeout); + this.slideTimeout = setTimeout(() => { this.next(); }, timeout); + + // restart progress animation + // https://css-tricks.com/restart-css-animation/ + this.progressBar.classList.remove("playing"); + void this.progressBar.offsetWidth; + this.progressBar.classList.add("playing"); + } + + getType(slideIndex) { + let type = this.data[slideIndex].image.split('.').pop().toLowerCase(); + + if (this.imageTypes.includes(type)) return "image"; + if (this.videoTypes.includes(type)) return "video"; + + return false; + } + +} \ No newline at end of file diff --git a/onboarding/package/assets/data/js/marked.min.js b/onboarding/package/assets/data/js/marked.min.js new file mode 100644 index 0000000..be3f096 --- /dev/null +++ b/onboarding/package/assets/data/js/marked.min.js @@ -0,0 +1,6 @@ +/** + * marked v12.0.0 - a markdown parser + * Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed) + * https://github.com/markedjs/marked + */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).marked={})}(this,(function(e){"use strict";function t(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}function n(t){e.defaults=t}e.defaults={async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null};const s=/[&<>"']/,r=new RegExp(s.source,"g"),i=/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,l=new RegExp(i.source,"g"),o={"&":"&","<":"<",">":">",'"':""","'":"'"},a=e=>o[e];function c(e,t){if(t){if(s.test(e))return e.replace(r,a)}else if(i.test(e))return e.replace(l,a);return e}const h=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi;function p(e){return e.replace(h,((e,t)=>"colon"===(t=t.toLowerCase())?":":"#"===t.charAt(0)?"x"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""))}const u=/(^|[^\[])\^/g;function k(e,t){let n="string"==typeof e?e:e.source;t=t||"";const s={replace:(e,t)=>{let r="string"==typeof t?t:t.source;return r=r.replace(u,"$1"),n=n.replace(e,r),s},getRegex:()=>new RegExp(n,t)};return s}function g(e){try{e=encodeURI(e).replace(/%25/g,"%")}catch(e){return null}return e}const f={exec:()=>null};function d(e,t){const n=e.replace(/\|/g,((e,t,n)=>{let s=!1,r=t;for(;--r>=0&&"\\"===n[r];)s=!s;return s?"|":" |"})).split(/ \|/);let s=0;if(n[0].trim()||n.shift(),n.length>0&&!n[n.length-1].trim()&&n.pop(),t)if(n.length>t)n.splice(t);else for(;n.length0)return{type:"space",raw:t[0]}}code(e){const t=this.rules.block.code.exec(e);if(t){const e=t[0].replace(/^ {1,4}/gm,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?e:x(e,"\n")}}}fences(e){const t=this.rules.block.fences.exec(e);if(t){const e=t[0],n=function(e,t){const n=e.match(/^(\s+)(?:```)/);if(null===n)return t;const s=n[1];return t.split("\n").map((e=>{const t=e.match(/^\s+/);if(null===t)return e;const[n]=t;return n.length>=s.length?e.slice(s.length):e})).join("\n")}(e,t[3]||"");return{type:"code",raw:e,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:n}}}heading(e){const t=this.rules.block.heading.exec(e);if(t){let e=t[2].trim();if(/#$/.test(e)){const t=x(e,"#");this.options.pedantic?e=t.trim():t&&!/ $/.test(t)||(e=t.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:e,tokens:this.lexer.inline(e)}}}hr(e){const t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:t[0]}}blockquote(e){const t=this.rules.block.blockquote.exec(e);if(t){const e=x(t[0].replace(/^ *>[ \t]?/gm,""),"\n"),n=this.lexer.state.top;this.lexer.state.top=!0;const s=this.lexer.blockTokens(e);return this.lexer.state.top=n,{type:"blockquote",raw:t[0],tokens:s,text:e}}}list(e){let t=this.rules.block.list.exec(e);if(t){let n=t[1].trim();const s=n.length>1,r={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");const i=new RegExp(`^( {0,3}${n})((?:[\t ][^\\n]*)?(?:\\n|$))`);let l="",o="",a=!1;for(;e;){let n=!1;if(!(t=i.exec(e)))break;if(this.rules.block.hr.test(e))break;l=t[0],e=e.substring(l.length);let s=t[2].split("\n",1)[0].replace(/^\t+/,(e=>" ".repeat(3*e.length))),c=e.split("\n",1)[0],h=0;this.options.pedantic?(h=2,o=s.trimStart()):(h=t[2].search(/[^ ]/),h=h>4?1:h,o=s.slice(h),h+=t[1].length);let p=!1;if(!s&&/^ *$/.test(c)&&(l+=c+"\n",e=e.substring(c.length+1),n=!0),!n){const t=new RegExp(`^ {0,${Math.min(3,h-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`),n=new RegExp(`^ {0,${Math.min(3,h-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),r=new RegExp(`^ {0,${Math.min(3,h-1)}}(?:\`\`\`|~~~)`),i=new RegExp(`^ {0,${Math.min(3,h-1)}}#`);for(;e;){const a=e.split("\n",1)[0];if(c=a,this.options.pedantic&&(c=c.replace(/^ {1,4}(?=( {4})*[^ ])/g," ")),r.test(c))break;if(i.test(c))break;if(t.test(c))break;if(n.test(e))break;if(c.search(/[^ ]/)>=h||!c.trim())o+="\n"+c.slice(h);else{if(p)break;if(s.search(/[^ ]/)>=4)break;if(r.test(s))break;if(i.test(s))break;if(n.test(s))break;o+="\n"+c}p||c.trim()||(p=!0),l+=a+"\n",e=e.substring(a.length+1),s=c.slice(h)}}r.loose||(a?r.loose=!0:/\n *\n *$/.test(l)&&(a=!0));let u,k=null;this.options.gfm&&(k=/^\[[ xX]\] /.exec(o),k&&(u="[ ] "!==k[0],o=o.replace(/^\[[ xX]\] +/,""))),r.items.push({type:"list_item",raw:l,task:!!k,checked:u,loose:!1,text:o,tokens:[]}),r.raw+=l}r.items[r.items.length-1].raw=l.trimEnd(),r.items[r.items.length-1].text=o.trimEnd(),r.raw=r.raw.trimEnd();for(let e=0;e"space"===e.type)),n=t.length>0&&t.some((e=>/\n.*\n/.test(e.raw)));r.loose=n}if(r.loose)for(let e=0;e$/,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",s=t[3]?t[3].substring(1,t[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):t[3];return{type:"def",tag:e,raw:t[0],href:n,title:s}}}table(e){const t=this.rules.block.table.exec(e);if(!t)return;if(!/[:|]/.test(t[2]))return;const n=d(t[1]),s=t[2].replace(/^\||\| *$/g,"").split("|"),r=t[3]&&t[3].trim()?t[3].replace(/\n[ \t]*$/,"").split("\n"):[],i={type:"table",raw:t[0],header:[],align:[],rows:[]};if(n.length===s.length){for(const e of s)/^ *-+: *$/.test(e)?i.align.push("right"):/^ *:-+: *$/.test(e)?i.align.push("center"):/^ *:-+ *$/.test(e)?i.align.push("left"):i.align.push(null);for(const e of n)i.header.push({text:e,tokens:this.lexer.inline(e)});for(const e of r)i.rows.push(d(e,i.header.length).map((e=>({text:e,tokens:this.lexer.inline(e)}))));return i}}lheading(e){const t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:"="===t[2].charAt(0)?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){const t=this.rules.block.paragraph.exec(e);if(t){const e="\n"===t[1].charAt(t[1].length-1)?t[1].slice(0,-1):t[1];return{type:"paragraph",raw:t[0],text:e,tokens:this.lexer.inline(e)}}}text(e){const t=this.rules.block.text.exec(e);if(t)return{type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){const t=this.rules.inline.escape.exec(e);if(t)return{type:"escape",raw:t[0],text:c(t[1])}}tag(e){const t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&/^/i.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){const t=this.rules.inline.link.exec(e);if(t){const e=t[2].trim();if(!this.options.pedantic&&/^$/.test(e))return;const t=x(e.slice(0,-1),"\\");if((e.length-t.length)%2==0)return}else{const e=function(e,t){if(-1===e.indexOf(t[1]))return-1;let n=0;for(let s=0;s-1){const n=(0===t[0].indexOf("!")?5:4)+t[1].length+e;t[2]=t[2].substring(0,e),t[0]=t[0].substring(0,n).trim(),t[3]=""}}let n=t[2],s="";if(this.options.pedantic){const e=/^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(n);e&&(n=e[1],s=e[3])}else s=t[3]?t[3].slice(1,-1):"";return n=n.trim(),/^$/.test(e)?n.slice(1):n.slice(1,-1)),b(t,{href:n?n.replace(this.rules.inline.anyPunctuation,"$1"):n,title:s?s.replace(this.rules.inline.anyPunctuation,"$1"):s},t[0],this.lexer)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){const e=t[(n[2]||n[1]).replace(/\s+/g," ").toLowerCase()];if(!e){const e=n[0].charAt(0);return{type:"text",raw:e,text:e}}return b(n,e,n[0],this.lexer)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s)return;if(s[3]&&n.match(/[\p{L}\p{N}]/u))return;if(!(s[1]||s[2]||"")||!n||this.rules.inline.punctuation.exec(n)){const n=[...s[0]].length-1;let r,i,l=n,o=0;const a="*"===s[0][0]?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(a.lastIndex=0,t=t.slice(-1*e.length+n);null!=(s=a.exec(t));){if(r=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!r)continue;if(i=[...r].length,s[3]||s[4]){l+=i;continue}if((s[5]||s[6])&&n%3&&!((n+i)%3)){o+=i;continue}if(l-=i,l>0)continue;i=Math.min(i,i+l+o);const t=[...s[0]][0].length,a=e.slice(0,n+s.index+t+i);if(Math.min(n,i)%2){const e=a.slice(1,-1);return{type:"em",raw:a,text:e,tokens:this.lexer.inlineTokens(e)}}const c=a.slice(2,-2);return{type:"strong",raw:a,text:c,tokens:this.lexer.inlineTokens(c)}}}}codespan(e){const t=this.rules.inline.code.exec(e);if(t){let e=t[2].replace(/\n/g," ");const n=/[^ ]/.test(e),s=/^ /.test(e)&&/ $/.test(e);return n&&s&&(e=e.substring(1,e.length-1)),e=c(e,!0),{type:"codespan",raw:t[0],text:e}}}br(e){const t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){const t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){const t=this.rules.inline.autolink.exec(e);if(t){let e,n;return"@"===t[2]?(e=c(t[1]),n="mailto:"+e):(e=c(t[1]),n=e),{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let e,n;if("@"===t[2])e=c(t[0]),n="mailto:"+e;else{let s;do{s=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??""}while(s!==t[0]);e=c(t[0]),n="www."===t[1]?"http://"+t[0]:t[0]}return{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}inlineText(e){const t=this.rules.inline.text.exec(e);if(t){let e;return e=this.lexer.state.inRawBlock?t[0]:c(t[0]),{type:"text",raw:t[0],text:e}}}}const m=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,y=/(?:[*+-]|\d{1,9}[.)])/,$=k(/^(?!bull )((?:.|\n(?!\s*?\n|bull ))+?)\n {0,3}(=+|-+) *(?:\n+|$)/).replace(/bull/g,y).getRegex(),z=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,T=/(?!\s*\])(?:\\.|[^\[\]\\])+/,R=k(/^ {0,3}\[(label)\]: *(?:\n *)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/).replace("label",T).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),_=k(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,y).getRegex(),A="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",S=/|$))/,I=k("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))","i").replace("comment",S).replace("tag",A).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),E=k(z).replace("hr",m).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex(),Z={blockquote:k(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",E).getRegex(),code:/^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,def:R,fences:/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,hr:m,html:I,lheading:$,list:_,newline:/^(?: *(?:\n|$))+/,paragraph:E,table:f,text:/^[^\n]+/},q=k("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",m).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex(),L={...Z,table:q,paragraph:k(z).replace("hr",m).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",q).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex()},P={...Z,html:k("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",S).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:f,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:k(z).replace("hr",m).replace("heading"," *#{1,6} *[^\n]").replace("lheading",$).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Q=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,v=/^( {2,}|\\)\n(?!\s*$)/,B="\\p{P}\\p{S}",M=k(/^((?![*_])[\spunctuation])/,"u").replace(/punctuation/g,B).getRegex(),O=k(/^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/,"u").replace(/punct/g,B).getRegex(),C=k("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)[punct](\\*+)(?=[\\s]|$)|[^punct\\s](\\*+)(?!\\*)(?=[punct\\s]|$)|(?!\\*)[punct\\s](\\*+)(?=[^punct\\s])|[\\s](\\*+)(?!\\*)(?=[punct])|(?!\\*)[punct](\\*+)(?!\\*)(?=[punct])|[^punct\\s](\\*+)(?=[^punct\\s])","gu").replace(/punct/g,B).getRegex(),D=k("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\\s]|$)|[^punct\\s](_+)(?!_)(?=[punct\\s]|$)|(?!_)[punct\\s](_+)(?=[^punct\\s])|[\\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])","gu").replace(/punct/g,B).getRegex(),j=k(/\\([punct])/,"gu").replace(/punct/g,B).getRegex(),H=k(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),U=k(S).replace("(?:--\x3e|$)","--\x3e").getRegex(),X=k("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",U).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),F=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,N=k(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label",F).replace("href",/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),G=k(/^!?\[(label)\]\[(ref)\]/).replace("label",F).replace("ref",T).getRegex(),J=k(/^!?\[(ref)\](?:\[\])?/).replace("ref",T).getRegex(),K={_backpedal:f,anyPunctuation:j,autolink:H,blockSkip:/\[[^[\]]*?\]\([^\(\)]*?\)|`[^`]*?`|<[^<>]*?>/g,br:v,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,del:f,emStrongLDelim:O,emStrongRDelimAst:C,emStrongRDelimUnd:D,escape:Q,link:N,nolink:J,punctuation:M,reflink:G,reflinkSearch:k("reflink|nolink(?!\\()","g").replace("reflink",G).replace("nolink",J).getRegex(),tag:X,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\t+" ".repeat(n.length)));e;)if(!(this.options.extensions&&this.options.extensions.block&&this.options.extensions.block.some((s=>!!(n=s.call({lexer:this},e,t))&&(e=e.substring(n.raw.length),t.push(n),!0)))))if(n=this.tokenizer.space(e))e=e.substring(n.raw.length),1===n.raw.length&&t.length>0?t[t.length-1].raw+="\n":t.push(n);else if(n=this.tokenizer.code(e))e=e.substring(n.raw.length),s=t[t.length-1],!s||"paragraph"!==s.type&&"text"!==s.type?t.push(n):(s.raw+="\n"+n.raw,s.text+="\n"+n.text,this.inlineQueue[this.inlineQueue.length-1].src=s.text);else if(n=this.tokenizer.fences(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.heading(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.hr(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.blockquote(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.list(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.html(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.def(e))e=e.substring(n.raw.length),s=t[t.length-1],!s||"paragraph"!==s.type&&"text"!==s.type?this.tokens.links[n.tag]||(this.tokens.links[n.tag]={href:n.href,title:n.title}):(s.raw+="\n"+n.raw,s.text+="\n"+n.raw,this.inlineQueue[this.inlineQueue.length-1].src=s.text);else if(n=this.tokenizer.table(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.lheading(e))e=e.substring(n.raw.length),t.push(n);else{if(r=e,this.options.extensions&&this.options.extensions.startBlock){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startBlock.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(r=e.substring(0,t+1))}if(this.state.top&&(n=this.tokenizer.paragraph(r)))s=t[t.length-1],i&&"paragraph"===s.type?(s.raw+="\n"+n.raw,s.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=s.text):t.push(n),i=r.length!==e.length,e=e.substring(n.raw.length);else if(n=this.tokenizer.text(e))e=e.substring(n.raw.length),s=t[t.length-1],s&&"text"===s.type?(s.raw+="\n"+n.raw,s.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=s.text):t.push(n);else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n,s,r,i,l,o,a=e;if(this.tokens.links){const e=Object.keys(this.tokens.links);if(e.length>0)for(;null!=(i=this.tokenizer.rules.inline.reflinkSearch.exec(a));)e.includes(i[0].slice(i[0].lastIndexOf("[")+1,-1))&&(a=a.slice(0,i.index)+"["+"a".repeat(i[0].length-2)+"]"+a.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;null!=(i=this.tokenizer.rules.inline.blockSkip.exec(a));)a=a.slice(0,i.index)+"["+"a".repeat(i[0].length-2)+"]"+a.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);for(;null!=(i=this.tokenizer.rules.inline.anyPunctuation.exec(a));)a=a.slice(0,i.index)+"++"+a.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);for(;e;)if(l||(o=""),l=!1,!(this.options.extensions&&this.options.extensions.inline&&this.options.extensions.inline.some((s=>!!(n=s.call({lexer:this},e,t))&&(e=e.substring(n.raw.length),t.push(n),!0)))))if(n=this.tokenizer.escape(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.tag(e))e=e.substring(n.raw.length),s=t[t.length-1],s&&"text"===n.type&&"text"===s.type?(s.raw+=n.raw,s.text+=n.text):t.push(n);else if(n=this.tokenizer.link(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.reflink(e,this.tokens.links))e=e.substring(n.raw.length),s=t[t.length-1],s&&"text"===n.type&&"text"===s.type?(s.raw+=n.raw,s.text+=n.text):t.push(n);else if(n=this.tokenizer.emStrong(e,a,o))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.codespan(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.br(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.del(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.autolink(e))e=e.substring(n.raw.length),t.push(n);else if(this.state.inLink||!(n=this.tokenizer.url(e))){if(r=e,this.options.extensions&&this.options.extensions.startInline){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startInline.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(r=e.substring(0,t+1))}if(n=this.tokenizer.inlineText(r))e=e.substring(n.raw.length),"_"!==n.raw.slice(-1)&&(o=n.raw.slice(-1)),l=!0,s=t[t.length-1],s&&"text"===s.type?(s.raw+=n.raw,s.text+=n.text):t.push(n);else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}else e=e.substring(n.raw.length),t.push(n);return t}}class se{options;constructor(t){this.options=t||e.defaults}code(e,t,n){const s=(t||"").match(/^\S*/)?.[0];return e=e.replace(/\n$/,"")+"\n",s?'
'+(n?e:c(e,!0))+"
\n":"
"+(n?e:c(e,!0))+"
\n"}blockquote(e){return`
\n${e}
\n`}html(e,t){return e}heading(e,t,n){return`${e}\n`}hr(){return"
\n"}list(e,t,n){const s=t?"ol":"ul";return"<"+s+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"}listitem(e,t,n){return`
  • ${e}
  • \n`}checkbox(e){return"'}paragraph(e){return`

    ${e}

    \n`}table(e,t){return t&&(t=`${t}`),"\n\n"+e+"\n"+t+"
    \n"}tablerow(e){return`\n${e}\n`}tablecell(e,t){const n=t.header?"th":"td";return(t.align?`<${n} align="${t.align}">`:`<${n}>`)+e+`\n`}strong(e){return`${e}`}em(e){return`${e}`}codespan(e){return`${e}`}br(){return"
    "}del(e){return`${e}`}link(e,t,n){const s=g(e);if(null===s)return n;let r='
    ",r}image(e,t,n){const s=g(e);if(null===s)return n;let r=`${n}0&&"paragraph"===n.tokens[0].type?(n.tokens[0].text=e+" "+n.tokens[0].text,n.tokens[0].tokens&&n.tokens[0].tokens.length>0&&"text"===n.tokens[0].tokens[0].type&&(n.tokens[0].tokens[0].text=e+" "+n.tokens[0].tokens[0].text)):n.tokens.unshift({type:"text",text:e+" "}):o+=e+" "}o+=this.parse(n.tokens,i),l+=this.renderer.listitem(o,r,!!s)}n+=this.renderer.list(l,t,s);continue}case"html":{const e=r;n+=this.renderer.html(e.text,e.block);continue}case"paragraph":{const e=r;n+=this.renderer.paragraph(this.parseInline(e.tokens));continue}case"text":{let i=r,l=i.tokens?this.parseInline(i.tokens):i.text;for(;s+1{const r=e[s].flat(1/0);n=n.concat(this.walkTokens(r,t))})):e.tokens&&(n=n.concat(this.walkTokens(e.tokens,t)))}}return n}use(...e){const t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach((e=>{const n={...e};if(n.async=this.defaults.async||n.async||!1,e.extensions&&(e.extensions.forEach((e=>{if(!e.name)throw new Error("extension name required");if("renderer"in e){const n=t.renderers[e.name];t.renderers[e.name]=n?function(...t){let s=e.renderer.apply(this,t);return!1===s&&(s=n.apply(this,t)),s}:e.renderer}if("tokenizer"in e){if(!e.level||"block"!==e.level&&"inline"!==e.level)throw new Error("extension level must be 'block' or 'inline'");const n=t[e.level];n?n.unshift(e.tokenizer):t[e.level]=[e.tokenizer],e.start&&("block"===e.level?t.startBlock?t.startBlock.push(e.start):t.startBlock=[e.start]:"inline"===e.level&&(t.startInline?t.startInline.push(e.start):t.startInline=[e.start]))}"childTokens"in e&&e.childTokens&&(t.childTokens[e.name]=e.childTokens)})),n.extensions=t),e.renderer){const t=this.defaults.renderer||new se(this.defaults);for(const n in e.renderer){if(!(n in t))throw new Error(`renderer '${n}' does not exist`);if("options"===n)continue;const s=n,r=e.renderer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n||""}}n.renderer=t}if(e.tokenizer){const t=this.defaults.tokenizer||new w(this.defaults);for(const n in e.tokenizer){if(!(n in t))throw new Error(`tokenizer '${n}' does not exist`);if(["options","rules","lexer"].includes(n))continue;const s=n,r=e.tokenizer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.tokenizer=t}if(e.hooks){const t=this.defaults.hooks||new le;for(const n in e.hooks){if(!(n in t))throw new Error(`hook '${n}' does not exist`);if("options"===n)continue;const s=n,r=e.hooks[s],i=t[s];le.passThroughHooks.has(n)?t[s]=e=>{if(this.defaults.async)return Promise.resolve(r.call(t,e)).then((e=>i.call(t,e)));const n=r.call(t,e);return i.call(t,n)}:t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.hooks=t}if(e.walkTokens){const t=this.defaults.walkTokens,s=e.walkTokens;n.walkTokens=function(e){let n=[];return n.push(s.call(this,e)),t&&(n=n.concat(t.call(this,e))),n}}this.defaults={...this.defaults,...n}})),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return ne.lex(e,t??this.defaults)}parser(e,t){return ie.parse(e,t??this.defaults)}#e(e,t){return(n,s)=>{const r={...s},i={...this.defaults,...r};!0===this.defaults.async&&!1===r.async&&(i.silent||console.warn("marked(): The async option was set to true by an extension. The async: false option sent to parse will be ignored."),i.async=!0);const l=this.#t(!!i.silent,!!i.async);if(null==n)return l(new Error("marked(): input parameter is undefined or null"));if("string"!=typeof n)return l(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));if(i.hooks&&(i.hooks.options=i),i.async)return Promise.resolve(i.hooks?i.hooks.preprocess(n):n).then((t=>e(t,i))).then((e=>i.hooks?i.hooks.processAllTokens(e):e)).then((e=>i.walkTokens?Promise.all(this.walkTokens(e,i.walkTokens)).then((()=>e)):e)).then((e=>t(e,i))).then((e=>i.hooks?i.hooks.postprocess(e):e)).catch(l);try{i.hooks&&(n=i.hooks.preprocess(n));let s=e(n,i);i.hooks&&(s=i.hooks.processAllTokens(s)),i.walkTokens&&this.walkTokens(s,i.walkTokens);let r=t(s,i);return i.hooks&&(r=i.hooks.postprocess(r)),r}catch(e){return l(e)}}}#t(e,t){return n=>{if(n.message+="\nPlease report this to https://github.com/markedjs/marked.",e){const e="

    An error occurred:

    "+c(n.message+"",!0)+"
    ";return t?Promise.resolve(e):e}if(t)return Promise.reject(n);throw n}}}const ae=new oe;function ce(e,t){return ae.parse(e,t)}ce.options=ce.setOptions=function(e){return ae.setOptions(e),ce.defaults=ae.defaults,n(ce.defaults),ce},ce.getDefaults=t,ce.defaults=e.defaults,ce.use=function(...e){return ae.use(...e),ce.defaults=ae.defaults,n(ce.defaults),ce},ce.walkTokens=function(e,t){return ae.walkTokens(e,t)},ce.parseInline=ae.parseInline,ce.Parser=ie,ce.parser=ie.parse,ce.Renderer=se,ce.TextRenderer=re,ce.Lexer=ne,ce.lexer=ne.lex,ce.Tokenizer=w,ce.Hooks=le,ce.parse=ce;const he=ce.options,pe=ce.setOptions,ue=ce.use,ke=ce.walkTokens,ge=ce.parseInline,fe=ce,de=ie.parse,xe=ne.lex;e.Hooks=le,e.Lexer=ne,e.Marked=oe,e.Parser=ie,e.Renderer=se,e.TextRenderer=re,e.Tokenizer=w,e.getDefaults=t,e.lexer=xe,e.marked=ce,e.options=he,e.parse=fe,e.parseInline=ge,e.parser=de,e.setOptions=pe,e.use=ue,e.walkTokens=ke})); diff --git a/onboarding/package/assets/data/slides/Automation.mp4 b/onboarding/package/assets/data/slides/Automation.mp4 new file mode 100755 index 0000000..7cd0a5a --- /dev/null +++ b/onboarding/package/assets/data/slides/Automation.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f20ad693aab95eb0a79bef674182b9fe3b53429b74197dd730fc5ea38fa031c +size 2327846 diff --git a/onboarding/package/assets/data/slides/File management.mp4 b/onboarding/package/assets/data/slides/File management.mp4 new file mode 100755 index 0000000..46452c7 --- /dev/null +++ b/onboarding/package/assets/data/slides/File management.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49d5a5a799f37e6224e5f6313e5caacf8a158a12566f3a74f18a84f1937cf401 +size 1207023 diff --git a/onboarding/package/assets/data/slides/Hello world.mp4 b/onboarding/package/assets/data/slides/Hello world.mp4 new file mode 100644 index 0000000..874a9e2 --- /dev/null +++ b/onboarding/package/assets/data/slides/Hello world.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b39c1da6f4c524c49941c8250fd2684f86767f240f49ad5f9e123daa11422be0 +size 5667703 diff --git a/onboarding/package/assets/data/slides/Shortcuts.mp4 b/onboarding/package/assets/data/slides/Shortcuts.mp4 new file mode 100755 index 0000000..4e0480d --- /dev/null +++ b/onboarding/package/assets/data/slides/Shortcuts.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eee006176316f640059b66edb2976953cf4b70cb58f318d8b98fe194b6f410a5 +size 632787 diff --git a/onboarding/package/assets/data/slides/System menu.mp4 b/onboarding/package/assets/data/slides/System menu.mp4 new file mode 100755 index 0000000..72840b2 --- /dev/null +++ b/onboarding/package/assets/data/slides/System menu.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5cd127749dd9bad43253534e9050e82a00fc355228fc8dc36d18eec64209b2d8 +size 2244469 diff --git a/onboarding/package/assets/data/slides/System settings.mp4 b/onboarding/package/assets/data/slides/System settings.mp4 new file mode 100755 index 0000000..9023697 --- /dev/null +++ b/onboarding/package/assets/data/slides/System settings.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:854d1cb1103de9b7fb93837838141e39e2d553ad9fcef221f850ac37df58586b +size 1758129 diff --git a/onboarding/package/assets/data/slides/slides.js b/onboarding/package/assets/data/slides/slides.js new file mode 100644 index 0000000..54d818d --- /dev/null +++ b/onboarding/package/assets/data/slides/slides.js @@ -0,0 +1,35 @@ +var slides = [ + { + image: "Hello world.mp4", + }, + { + image: "System menu.mp4", + title: "The system menu", + description: `Your mouse cursor is hidden. It will only show up if you move it. + Click on the desktop to open the menu.` + }, + { + image: "System settings.mp4", + title: "System settings", + description: `Reach for the settings app to configure and monitor this computer. + It’s browser-based so you can use it remotely.` + }, + { + image: "File management.mp4", + title: "File management", + description: `Tooloop OS is designed to be maintained over network. + Administrate over \`SSH\` and manage files using \`SFTP\` or \`AFP\`. + You can of course also use a USB flash drive.` + }, + { + image: "Automation.mp4", + title: "Automation", + description: `Integrate Tooloop Boxes with your automation system. + Almost everything Tooloop OS can do can also be done via REST.`, + }, + { + image: "Shortcuts.mp4", + title: "Shortcuts for your convenience", + description: `There are some handy keyboard shortcuts and terminal commands starting with _tooloop_, e. g. \`tooloop-presentation-start\`.`, + } +] \ No newline at end of file diff --git a/onboarding/package/assets/presentation/start-presentation.sh b/onboarding/package/assets/presentation/start-presentation.sh new file mode 100644 index 0000000..f98fe43 --- /dev/null +++ b/onboarding/package/assets/presentation/start-presentation.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# List of Chromium Command Line Switches +# https://peter.sh/experiments/chromium-command-line-switches/ + +COMMAND="chromium-browser \ +--disable-features=Translate,Infobars \ +--no-default-browser-check \ +--no-first-run \ +--noerrdialogs \ +--class=TooloopOnboarding \ +--app=file:///media/assets/data/index.html" + +if [ $EUID == 0 ]; then + /bin/bash /assets/presentation/stop-presentation.sh + sleep 0.1 + su tooloop -c "$COMMAND" & +else + /bin/bash /assets/presentation/stop-presentation.sh + sleep 0.1 + $COMMAND & +fi + +exit 0 \ No newline at end of file diff --git a/onboarding/package/assets/presentation/stop-presentation.sh b/onboarding/package/assets/presentation/stop-presentation.sh new file mode 100644 index 0000000..fd31080 --- /dev/null +++ b/onboarding/package/assets/presentation/stop-presentation.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +pids=$(xdotool search --class "TooloopOnboarding") +for pid in $pids; do + xkill -id $pid + break +done + +exit 0 diff --git a/simple-kiosk-browser/media/kiosk-browser-thumbnail.jpg b/simple-kiosk-browser/media/kiosk-browser-thumbnail.jpg new file mode 100644 index 0000000..36522f7 --- /dev/null +++ b/simple-kiosk-browser/media/kiosk-browser-thumbnail.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4656c13ba092b330cf03dc5e8544051307a83681f6dc7755d1fa4e8d33187d68 +size 19664 diff --git a/kiosk-browser/package/DEBIAN/control b/simple-kiosk-browser/package/DEBIAN/control similarity index 73% rename from kiosk-browser/package/DEBIAN/control rename to simple-kiosk-browser/package/DEBIAN/control index eedac95..2adf61a 100644 --- a/kiosk-browser/package/DEBIAN/control +++ b/simple-kiosk-browser/package/DEBIAN/control @@ -1,15 +1,15 @@ -Package: tooloop-kiosk-browser +Package: tooloop-simple-kiosk-browser Version: 1.0.0 Maintainer: Tooloop Multimedia Homepage: https://www.tooloop.de Bugs: https://github.com/Tooloop/Tooloop-Packages Section: tooloop/presentation -Architecture: amd64 +Architecture: all Depends: chromium-browser Recommends: tooloop-transparent-cursor Suggests: tooloop-nginx -Name: Kiosk Browser -Description: Full-screen browser for touch kiosks +Name: Simple Kiosk Browser +Description: Simple fullscreen browser for touch kiosks A simple full-screen kiosk browser based on chromium. You can define its’ homepage in the settings. Thumbnail: kiosk-browser-thumbnail.jpg diff --git a/kiosk-browser/package/assets/data/index.html b/simple-kiosk-browser/package/assets/data/index.html similarity index 93% rename from kiosk-browser/package/assets/data/index.html rename to simple-kiosk-browser/package/assets/data/index.html index fc2a69a..e0485ed 100644 --- a/kiosk-browser/package/assets/data/index.html +++ b/simple-kiosk-browser/package/assets/data/index.html @@ -4,7 +4,7 @@ - Simple Kiosk + Kiosk Browser