Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Colour handling improvements #8702

Draft
wants to merge 101 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
fb9c0d6
Replace 12 year old CSS colour parsing library
Jermolene Oct 21, 2024
93d1c05
Include colour.js license and mark version number
Jermolene Oct 21, 2024
467a1a4
Introduce wikify operator
Jermolene Oct 22, 2024
a23ee16
Rewrite colour macro as a function
Jermolene Oct 22, 2024
e1e73d2
Merge branch 'master' into colour-improvements
Jermolene Oct 23, 2024
1e5c69e
Fix typo
Jermolene Oct 23, 2024
4af573a
Fix nested colour definitions
Jermolene Oct 23, 2024
96b85ed
Fix up the tests
Jermolene Oct 24, 2024
d372729
Add colour-lighten and colour-darken operators
Jermolene Oct 24, 2024
b5a22e3
Remove obsolete comment
Jermolene Oct 25, 2024
fc36941
Improve colour palette switcher with previews
Jermolene Oct 25, 2024
151f61a
Palette chooser styling tweaks
Jermolene Oct 25, 2024
4445111
Merge branch 'master' into colour-improvements
Jermolene Oct 30, 2024
4f2754d
Merge branch 'master' into colour-improvements
Jermolene Oct 31, 2024
bc0fde6
Fix palette chooser when displayed in "Tools" dropdown
Jermolene Oct 31, 2024
85fa913
Merge branch 'master' into colour-improvements
Jermolene Nov 3, 2024
a8fb071
Add expertimental colour-oklch operator
Jermolene Nov 3, 2024
81b7bb4
Merge branch 'master' into colour-improvements
Jermolene Nov 4, 2024
ff5c846
Indentation for palette switcher
Jermolene Nov 4, 2024
23eccd1
Merge branch 'master' into colour-improvements
Jermolene Nov 4, 2024
c607440
Restore default styling for chosen chooser item
Jermolene Nov 5, 2024
348f717
Remove logging
Jermolene Nov 5, 2024
c3ce9ca
Testing Netlify CI
Jermolene Nov 6, 2024
a4d9303
Testing CI
Jermolene Nov 6, 2024
250e57c
Remove wikify operator and refactor palette preview
Jermolene Nov 7, 2024
1be89a2
Make preview templates tag driven and extensible
Jermolene Nov 8, 2024
f889157
Introduce new static palette architecture
Jermolene Nov 9, 2024
4e2f2be
Avoid redefining the colour function by adding a configuration variable
Jermolene Nov 9, 2024
b54d56e
Support for imported palettes
Jermolene Nov 9, 2024
297ae7e
Fix preview of filtered palettes
Jermolene Nov 10, 2024
38d5daa
Improve chooser chosen item highlight
Jermolene Nov 10, 2024
bad9517
Another fix for filtered palette previews
Jermolene Nov 10, 2024
46da161
Add aria labels to palette switcher
Jermolene Nov 11, 2024
1db8cf7
Merge branch 'master' into colour-improvements
Jermolene Nov 12, 2024
ad1b0fd
Palette tweaks
Jermolene Nov 12, 2024
21cd3b8
Merge branch 'master' into colour-improvements
Jermolene Nov 12, 2024
7de5f40
Merge branch 'master' into colour-improvements
Jermolene Nov 12, 2024
c2ee072
Merge branch 'master' into colour-improvements
Jermolene Nov 12, 2024
3faf9ba
Fix previews of filtered palettes
Jermolene Nov 14, 2024
8b59b61
Palette tweaks
Jermolene Nov 14, 2024
809465b
Merge branch 'master' into colour-improvements
Jermolene Nov 16, 2024
cfabc92
Update contrastcolour macro to use color.js
Jermolene Nov 16, 2024
b2d0c22
Componentise more preview components
Jermolene Nov 17, 2024
32ac671
Add alert preview
Jermolene Nov 17, 2024
b0828cc
Add notification preview
Jermolene Nov 17, 2024
3507b0f
Fix filtered palette previews
Jermolene Nov 17, 2024
84bef54
Docs for colour-oklch operator
Jermolene Nov 18, 2024
76f2dec
Start fixing the TwentyTwenties palettes
Jermolene Nov 18, 2024
aa69c3a
Add colour-contrast operator
Jermolene Nov 18, 2024
cd5bbcd
Add contrast checks to TwentyTwenties palette
Jermolene Nov 18, 2024
9efcad9
Display test results at the bottom of the palette switcher
Jermolene Nov 19, 2024
fc695e7
Merge branch 'master' into colour-improvements
Jermolene Dec 5, 2024
6a66c49
Merge branch 'master' into colour-improvements
Jermolene Dec 14, 2024
6fe16bc
Fix colour for site title
Jermolene Dec 14, 2024
5a6eea7
Make the alert and notification previews be optional
Jermolene Dec 14, 2024
b1fcb18
Refactor for clearer variable names
Jermolene Dec 15, 2024
1df0ac4
Refactor colour-oklch operator to colour-set-oklch
Jermolene Dec 15, 2024
ae1d9f5
Add colour-get-oklch operator
Jermolene Dec 15, 2024
c1e36a1
Add colour-interpolate operator
Jermolene Dec 15, 2024
2640406
Include contrast value in contrast errors
Jermolene Dec 15, 2024
3c44532
Barebones docs for colour spaces
Jermolene Dec 15, 2024
2685fa7
Improvements to TwentyTwenties palettes
Jermolene Dec 15, 2024
2eee3bf
Merge branch 'master' into colour-improvements
Jermolene Dec 21, 2024
2558dc0
TwentyTwenties palette: use interpolation
Jermolene Dec 22, 2024
6a06df7
Fix palette switcher
Jermolene Dec 27, 2024
b90b449
Use interpolation to derive colours
Jermolene Jan 2, 2025
c02c825
Add a primitive custom palette editor
Jermolene Jan 2, 2025
5d1cf25
Add best contrast operator
Jermolene Jan 7, 2025
6b39d6a
Fix editing colours that are not in 6 digit hex format
Jermolene Jan 8, 2025
d1ce548
Download button should use palette colours
Jermolene Jan 8, 2025
a429306
Clarify method name
Jermolene Jan 8, 2025
2cbd108
Fix more TwentyTwenties entries
Jermolene Jan 8, 2025
bd4b3e4
Fix some old-style palette references
Jermolene Jan 8, 2025
28167ad
Add a palette that automatically switches between dark and light
Jermolene Jan 8, 2025
2b0c634
Refactor actions for recompiling current palette
Jermolene Jan 8, 2025
69363bf
Palette manager should recompile palette on edits
Jermolene Jan 8, 2025
2edcf0f
Refactor TwentyTwenties editor
Jermolene Jan 9, 2025
55d9e92
Edit text widget shouldn't fully refresh when default attribute changes
Jermolene Jan 9, 2025
c75f50e
Fix palette switcher used in the sidebar
Jermolene Jan 9, 2025
3614236
Paldette and style tweaks
Jermolene Jan 21, 2025
62fb916
Merge branch 'master' into colour-improvements
Jermolene Jan 23, 2025
9681b0d
Merge branch 'master' into colour-improvements
Jermolene Jan 23, 2025
0baf395
Merge background actions and media tracker from #8555
Jermolene Jan 23, 2025
28c1e77
Make sure rootwidget is available before background actions start
Jermolene Jan 24, 2025
9588b7f
Autocompile palettes when they change
Jermolene Jan 24, 2025
407e58f
Add a basic dark palette
Jermolene Jan 24, 2025
8c619fd
Compile palette at startup
Jermolene Jan 24, 2025
0dfde06
Detect darkmode at startup
Jermolene Jan 24, 2025
7513e44
Allow text editor type=color for colours not in hex RGB format
Jermolene Jan 25, 2025
3ea7cd3
Palette editors no longer need to manually recompile the palette
Jermolene Jan 25, 2025
0fd5b04
Merge branch 'master' into colour-improvements
Jermolene Jan 25, 2025
8957424
Start adding tests for palette operations
Jermolene Jan 25, 2025
d2bbc56
Move modern palettes to correct directory
Jermolene Jan 25, 2025
317e124
Introduce an improved but temporary cache invalidation method for pal…
Jermolene Jan 26, 2025
0c8aad4
Replace accumulate-palette-entries with new changecount filter
Jermolene Jan 27, 2025
efcd239
Merge branch 'master' into colour-improvements
Jermolene Jan 27, 2025
546e438
Allow background actions to be scoped by platform
Jermolene Jan 27, 2025
effeed7
Remove extraneous logging
Jermolene Jan 27, 2025
c1fd82f
Minor cleanups
Jermolene Jan 28, 2025
139b61f
Proper recursion detection for palettes
Jermolene Jan 28, 2025
22cf3b2
Remove infinite loop that was added for testing
Jermolene Jan 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/language/en-GB/ControlPanel.multids
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ LayoutSwitcher/Caption: Layout
LoadedModules/Caption: Loaded Modules
LoadedModules/Hint: These are the currently loaded tiddler modules linked to their source tiddlers. Any italicised modules lack a source tiddler, typically because they were setup during the boot process.
Palette/Caption: Palette
Palette/CustomEditor/Prompt: Custom editor for current palette:
Palette/Editor/Clone/Caption: clone
Palette/Editor/Clone/Prompt: It is recommended that you clone this shadow palette before editing it
Palette/Editor/Delete/Hint: delete this entry from the current palette
Expand Down
129 changes: 129 additions & 0 deletions core/modules/background-actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*\
title: $:/core/modules/background-actions.js
type: application/javascript
module-type: global

Class to dispatch actions when filters change

\*/
(function(){

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

function BackgroundActionDispatcher(filterTracker,wiki) {
var self = this;
this.filterTracker = filterTracker;
this.wiki = wiki;
this.nextTrackedFilterId = 1;
this.trackedFilters = Object.create(null); // Hashmap by id
// Track the filter for the background actions
this.filterTracker.track({
filterString: "[all[tiddlers+shadows]tag[$:/tags/BackgroundAction]!is[draft]]",
fnEnter: function fnEnter(title) {
return self.trackFilter(title);
},
fnLeave: function fnLeave(title,enterValue) {
self.untrackFilter(enterValue);
},
fnChange: function fnChange(title,enterValue) {
self.untrackFilter(enterValue);
return self.trackFilter(title);
},
fnProcess: function fnProcess(changes) {
self.process(changes);
}
});
}

BackgroundActionDispatcher.prototype.trackFilter = function(title) {
var tiddler = this.wiki.getTiddler(title),
id = this.nextTrackedFilterId++,
tracker = new BackgroundActionTracker({
wiki: this.wiki,
title: title,
trackFilter: tiddler.fields["track-filter"],
actions: tiddler.fields.text
});
this.trackedFilters[id] = tracker;
return id;
};

BackgroundActionDispatcher.prototype.untrackFilter = function(enterValue) {
var tracker = this.trackedFilters[enterValue];
if(tracker) {
tracker.destroy();
}
delete this.trackedFilters[enterValue];
};

BackgroundActionDispatcher.prototype.process = function(changes) {
for(var id in this.trackedFilters) {
this.trackedFilters[id].process(changes);
}
};

/*
Represents an individual tracked filter. Options include:
wiki: wiki to use
title: title of the tiddler being tracked
trackFilter: filter string to track changes
actions: actions to be executed when the filter changes
*/
function BackgroundActionTracker(options) {
var self = this;
this.wiki = options.wiki;
this.title = options.title;
this.trackFilter = options.trackFilter;
this.actions = options.actions
this.filterTracker = new $tw.FilterTracker(this.wiki);
this.hasChanged = false;
this.trackerID = this.filterTracker.track({
filterString: this.trackFilter,
fnEnter: function(title) {
self.hasChanged = true;
},
fnLeave: function(title,enterValue) {
self.hasChanged = true;
},
fnProcess: function(changes) {
if(self.hasChanged) {
self.hasChanged = false;
console.log("Processing background action",self.title);
var tiddler = self.wiki.getTiddler(self.title),
doActions = true;
if(tiddler && tiddler.fields.platforms) {
doActions = false;
var platforms = $tw.utils.parseStringArray(tiddler.fields.platforms);
if(($tw.browser && platforms.indexOf("browser") !== -1) || ($tw.node && platforms.indexOf("node") !== -1)) {
doActions = true;
}
}
if(doActions) {
self.wiki.invokeActionString(
self.actions,
null,
{
currentTiddler: self.title
},{
parentWidget: $tw.rootWidget
}
);
}
}
}
});
}

BackgroundActionTracker.prototype.process = function(changes) {
this.filterTracker.handleChangeEvent(changes);
};

BackgroundActionTracker.prototype.destroy = function() {
this.filterTracker.untrack(this.trackerID);
};

exports.BackgroundActionDispatcher = BackgroundActionDispatcher;

})();
10 changes: 9 additions & 1 deletion core/modules/editor/engines/simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ function SimpleEngine(options) {
if(this.widget.editTag === "textarea") {
this.domNode.appendChild(this.widget.document.createTextNode(this.value));
} else {
this.domNode.value = this.value;
if(this.widget.editType === "color") {
// The <input type="color"> element requires a six digit hex value
this.domNode.value = $tw.utils.convertCSSColorToRGBString(this.value);
} else {
this.domNode.value = this.value;
}
}
// Set the attributes
if(this.widget.editType && this.widget.editTag !== "textarea") {
Expand Down Expand Up @@ -86,6 +91,9 @@ Update the DomNode with the new text
*/
SimpleEngine.prototype.updateDomNodeText = function(text) {
try {
if(this.widget.editType === "color") {
text = $tw.utils.convertRGBStringToCSSColor(text);
}
this.domNode.value = text;
} catch(e) {
// Ignore
Expand Down
6 changes: 2 additions & 4 deletions core/modules/editor/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,10 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
EditTextWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
// Completely rerender if any of our attributes have changed
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) {
if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedTiddlers["$:/palette"] || changedAttributes.disabled || changedAttributes.fileDrop) {
this.refreshSelf();
return true;
} else if (changedTiddlers[this.editRefreshTitle]) {
this.engine.updateDomNodeText(this.getEditInfo().value);
} else if(changedTiddlers[this.editTitle]) {
} else if (changedAttributes["default"] || changedTiddlers[this.editRefreshTitle] || changedTiddlers[this.editTitle]) {
var editInfo = this.getEditInfo();
this.updateEditor(editInfo.value,editInfo.type);
}
Expand Down
108 changes: 108 additions & 0 deletions core/modules/filter-tracker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*\
title: $:/core/modules/filter-tracker.js
type: application/javascript
module-type: global

Class to track the results of a filter string

\*/
(function(){

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

function FilterTracker(wiki) {
this.wiki = wiki;
this.trackers = [];
this.nextTrackerId = 1;
}

FilterTracker.prototype.handleChangeEvent = function(changes) {
this.processTrackers();
this.processChanges(changes);
};

/*
Add a tracker to the filter tracker. Returns null if any of the parameters are invalid, or a tracker id if the tracker was added successfully. Options include:
filterString: the filter string to track
fnEnter: function to call when a title enters the filter results. Called even if the tiddler does not actually exist. Called as (title), and should return a truthy value that is stored in the tracker as the "enterValue"
fnLeave: function to call when a title leaves the filter results. Called as (title,enterValue)
fnChange: function to call when a tiddler changes in the filter results. Only called for filter results that identify a tiddler or shadow tiddler. Called as (title,enterValue), and may optionally return a replacement enterValue
fnProcess: function to call each time the tracker is processed, after any enter, leave or change functions are called. Called as (changes)
*/
FilterTracker.prototype.track = function(options) {
// Add the tracker details
var tracker = {
id: this.nextTrackerId++,
filterString: options.filterString,
fnEnter: options.fnEnter,
fnLeave: options.fnLeave,
fnChange: options.fnChange,
fnProcess: options.fnProcess,
previousResults: [], // Results from the previous time the tracker was processed
resultValues: {} // Map by title to the value returned by fnEnter
};
this.trackers.push(tracker);
// Process the tracker
this.processTracker(this.trackers.length - 1);
return tracker.id;
};

FilterTracker.prototype.untrack = function(id) {
for(var t=0; t<this.trackers.length; t++) {
if(this.trackers[t].id === id) {
this.trackers.splice(t,1);
break;
}
}
};

FilterTracker.prototype.processTrackers = function() {
for(var t=0; t<this.trackers.length; t++) {
this.processTracker(t);
}
};

FilterTracker.prototype.processTracker = function(index) {
var tracker = this.trackers[index];
var results = [];
// Evaluate the filter and remove duplicate results
$tw.utils.each(this.wiki.filterTiddlers(tracker.filterString),function(title) {
$tw.utils.pushTop(results,title);
});
// Process the newly entered results
$tw.utils.each(results,function(title) {
if(tracker.previousResults.indexOf(title) === -1 && !tracker.resultValues[title] && tracker.fnEnter) {
tracker.resultValues[title] = tracker.fnEnter(title) || true;
}
});
// Process the results that have just left
$tw.utils.each(tracker.previousResults,function(title) {
if(results.indexOf(title) === -1 && tracker.resultValues[title] && tracker.fnLeave) {
tracker.fnLeave(title,tracker.resultValues[title]);
delete tracker.resultValues[title];
}
});
// Update the previous results
tracker.previousResults = results;
};

FilterTracker.prototype.processChanges = function(changes) {
for(var t=0; t<this.trackers.length; t++) {
var tracker = this.trackers[t];
$tw.utils.each(changes,function(change,title) {
if(title && tracker.previousResults.indexOf(title) !== -1 && tracker.fnChange) {
// Call the change function and if it doesn't return a value then keep the old value
tracker.resultValues[title] = tracker.fnChange(title,tracker.resultValues[title]) || tracker.resultValues[title];
}
});
if(tracker.fnProcess) {
tracker.fnProcess(changes);
}
}
};

exports.FilterTracker = FilterTracker;

})();
26 changes: 26 additions & 0 deletions core/modules/filters/changecount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*\
title: $:/core/modules/filters/changecount.js
type: application/javascript
module-type: filteroperator

Filter operator for retrieving the changecount for each title in the list.

\*/
(function(){

/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";

/*
Export our filter function
*/
exports.changecount = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
results.push(options.wiki.getChangeCount(title) + "");
});
return results;
};

})();
Loading