From 8f4ffabb8ed0585079d9e0c67dc676791eb3eb71 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 6 Aug 2026 10:07:59 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=A4=20Sync=202026-08-06=2010:07:59?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- linkease-common-bin/Makefile | 21 ++--- linkease/Makefile | 19 +++-- linkeasefull/Makefile | 5 +- linkeaselite/Makefile | 75 ------------------ linkeaselite/files/linkeaselite-config.sh | 78 ------------------- linkeaselite/files/linkeaselite.config | 4 - linkeaselite/files/linkeaselite.init | 68 ---------------- linkeaselite/files/linkeaselite.uci-default | 60 -------------- luci-theme-footstrap/Makefile | 2 +- .../htdocs/luci-static/resources/fs-sheets.js | 10 +-- .../etc/uci-defaults/30_luci-theme-footstrap | 7 +- .../themes/footstrap/partials/head.ut | 32 +++++--- 12 files changed, 57 insertions(+), 324 deletions(-) delete mode 100644 linkeaselite/Makefile delete mode 100755 linkeaselite/files/linkeaselite-config.sh delete mode 100644 linkeaselite/files/linkeaselite.config delete mode 100755 linkeaselite/files/linkeaselite.init delete mode 100644 linkeaselite/files/linkeaselite.uci-default diff --git a/linkease-common-bin/Makefile b/linkease-common-bin/Makefile index ed5e2204..d244a3b5 100644 --- a/linkease-common-bin/Makefile +++ b/linkease-common-bin/Makefile @@ -10,25 +10,28 @@ include $(TOPDIR)/rules.mk PKG_ARCH_LINKEASE:=$(ARCH) PKG_NAME:=linkease-common-bin -PKG_SOURCE_DATE:=1.7.5 -PKG_RELEASE:=1 +PKG_VERSION:=linkease-runtime-v1.7.5 +PKG_SOURCE_DATE:=$(PKG_VERSION) +PKG_RELEASE:=2 ARCH_HEXCODE:= ifeq ($(ARCH),x86_64) ARCH_HEXCODE=8664 +PKG_HASH:=skip else ifeq ($(ARCH),aarch64) ARCH_HEXCODE=aa64 +PKG_HASH:=skip else ifeq ($(ARCH),arm) ARCH_HEXCODE=aa32 +PKG_HASH:=skip else ifeq ($(ARCH),mipsel) ARCH_HEXCODE=1b0c endif -PKG_SOURCE_VERSION:=$(ARCH_HEXCODE) -PKG_SOURCE:=linkease-binary-$(PKG_SOURCE_DATE).tar.gz -PKG_SOURCE_URL:=https://dl.istoreos.com/binary/LinkEase/LinuxStorage/ -PKG_HASH:=skip -PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-binary-$(PKG_SOURCE_DATE) +PKG_SOURCE_VERSION:=f6d705f77dade7d57c1bb24334da4028279689b9 +PKG_SOURCE:=linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz +PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/ +PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE) PKG_BUILD_PARALLEL:=1 PKG_USE_MIPS16:=0 @@ -57,8 +60,8 @@ endef define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/heif-converter.$(PKG_ARCH_LINKEASE) $(1)/usr/sbin/heif-converter - $(INSTALL_BIN) $(PKG_BUILD_DIR)/linkease-media.$(PKG_ARCH_LINKEASE) $(1)/usr/sbin/linkease-media + $(INSTALL_BIN) $(PKG_BUILD_DIR)/heif-converter $(1)/usr/sbin/heif-converter + $(INSTALL_BIN) $(PKG_BUILD_DIR)/linkease-media $(1)/usr/sbin/linkease-media $(INSTALL_BIN) ./files/linkease-config.sh $(1)/usr/sbin/linkease-config.sh endef diff --git a/linkease/Makefile b/linkease/Makefile index 5edd4f5a..ca359d9d 100644 --- a/linkease/Makefile +++ b/linkease/Makefile @@ -10,25 +10,28 @@ include $(TOPDIR)/rules.mk PKG_ARCH_LINKEASE:=$(ARCH) PKG_NAME:=linkease -PKG_SOURCE_DATE:=1.7.5 -PKG_RELEASE:=4 +PKG_VERSION:=linkease-runtime-v1.7.5 +PKG_SOURCE_DATE:=$(PKG_VERSION) +PKG_RELEASE:=5 ARCH_HEXCODE:= ifeq ($(ARCH),x86_64) ARCH_HEXCODE=8664 +PKG_HASH:=skip else ifeq ($(ARCH),aarch64) ARCH_HEXCODE=aa64 +PKG_HASH:=skip else ifeq ($(ARCH),arm) ARCH_HEXCODE=aa32 +PKG_HASH:=skip else ifeq ($(ARCH),mipsel) ARCH_HEXCODE=1b0c endif -PKG_SOURCE_VERSION:=$(ARCH_HEXCODE) -PKG_SOURCE:=linkease-binary-$(PKG_SOURCE_DATE).tar.gz -PKG_SOURCE_URL:=https://dl.istoreos.com/binary/LinkEase/LinuxStorage/ -PKG_HASH:=skip -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_SOURCE_DATE) +PKG_SOURCE_VERSION:=f6d705f77dade7d57c1bb24334da4028279689b9 +PKG_SOURCE:=linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz +PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/ +PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE) PKG_BUILD_PARALLEL:=1 PKG_USE_MIPS16:=0 @@ -69,7 +72,7 @@ endef define Package/$(PKG_NAME)/install $(INSTALL_DIR) $(1)/usr/sbin/linkease-plugins $(1)/etc/config $(1)/etc/init.d $(1)/etc/uci-defaults - $(INSTALL_BIN) $(PKG_BUILD_DIR)/linkease.$(PKG_ARCH_LINKEASE) $(1)/usr/sbin/linkease + $(INSTALL_BIN) $(PKG_BUILD_DIR)/linkease $(1)/usr/sbin/linkease $(INSTALL_CONF) ./files/linkease.config $(1)/etc/config/linkease $(INSTALL_BIN) ./files/linkease.init $(1)/etc/init.d/linkease $(INSTALL_BIN) ./files/linkease.uci-default $(1)/etc/uci-defaults/linkease diff --git a/linkeasefull/Makefile b/linkeasefull/Makefile index 1bd12ab1..b5ebc475 100644 --- a/linkeasefull/Makefile +++ b/linkeasefull/Makefile @@ -7,8 +7,9 @@ include $(TOPDIR)/rules.mk PKG_NAME:=linkeasefull -PKG_SOURCE_DATE:=3.0.4 -PKG_RELEASE:=3 +PKG_VERSION:=linkease-runtime-v1.7.5 +PKG_SOURCE_DATE:=$(PKG_VERSION) +PKG_RELEASE:=4 ifeq ($(ARCH),x86_64) LINKEASE_RUNTIME_ARCH:=amd64 diff --git a/linkeaselite/Makefile b/linkeaselite/Makefile deleted file mode 100644 index f9e4457e..00000000 --- a/linkeaselite/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# -# Copyright (C) 2015-2016 OpenWrt.org -# Copyright (C) 2026 LinkEaseLite Contributors -# -# This is free software, licensed under the GNU General Public License v3. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=linkeaselite -PKG_SOURCE_DATE:=3.0.0 -PKG_RELEASE:=3 - -PKG_SOURCE:=linkeaselite-binary-$(PKG_SOURCE_DATE).tar.gz -PKG_SOURCE_URL:=https://github.com/linkease/istore-packages/releases/download/linkeaselite-v$(PKG_SOURCE_DATE)/ -PKG_HASH:=skip -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_SOURCE_DATE) - -PKG_BUILD_PARALLEL:=1 -PKG_USE_MIPS16:=0 -TAR_CMD=$(HOST_TAR) -C $(PKG_BUILD_DIR) $(TAR_OPTIONS) - -include $(INCLUDE_DIR)/package.mk - -define Package/$(PKG_NAME) - SECTION:=net - CATEGORY:=Network - SUBMENU:=Web Servers/Proxies - TITLE:=LinkEaseLite - the file cloud - DEPENDS:=@(arm||x86_64||aarch64) +ca-bundle - URL:=https://www.linkease.com/ -endef - -define Package/$(PKG_NAME)/description - LinkEaseLite is a lightweight LinkEase runtime for small-memory OpenWrt devices. -endef - -define Package/$(PKG_NAME)/conffiles -/etc/config/linkeaselite -endef - -define Package/$(PKG_NAME)/postinst -#!/bin/sh -if [ -z "$${IPKG_INSTROOT}" ]; then - [ -f /etc/uci-defaults/linkeaselite ] && /etc/uci-defaults/linkeaselite && rm -f /etc/uci-defaults/linkeaselite - exit 0 -fi -endef - -define Package/$(PKG_NAME)/postrm -#!/bin/sh -if [ -z "$${IPKG_INSTROOT}" ]; then - uci -q delete firewall.linkeaselite - uci -q commit firewall - /etc/init.d/firewall reload -fi -exit 0 -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/$(PKG_NAME)/install - $(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/config $(1)/etc/init.d $(1)/etc/uci-defaults - $(INSTALL_BIN) $(PKG_BUILD_DIR)/linkease-lite.$(ARCH) $(1)/usr/sbin/linkease-lite - $(INSTALL_BIN) ./files/linkeaselite-config.sh $(1)/usr/sbin/linkeaselite-config.sh - $(INSTALL_CONF) ./files/linkeaselite.config $(1)/etc/config/linkeaselite - $(INSTALL_BIN) ./files/linkeaselite.init $(1)/etc/init.d/linkeaselite - $(INSTALL_BIN) ./files/linkeaselite.uci-default $(1)/etc/uci-defaults/linkeaselite -endef - -$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/linkeaselite/files/linkeaselite-config.sh b/linkeaselite/files/linkeaselite-config.sh deleted file mode 100755 index 7dc6c7ae..00000000 --- a/linkeaselite/files/linkeaselite-config.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/sh - -. /lib/functions.sh - -case "$1" in - save) - if [ -n "$2" ]; then - uci set "linkeaselite.@linkeaselite[0].preconfig=$2" - uci commit linkeaselite - fi - ;; - - load) - data="`uci -q get linkeaselite.@linkeaselite[0].preconfig`" - if [ -z "${data}" ]; then - echo "nil" - else - echo "${data}" - fi - ;; - - local_save) - if [ -n "$2" ]; then - uci set "linkeaselite.@linkeaselite[0].local_home=$2" - uci commit linkeaselite - ROOT_DIR="$2" - if [ -f "/etc/config/quickstart" ]; then - config_load quickstart - config_get MAIN_DIR main main_dir "" - config_get CONF_DIR main conf_dir "" - config_get PUB_DIR main pub_dir "" - config_get DL_DIR main dl_dir "" - config_get TMP_DIR main tmp_dir "" - [ "$ROOT_DIR" = "$MAIN_DIR" ] && exit 0 - uci set "quickstart.main.main_dir=$ROOT_DIR" - if [ -z "$CONF_DIR" ] || [ "$CONF_DIR" = "$MAIN_DIR/Configs" ]; then - uci set "quickstart.main.conf_dir=$ROOT_DIR/Configs" - fi - if [ -z "$PUB_DIR" ] || [ "$PUB_DIR" = "$MAIN_DIR/Public" ]; then - uci set "quickstart.main.pub_dir=$ROOT_DIR/Public" - fi - if [ -z "$DL_DIR" ] || [ "$DL_DIR" = "$MAIN_DIR/Public/Downloads" ]; then - uci set "quickstart.main.dl_dir=$ROOT_DIR/Public/Downloads" - fi - if [ -z "$TMP_DIR" ] || [ "$TMP_DIR" = "$MAIN_DIR/Caches" ]; then - uci set "quickstart.main.tmp_dir=$ROOT_DIR/Caches" - fi - uci commit quickstart - fi - fi - ;; - - local_load) - if [ -f "/etc/config/quickstart" ]; then - data="`uci -q get quickstart.main.main_dir`" - fi - if [ -z "$data" ]; then - data="`uci -q get linkeaselite.@linkeaselite[0].local_home`" - fi - if [ -z "${data}" ]; then - echo "nil" - else - echo "${data}" - fi - ;; - - status) - if pidof linkease-lite >/dev/null 2>&1; then - echo "running" - else - echo "stopped" - fi - ;; - - *) - echo "Usage: $0 {save|load|local_save|local_load|status}" - exit 1 -esac diff --git a/linkeaselite/files/linkeaselite.config b/linkeaselite/files/linkeaselite.config deleted file mode 100644 index 1e610c0f..00000000 --- a/linkeaselite/files/linkeaselite.config +++ /dev/null @@ -1,4 +0,0 @@ -config linkeaselite - option enabled '1' - option port '8897' - option allowPublic '0' diff --git a/linkeaselite/files/linkeaselite.init b/linkeaselite/files/linkeaselite.init deleted file mode 100755 index 276d6fd5..00000000 --- a/linkeaselite/files/linkeaselite.init +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 -STOP=10 -USE_PROCD=1 - -PROG=/usr/sbin/linkease-lite -LOCAL_API=/var/run/linkeaselite.sock - -read_config() { - section="$1" - config_get_bool enabled "$section" enabled 1 - config_get port "$section" port 8897 - config_get_bool allowPublic "$section" allowPublic 0 -} - -sync_firewall() { - uci -q delete firewall.linkeaselite - if [ "$allowPublic" = "1" ]; then - uci -q set firewall.linkeaselite=rule - uci -q set firewall.linkeaselite.name="linkeaselite" - uci -q set firewall.linkeaselite.target="ACCEPT" - uci -q set firewall.linkeaselite.src="wan" - uci -q set firewall.linkeaselite.proto="tcp" - uci -q set firewall.linkeaselite.dest_port="$port" - fi - uci -q commit firewall - /etc/init.d/firewall reload -} - -stop_linkease_runtimes() { - [ -x /etc/init.d/linkeasefull ] && /etc/init.d/linkeasefull stop >/dev/null 2>&1 - [ -x /etc/init.d/linkease ] && /etc/init.d/linkease stop >/dev/null 2>&1 - - if uci -q get linkease.@linkease[0] >/dev/null 2>&1; then - uci -q set linkease.@linkease[0].enabled="0" - uci -q commit linkease - fi - if uci -q get linkeasefull.@linkeasefull[0] >/dev/null 2>&1; then - uci -q set linkeasefull.@linkeasefull[0].enabled="0" - uci -q commit linkeasefull - fi -} - -start_service() { - config_load linkeaselite - config_foreach read_config linkeaselite - sync_firewall - [ "$enabled" = "1" ] || return 1 - [ -x "$PROG" ] || return 1 - - stop_linkease_runtimes - rm -f "$LOCAL_API" - - procd_open_instance linkeaselite - procd_set_param limits nofile="65535 65535" - procd_set_param command "$PROG" - procd_append_param command --deviceAddr ":$port" --localApi "$LOCAL_API" - [ "$allowPublic" = "1" ] && procd_append_param command --allowPublic - procd_set_param respawn - procd_set_param stdout 1 - procd_set_param stderr 1 - procd_close_instance -} - -service_triggers() { - procd_add_reload_trigger "linkeaselite" -} diff --git a/linkeaselite/files/linkeaselite.uci-default b/linkeaselite/files/linkeaselite.uci-default deleted file mode 100644 index 6ebed20d..00000000 --- a/linkeaselite/files/linkeaselite.uci-default +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh -[ ! -f "/usr/share/ucitrack/luci-app-linkeaselite.json" ] && { - cat > /usr/share/ucitrack/luci-app-linkeaselite.json << EEOF -{ - "config": "linkeaselite", - "init": "linkeaselite" -} -EEOF -} - -if ! uci -q get linkeaselite.@linkeaselite[0] >/dev/null; then - uci -q add linkeaselite linkeaselite >/dev/null -fi - -set_default() { - key="$1" - value="$2" - current="$(uci -q get "linkeaselite.@linkeaselite[0].$key" 2>/dev/null || true)" - [ -n "$current" ] && return 0 - uci -q set "linkeaselite.@linkeaselite[0].$key=$value" -} - -set_default enabled 1 -set_default port 8897 -set_default allowPublic 0 -uci -q commit linkeaselite - -port="$(uci -q get linkeaselite.@linkeaselite[0].port 2>/dev/null || true)" -[ -n "$port" ] || port=8897 -allow_public="$(uci -q get linkeaselite.@linkeaselite[0].allowPublic 2>/dev/null || true)" - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@linkeaselite[-1] - add ucitrack linkeaselite - set ucitrack.@linkeaselite[-1].init=linkeaselite - commit ucitrack -EOF - -if [ "$allow_public" = "1" ]; then - uci -q batch <<-EOF >/dev/null - delete firewall.linkeaselite - set firewall.linkeaselite=rule - set firewall.linkeaselite.name="linkeaselite" - set firewall.linkeaselite.target="ACCEPT" - set firewall.linkeaselite.src="wan" - set firewall.linkeaselite.proto="tcp" - set firewall.linkeaselite.dest_port="$port" - commit firewall -EOF -else - uci -q batch <<-EOF >/dev/null - delete firewall.linkeaselite - commit firewall -EOF -fi - -/etc/init.d/linkeaselite enable -/etc/init.d/linkeaselite restart - -exit 0 diff --git a/luci-theme-footstrap/Makefile b/luci-theme-footstrap/Makefile index 98ae39f5..1b3361e6 100644 --- a/luci-theme-footstrap/Makefile +++ b/luci-theme-footstrap/Makefile @@ -17,7 +17,7 @@ LUCI_NAME:=luci-theme-footstrap FOOTSTRAP_VERSION?= ifneq ($(FOOTSTRAP_VERSION),) PKG_VERSION:=$(FOOTSTRAP_VERSION) -PKG_RELEASE:=6 +PKG_RELEASE:=7 endif LUCI_TITLE:=Footstrap Theme diff --git a/luci-theme-footstrap/htdocs/luci-static/resources/fs-sheets.js b/luci-theme-footstrap/htdocs/luci-static/resources/fs-sheets.js index 04d61ea3..e5ed6e10 100644 --- a/luci-theme-footstrap/htdocs/luci-static/resources/fs-sheets.js +++ b/luci-theme-footstrap/htdocs/luci-static/resources/fs-sheets.js @@ -525,8 +525,8 @@ function silence(el) { * `:root { --span-spacing; --clr-background; … }`, the view adds `:root`, `.cbi-page-actions`, * `.cbi-button-save:not(.custom-save-button)` and a `td:last-child` riding as the second half of * `#file-manager-container th:last-child, td:last-child`. `luci-app-ssclash` adds four more as the - * Ace editor initialises. Invasive by the only definition that also catches - * `[class] { padding: 0 !important }`. + * Ace editor initialises. Invasive by the only definition that also catches `[class] { padding: 0 + * !important }`. * * Measured on owrt2512, 25.12.4, with ownership taken out of documentPoisoned() and put back: * leaving either page is a FULL LOAD, 5 runs of 5, and with ownership all 5 are in place — @@ -539,9 +539,9 @@ function silence(el) { * TOP LEVEL happens once, because `L.require` caches the module, so a second visit re-runs nothing * and the page renders unstyled — HexEditor's injector above is exactly that shape, and its own * `getElementById('hexeditor-styles')` guard never gets a second chance to notice the element is - * gone, because nothing calls it again. A sheet injected from - * `render()` would survive removal, but the two cases are indistinguishable from here and only one - * mechanism can be right for both. Disabling is reversible, which is the whole difference. + * gone, because nothing calls it again. A sheet injected from `render()` would survive removal, but + * the two cases are indistinguishable from here and only one mechanism can be right for both. + * Disabling is reversible, which is the whole difference. * * OWNER = body[data-page] when the sheet was re-hosted. The order that makes this sound is in * fs-router.js: it stamps data-page (line ~371) BEFORE require()ing the view class (~450), so at the diff --git a/luci-theme-footstrap/root/etc/uci-defaults/30_luci-theme-footstrap b/luci-theme-footstrap/root/etc/uci-defaults/30_luci-theme-footstrap index 71e593c9..3f0c8eec 100755 --- a/luci-theme-footstrap/root/etc/uci-defaults/30_luci-theme-footstrap +++ b/luci-theme-footstrap/root/etc/uci-defaults/30_luci-theme-footstrap @@ -103,10 +103,9 @@ mkdir -p /etc/footstrap 2>/dev/null [ -d /www/luci-static/footstrap ] && ln -sf /etc/footstrap/pattern.svg /www/luci-static/footstrap/pattern.svg 2>/dev/null # The admin-installed webfonts (/etc/footstrap/fonts, see partials/head.ut) are a whole DIRECTORY # rather than one file: the faces plus an @font-face sheet beside them. Same arrangement as the two -# images above, -# and linking a directory has TWO traps, both of which end with `ln` exiting 0 and the link sitting -# one level too deep, at .../fonts/fonts — where no browser looks, so the fonts silently do not -# serve and nothing reports a thing: +# images above, and linking a directory has TWO traps, both of which end with `ln` exiting 0 and +# the link sitting one level too deep, at .../fonts/fonts — where no browser looks, so the fonts +# silently do not serve and nothing reports a thing: # - the link already exists and points at a directory: `ln -sf` follows it. `-n` is the fix. # - the path is a REAL directory, which every footstrap before 0.12.1 shipped here full of # woff2 files. `-n` does not help — measured on a 25.12 router: exit 0, link created inside. diff --git a/luci-theme-footstrap/ucode/template/themes/footstrap/partials/head.ut b/luci-theme-footstrap/ucode/template/themes/footstrap/partials/head.ut index 1c2b78ba..7b12a5a7 100644 --- a/luci-theme-footstrap/ucode/template/themes/footstrap/partials/head.ut +++ b/luci-theme-footstrap/ucode/template/themes/footstrap/partials/head.ut @@ -107,20 +107,32 @@ A Cyrillic or CJK family name is refused by this too — those faces carry a Latin name as well, and the tool's README says to use it. - THE QUOTE IS THE ONE CHARACTER THE CHARSET CANNOT REFUSE, and it does not end anything — it - EXTENDS. Both quotes have to be in the class (the shipped default is `"Manrope",system-ui,…`), - and a value with an ODD count of either opens a CSS string that runs to the end of the sheet: - `font_sans=My"Font` swallows `; --fs-font-mono: …; }` with it, so a typo in the sans stack - silently costs the MONO one on a router that set that one correctly. Two options this file - calls independent, and one takes the other down. So count them and refuse the odd case: n - quotes split a string into n+1 parts, hence the even-length test. */ + THE TWO QUOTES ARE WHAT THE CHARSET CANNOT REFUSE, and neither ends anything — they EXTEND. + Both have to be in the class (the shipped default is `"Manrope",system-ui,…`), and one left + OPEN starts a CSS string that runs to the end of the sheet: `font_sans=My"Font` swallows + `; --fs-font-mono: …; }` with it, so a typo in the sans stack silently costs the MONO one on a + router that set that one correctly. Two options this file calls independent, and one takes + the other down. + + COUNTING THEM IS NOT THE TEST, because tokenizing is STATEFUL: inside '…' a " is literal and + vice versa. `"O'Reilly Sans", 'Fira Sans` — a family name with an apostrophe next to a stack + whose closing quote was forgotten — holds two of each, so both counts come out even while the + second `'` is still open at the end. So scan in ORDER, the way the value is actually read: + the quote that opens wins until its own kind closes it, and one still open at the end refuses + the value. `for (let c in …)` walks array VALUES in ucode, and split(v, '') on the empty + separator yields one character per element. */ function _sd_family(v) { if (!(type(v) == 'string' && length(v) >= 1 && length(v) <= 120 && match(v, /^[A-Za-z0-9 ,._"'-]+$/))) return ''; - if ((length(split(v, '"')) % 2) == 0 || (length(split(v, "'")) % 2) == 0) - return ''; - return v; + let q = ''; + for (let c in split(v, '')) { + if (q == '') + q = (c == '"' || c == "'") ? c : ''; + else if (c == q) + q = ''; + } + return (q == '') ? v : ''; } let _sd_fsans = _sd_family(fs_defaults.font_sans); let _sd_fmono = _sd_family(fs_defaults.font_mono);