Configuration management for the Brazen user scripts framework
此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.greasyfork.org/scripts/418665/1847371/Brazen%20Framework%20-%20Configuration%20Manager.js
Typed settings schema, localStorage persistence, cross-tab sync, backup/restore, and DOM factories bound to View Layer widgets.
Greasy Fork: Configuration Manager · Requires: Utilities, View Layer · Used by: Framework core
new BrazenConfigurationManager(scriptPrefix, uiGenerator, tagSelectorGenerator)
| Parameter | Role |
|---|---|
scriptPrefix |
Prefix for localStorage keys |
uiGenerator |
BrazenViewLayer instance |
tagSelectorGenerator |
(tag: string) => string — used by addTagRulesetField / _optimizeTagRuleset |
Framework exposes this as this._configurationManager. Register fields in the subclass constructor; call initialize() during init() before UI build.
Display name strings (e.g. 'Tag Blacklist') are normalized to kebab-case keys via Utilities.toKebabCase (tag-blacklist). Use the same display name in createElement, getValue, and getField.
| Constant | add* method |
Stored value type |
UI |
|---|---|---|---|
CONFIG_TYPE_FLAG |
addFlagField(name, helpText) |
boolean |
Checkbox |
CONFIG_TYPE_TEXT |
addTextField(name, helpText, defaultValue?) |
string |
Text input; empty → defaultValue on read |
CONFIG_TYPE_NUMBER |
addNumberField(name, min, max, helpText) |
number |
Number input |
CONFIG_TYPE_COLOR |
addColorField(name, helpText) |
color string | Color input |
CONFIG_TYPE_RANGE |
addRangeField(name, min, max, helpText) |
{ minimum, maximum } |
Two number inputs |
CONFIG_TYPE_SELECT |
addSelectField(name, pairs, helpText) |
option value | See known limitation in spec |
CONFIG_TYPE_CHECKBOXES_GROUP |
addCheckboxesGroup(name, pairs, helpText) |
string[] of checked data-values |
Checkbox group |
CONFIG_TYPE_RADIOS_GROUP |
addRadiosGroup(name, pairs, helpText) |
selected data-value |
Radio group |
CONFIG_TYPE_RULESET |
addRulesetField(name, rows, helpText, onTranslate?, onFormat?, onOptimize?, sortRules?) |
string[] lines |
Textarea |
CONFIG_TYPE_BOOKMARKS |
addBookmarksField(name, helpText, handlers) |
array (not persisted) |
Bookmarks panel |
All add* methods return this (fluent).
On Apply/Save (setFromUserInterface):
REGEX_LINE_BREAK; trim empty lines.sortRules: true — locale-aware sort.onTranslateFromUI(values) — normalize (optional).onOptimize(values) — store result in field.optimized (filters read this at runtime).On interface refresh (updateUserInterface):
onFormatForUI(value) → join with \n for textarea display.addTagRulesetField(key, useSelectors, rows, helpText?, formatter?, sortRules?) wraps addRulesetField with default onOptimize → _optimizeTagRuleset.
Tag rule syntax (one rule per line):
& — AND (all tags in segment must match)| — OR within a segment// — comment suffix (ignored after split)Optimized output: array of arrays (each inner array = one conjunctive rule). Sorted shortest-first.
addBookmarksFieldaddBookmarksField('Bookmarks', 'Add pages you visit often.', {
load: () => /* array from GM_setValue */,
showAddButton: true,
pageMatch: { getCurrentUrl, normalizeUrl, onMatchChange, watchSelectors, isActive },
onAdd, onSort, onRemove(id), onNavigate(url),
})
| Behaviour | Detail |
|---|---|
persist |
false — excluded from localStorage backup object |
widget |
BrazenBookmarksPanel from createBookmarksPanel |
setFromUserInterface |
No-op |
updateUserInterface |
Calls handlers.load() then widget.render(value) |
createElementthis._configurationManager.createElement('My Setting') // display name
Invokes the field's createElement() which:
field.element.Fields without createElement called remain memory-only until mounted.
Each field implements:
| Callback | When |
|---|---|
createElement() |
First mount |
setFromUserInterface() |
Apply/Save — read DOM → field.value (+ ruleset optimize) |
updateUserInterface() |
Load/reset/tab switch — write field.value → DOM |
this._configurationManager.getValue('My Setting')
this._configurationManager.getField('My Setting') // ConfigurationField | null
this._configurationManager.getFieldOrFail('My Setting') // throws if missing
this._configurationManager.hasField('My Setting')
ConfigurationField properties: title, type, element, value, optimized?, helpText, minimum, maximum, options, persist, widget, ruleset callbacks.
| Store | Key | Content |
|---|---|---|
| Settings | {scriptPrefix}settings |
JSON object: kebab keys → values (skips persist: false) |
| Sync id | {scriptPrefix}settings-id |
{ id: number } — bumps on save |
initialize()LocalStore instances._syncLocalStore() — merge disk into fields; rulesets run onOptimize.onChange on settings store → updateInterface().visibilitychange — if tab visible and id changed, re-sync + onExternalConfigurationChange.| Method | Behaviour |
|---|---|
update() |
All mounted fields: setFromUserInterface() (rulesets: trim → optional sort → onTranslateFromUI → dedupe rules case-sensitively → onOptimize) |
save() |
update() → write store → bump sync id |
revertChanges() |
Re-read store into fields + updateInterface() |
updateInterface() |
All mounted fields: updateUserInterface() |
Framework button wiring:
update() + re-run compliance (no disk).save().revertChanges() + compliance.backup() downloads {scriptPrefix}backup.json:
{
"tag-blacklist": ["rule1", "rule2"],
"pagination-threshold": 20,
"id": 123456789
}
restore(response) — fetch/Response with JSON body; restores values + sync id; alerts success/failure.
Not included: GM_setValue data (bookmarks, download ledger) unless stored in a persisted config field.
onExternalConfigurationChange(handler) — (manager) => void when another tab saved. Framework registers compliance re-run.
generateValidationCallback(configKey) → default enable checks:
| Type | Active when |
|---|---|
| flag / radios / select | truthy value |
| checkboxes | length > 0 |
| number | value > 0 |
| range | `minimum > 0 \ |
| ruleset / text | length > 0 |
Used by framework _addItemComplianceFilter when no custom validate callback is supplied.
init() builds UI.createElement inside tab panels.addFlagField + ruleset).persist: false, GM_setValue).#bv-ui userScript reference if tabs need updateInterface from custom widgets.Next in stack: Item Attributes Resolver (before Framework core).