🐤 Sync 2026-08-06 10:07:59

This commit is contained in:
github-actions[bot] committed 2026-08-06 10:07:59 +08:00
1 parent 90348f4645
commit d02e0fec8f
12 files changed
+57 -324

No files matched your search

+12 -9
View File
@@ -10,25 +10,28 @@ include $(TOPDIR)/rules.mk
PKG_ARCH_LINKEASE:=$(ARCH) PKG_ARCH_LINKEASE:=$(ARCH)
PKG_NAME:=linkease-common-bin PKG_NAME:=linkease-common-bin
PKG_SOURCE_DATE:=1.7.5 PKG_VERSION:=linkease-runtime-v1.7.5
PKG_RELEASE:=1 PKG_SOURCE_DATE:=$(PKG_VERSION)
PKG_RELEASE:=2
ARCH_HEXCODE:= ARCH_HEXCODE:=
ifeq ($(ARCH),x86_64) ifeq ($(ARCH),x86_64)
ARCH_HEXCODE=8664 ARCH_HEXCODE=8664
PKG_HASH:=skip
else ifeq ($(ARCH),aarch64) else ifeq ($(ARCH),aarch64)
ARCH_HEXCODE=aa64 ARCH_HEXCODE=aa64
PKG_HASH:=skip
else ifeq ($(ARCH),arm) else ifeq ($(ARCH),arm)
ARCH_HEXCODE=aa32 ARCH_HEXCODE=aa32
PKG_HASH:=skip
else ifeq ($(ARCH),mipsel) else ifeq ($(ARCH),mipsel)
ARCH_HEXCODE=1b0c ARCH_HEXCODE=1b0c
endif endif
PKG_SOURCE_VERSION:=$(ARCH_HEXCODE) PKG_SOURCE_VERSION:=f6d705f77dade7d57c1bb24334da4028279689b9
PKG_SOURCE:=linkease-binary-$(PKG_SOURCE_DATE).tar.gz PKG_SOURCE:=linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz
PKG_SOURCE_URL:=https://dl.istoreos.com/binary/LinkEase/LinuxStorage/ PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/
PKG_HASH:=skip PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-common-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE)
PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-binary-$(PKG_SOURCE_DATE)
PKG_BUILD_PARALLEL:=1 PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0 PKG_USE_MIPS16:=0
@@ -57,8 +60,8 @@ endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin $(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)/heif-converter $(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)/linkease-media $(1)/usr/sbin/linkease-media
$(INSTALL_BIN) ./files/linkease-config.sh $(1)/usr/sbin/linkease-config.sh $(INSTALL_BIN) ./files/linkease-config.sh $(1)/usr/sbin/linkease-config.sh
endef endef
+11 -8
View File
@@ -10,25 +10,28 @@ include $(TOPDIR)/rules.mk
PKG_ARCH_LINKEASE:=$(ARCH) PKG_ARCH_LINKEASE:=$(ARCH)
PKG_NAME:=linkease PKG_NAME:=linkease
PKG_SOURCE_DATE:=1.7.5 PKG_VERSION:=linkease-runtime-v1.7.5
PKG_RELEASE:=4 PKG_SOURCE_DATE:=$(PKG_VERSION)
PKG_RELEASE:=5
ARCH_HEXCODE:= ARCH_HEXCODE:=
ifeq ($(ARCH),x86_64) ifeq ($(ARCH),x86_64)
ARCH_HEXCODE=8664 ARCH_HEXCODE=8664
PKG_HASH:=skip
else ifeq ($(ARCH),aarch64) else ifeq ($(ARCH),aarch64)
ARCH_HEXCODE=aa64 ARCH_HEXCODE=aa64
PKG_HASH:=skip
else ifeq ($(ARCH),arm) else ifeq ($(ARCH),arm)
ARCH_HEXCODE=aa32 ARCH_HEXCODE=aa32
PKG_HASH:=skip
else ifeq ($(ARCH),mipsel) else ifeq ($(ARCH),mipsel)
ARCH_HEXCODE=1b0c ARCH_HEXCODE=1b0c
endif endif
PKG_SOURCE_VERSION:=$(ARCH_HEXCODE) PKG_SOURCE_VERSION:=f6d705f77dade7d57c1bb24334da4028279689b9
PKG_SOURCE:=linkease-binary-$(PKG_SOURCE_DATE).tar.gz PKG_SOURCE:=linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE).tar.gz
PKG_SOURCE_URL:=https://dl.istoreos.com/binary/LinkEase/LinuxStorage/ PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/linkease-runtime-v$(PKG_SOURCE_DATE)/
PKG_HASH:=skip PKG_BUILD_DIR:=$(BUILD_DIR)/linkease-bin-$(PKG_SOURCE_DATE)-linux-$(PKG_ARCH_LINKEASE)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-binary-$(PKG_SOURCE_DATE)
PKG_BUILD_PARALLEL:=1 PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0 PKG_USE_MIPS16:=0
@@ -69,7 +72,7 @@ endef
define Package/$(PKG_NAME)/install define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/sbin/linkease-plugins $(1)/etc/config $(1)/etc/init.d $(1)/etc/uci-defaults $(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_CONF) ./files/linkease.config $(1)/etc/config/linkease
$(INSTALL_BIN) ./files/linkease.init $(1)/etc/init.d/linkease $(INSTALL_BIN) ./files/linkease.init $(1)/etc/init.d/linkease
$(INSTALL_BIN) ./files/linkease.uci-default $(1)/etc/uci-defaults/linkease $(INSTALL_BIN) ./files/linkease.uci-default $(1)/etc/uci-defaults/linkease
+3 -2
View File
@@ -7,8 +7,9 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=linkeasefull PKG_NAME:=linkeasefull
PKG_SOURCE_DATE:=3.0.4 PKG_VERSION:=linkease-runtime-v1.7.5
PKG_RELEASE:=3 PKG_SOURCE_DATE:=$(PKG_VERSION)
PKG_RELEASE:=4
ifeq ($(ARCH),x86_64) ifeq ($(ARCH),x86_64)
LINKEASE_RUNTIME_ARCH:=amd64 LINKEASE_RUNTIME_ARCH:=amd64
-75
View File
@@ -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)))
-78
View File
@@ -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
-4
View File
@@ -1,4 +0,0 @@
config linkeaselite
option enabled '1'
option port '8897'
option allowPublic '0'
-68
View File
@@ -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"
}
@@ -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
+1 -1
View File
@@ -17,7 +17,7 @@ LUCI_NAME:=luci-theme-footstrap
FOOTSTRAP_VERSION?= FOOTSTRAP_VERSION?=
ifneq ($(FOOTSTRAP_VERSION),) ifneq ($(FOOTSTRAP_VERSION),)
PKG_VERSION:=$(FOOTSTRAP_VERSION) PKG_VERSION:=$(FOOTSTRAP_VERSION)
PKG_RELEASE:=6 PKG_RELEASE:=7
endif endif
LUCI_TITLE:=Footstrap Theme LUCI_TITLE:=Footstrap Theme
@@ -525,8 +525,8 @@ function silence(el) {
* `:root { --span-spacing; --clr-background; … }`, the view adds `:root`, `.cbi-page-actions`, * `: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 * `.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 * `#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 * Ace editor initialises. Invasive by the only definition that also catches `[class] { padding: 0
* `[class] { padding: 0 !important }`. * !important }`.
* *
* Measured on owrt2512, 25.12.4, with ownership taken out of documentPoisoned() and put back: * 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 — * 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 * 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 * 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 * `getElementById('hexeditor-styles')` guard never gets a second chance to notice the element is
* gone, because nothing calls it again. A sheet injected from * gone, because nothing calls it again. A sheet injected from `render()` would survive removal, but
* `render()` would survive removal, but the two cases are indistinguishable from here and only one * the two cases are indistinguishable from here and only one mechanism can be right for both.
* mechanism can be right for both. Disabling is reversible, which is the whole difference. * 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 * 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 * fs-router.js: it stamps data-page (line ~371) BEFORE require()ing the view class (~450), so at the
@@ -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 [ -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 # 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 # rather than one file: the faces plus an @font-face sheet beside them. Same arrangement as the two
# images above, # images above, and linking a directory has TWO traps, both of which end with `ln` exiting 0 and
# and linking a directory has TWO traps, both of which end with `ln` exiting 0 and the link sitting # the link sitting one level too deep, at .../fonts/fonts — where no browser looks, so the fonts
# one level too deep, at .../fonts/fonts — where no browser looks, so the fonts silently do not # silently do not serve and nothing reports a thing:
# serve and nothing reports a thing:
# - the link already exists and points at a directory: `ln -sf` follows it. `-n` is the fix. # - 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 # - 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. # woff2 files. `-n` does not help — measured on a 25.12 router: exit 0, link created inside.
@@ -107,20 +107,32 @@
A Cyrillic or CJK family name is refused by this too — those faces carry a Latin name as well, 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. 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 THE TWO QUOTES ARE WHAT THE CHARSET CANNOT REFUSE, and neither ends anything — they EXTEND.
EXTENDS. Both quotes have to be in the class (the shipped default is `"Manrope",system-ui,…`), Both have to be in the class (the shipped default is `"Manrope",system-ui,…`), and one left
and a value with an ODD count of either opens a CSS string that runs to the end of the sheet: OPEN starts a CSS string that runs to the end of the sheet: `font_sans=My"Font` swallows
`font_sans=My"Font` swallows `; --fs-font-mono: …; }` with it, so a typo in the sans stack `; --fs-font-mono: …; }` with it, so a typo in the sans stack silently costs the MONO one on a
silently costs the MONO one on a router that set that one correctly. Two options this file router that set that one correctly. Two options this file calls independent, and one takes
calls independent, and one takes the other down. So count them and refuse the odd case: n the other down.
quotes split a string into n+1 parts, hence the even-length test. */
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) { function _sd_family(v) {
if (!(type(v) == 'string' && length(v) >= 1 && length(v) <= 120 && if (!(type(v) == 'string' && length(v) >= 1 && length(v) <= 120 &&
match(v, /^[A-Za-z0-9 ,._"'-]+$/))) match(v, /^[A-Za-z0-9 ,._"'-]+$/)))
return ''; return '';
if ((length(split(v, '"')) % 2) == 0 || (length(split(v, "'")) % 2) == 0) let q = '';
return ''; for (let c in split(v, '')) {
return 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_fsans = _sd_family(fs_defaults.font_sans);
let _sd_fmono = _sd_family(fs_defaults.font_mono); let _sd_fmono = _sd_family(fs_defaults.font_mono);