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

Preferences API #106

Draft
wants to merge 103 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
11d0985
Bump ReadiumCSS version
JayPanoz Feb 7, 2025
c474f7c
Remove scroll anchors
JayPanoz Feb 7, 2025
42b4a2b
Init interfaces
JayPanoz Feb 12, 2025
2057d00
Classes for Preference
JayPanoz Feb 13, 2025
bc13f84
EPUBPreferences class
JayPanoz Feb 13, 2025
2fb3856
Create EpubDefaults.ts
JayPanoz Feb 13, 2025
7f1c445
Match case of Epub interfaces and classes
JayPanoz Feb 13, 2025
45c83a4
EpubSettings class
JayPanoz Feb 13, 2025
1e6a0d3
Update image filters
JayPanoz Feb 13, 2025
dc7e8d3
Add checks in EpubPreferences constructor
JayPanoz Feb 13, 2025
0d2346b
Init EPUBPreferencesEditor
JayPanoz Feb 14, 2025
ea54b32
Add minimal and optimal lineLength
JayPanoz Feb 18, 2025
f8be9b6
LineLength as a helper
JayPanoz Feb 18, 2025
eac5e2c
Corrections in Preferences interfaces
JayPanoz Feb 18, 2025
189ea87
Add Properties for ReadiumCSS
JayPanoz Feb 19, 2025
b88f023
separate RCSS types from Preferences
JayPanoz Feb 19, 2025
091dc2b
Correct Theme enum
JayPanoz Feb 19, 2025
4751eb7
rename valueInRange method for consistency
JayPanoz Feb 19, 2025
986751c
Init ReadiumCSS class
JayPanoz Feb 19, 2025
8132b58
Corrections in lineLength helper
JayPanoz Feb 20, 2025
544291e
Update User Properties for corrected ReadiumCSS
JayPanoz Feb 20, 2025
67bc063
Rename visitedLinkColor property
JayPanoz Feb 20, 2025
f14883d
Init EpubNavigator config + pref editor
JayPanoz Feb 20, 2025
3cc4a69
Replace config with pref + defaults
JayPanoz Feb 20, 2025
9bd8203
add mixing export for preferences in Navigator
JayPanoz Feb 20, 2025
71658f0
Update @readium/css package
JayPanoz Feb 20, 2025
2c5b0e9
[WIP] CSS handling in EpubNavigator
JayPanoz Feb 21, 2025
9c75563
[WIP] setting properties methods and helpers
JayPanoz Feb 21, 2025
a0423be
colCount with line lengths
JayPanoz Feb 22, 2025
defab72
index for css folder
JayPanoz Feb 22, 2025
9460d07
add constraint prop in EpubPrefs
JayPanoz Feb 22, 2025
6adf033
Add missing prefs in LineLength
JayPanoz Feb 22, 2025
3c4e3de
Plug EpubDefaults
JayPanoz Feb 22, 2025
1c1c006
Handle optimal line length default
JayPanoz Feb 22, 2025
749a62d
add viewport width in data when update_properties
JayPanoz Feb 23, 2025
955d3a5
consistency in epubnav constructor
JayPanoz Feb 23, 2025
41bcf7a
Update virtual columns
JayPanoz Feb 23, 2025
6e59c17
Corrections in css update & commit
JayPanoz Feb 24, 2025
13b9db2
updateCSS in apply method
JayPanoz Feb 24, 2025
3c56d90
use values from ReadiumCSS in PrefEditor
JayPanoz Feb 24, 2025
fd13e75
Add comment re fontFamily effectiveValue
JayPanoz Feb 24, 2025
f5b896c
Update darkMode check in Decorator
JayPanoz Feb 24, 2025
c4ae60e
Add support for hex with 4 numbers in colorToRgba
JayPanoz Feb 24, 2025
4e8b41f
Correct currentProgression
JayPanoz Feb 24, 2025
61daba4
ReadiumCSS’ required attr
JayPanoz Feb 24, 2025
74c3c09
resume comms on setCSSProperties
JayPanoz Feb 24, 2025
66b70cf
Correct lang setting in BlobBuilder
JayPanoz Feb 24, 2025
ea10e49
Add PreferencesEditor in Configurable
JayPanoz Feb 24, 2025
3236321
pass settings to epubPreferenceEditor
JayPanoz Feb 24, 2025
a4146ca
Add link + selection colors to settings
JayPanoz Feb 25, 2025
4a142b2
Update effectiveValue of lineLength
JayPanoz Feb 25, 2025
6de7f7f
Add invertGaijiFilter to EpubSettings
JayPanoz Feb 25, 2025
b916448
Consistency in added constructors
JayPanoz Feb 25, 2025
41be484
handle ColCount setting in FXL
JayPanoz Feb 25, 2025
befc756
Apply constraint in EpubNavigator
JayPanoz Feb 25, 2025
fa3a57c
Correct effective values
JayPanoz Feb 25, 2025
25524ad
Add some color utils for contrast
JayPanoz Feb 25, 2025
745cebd
update contrast helper in color
JayPanoz Feb 25, 2025
12b0504
Correct adjustment of colors
JayPanoz Feb 25, 2025
5dc4aa5
Remove ResizeObserver polyfill
JayPanoz Feb 26, 2025
eca7fa8
Add custom key in Theme enum
JayPanoz Feb 26, 2025
96c8c4e
Adding Missing pieces of Pref API in EpubNavigator
JayPanoz Feb 26, 2025
cc76fe6
Correct preferencesEditor getters
JayPanoz Feb 26, 2025
080e552
Set some EpubDefaults
JayPanoz Feb 26, 2025
1be2160
Pass callback to update PrefEditor preferences
JayPanoz Feb 26, 2025
0fcaf3e
More PreferenceEditor fixes
JayPanoz Feb 26, 2025
6e45715
Only update prefEditor if not null
JayPanoz Feb 26, 2025
00f0b69
Bump version for breaking changes
JayPanoz Feb 26, 2025
465fc1b
Remove fontOpticalSizing default
JayPanoz Feb 26, 2025
aebfe62
Add missing export in EpubNavigator
JayPanoz Feb 26, 2025
e399760
Correct ReadiumCSS update
JayPanoz Feb 27, 2025
a1e8178
More fixes in ReadiumCSS
JayPanoz Feb 27, 2025
25468c5
Correct UserSettings constructor
JayPanoz Feb 27, 2025
556fdde
Add boolean check in EpubPreferences
JayPanoz Feb 27, 2025
f02a76f
More corrections in init + merging
JayPanoz Feb 27, 2025
d594bc5
Correct merging
JayPanoz Feb 27, 2025
002796c
Correct resizeObserver
JayPanoz Feb 27, 2025
f9b819d
Remove resize + orientationChange events in FXL
JayPanoz Feb 27, 2025
7e4ab6f
Correct init of Preferences
JayPanoz Feb 27, 2025
929bce1
Correct async in applyPref
JayPanoz Feb 27, 2025
0cd6ad9
update constraint pref
JayPanoz Feb 27, 2025
ad18bcb
Fix setting CSS props for hidden iframes
JayPanoz Feb 27, 2025
54b5e94
Update line lengths in ReadiumCSS
JayPanoz Feb 28, 2025
fb4704b
apply correct line-length on user property
JayPanoz Feb 28, 2025
33f9f57
move serializer to EpubPreferences
JayPanoz Feb 28, 2025
88c4f0a
Remove PreferenceSerializer export
JayPanoz Feb 28, 2025
afe62f0
Correct settings / defaults
JayPanoz Feb 28, 2025
68200e9
Resolve some column snapping issues
JayPanoz Feb 28, 2025
1d65686
SetContainerWidth on settings update
JayPanoz Feb 28, 2025
ba25b83
Fix updating of virtualCols
JayPanoz Feb 28, 2025
978be0a
consistency with resize/orientationChange
JayPanoz Feb 28, 2025
8c378f2
setCSSProperties in blob
JayPanoz Mar 3, 2025
9246537
Fix snapOffset when going backwards
JayPanoz Mar 3, 2025
a9ac8c8
Fix ColumnSnapping on mobile
JayPanoz Mar 3, 2025
e3343fc
transform as regex in column snapper Mutation
JayPanoz Mar 3, 2025
fbbf218
Override colCount in settings
JayPanoz Mar 4, 2025
302f55b
return settings as readonly
JayPanoz Mar 4, 2025
975456e
Init lineLengths with settings
JayPanoz Mar 4, 2025
c3e7014
Fix EpubNavigator for FXL
JayPanoz Mar 4, 2025
181338b
Move constraint to settings
JayPanoz Mar 4, 2025
cbc002a
Return settings for FXL
JayPanoz Mar 4, 2025
b304ab6
Remove unecessary number constructor
JayPanoz Mar 5, 2025
b7fb7d9
Protect setting CSS props if frame destroyed
JayPanoz Mar 5, 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
3 changes: 1 addition & 2 deletions navigator-html-injectables/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@readium/navigator-html-injectables",
"version": "1.3.3",
"version": "2.0.0-beta.1",
"type": "module",
"description": "An embeddable solution for connecting frames of HTML publications with a Readium Navigator",
"author": "readium",
Expand Down Expand Up @@ -48,7 +48,6 @@
"node": ">=18"
},
"devDependencies": {
"@juggle/resize-observer": "^3.4.0",
"@readium/shared": "workspace:*",
"css-selector-generator": "^3.6.9",
"tslib": "^2.6.1",
Expand Down
2 changes: 2 additions & 0 deletions navigator-html-injectables/src/comms/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export type CommsCommandKey =
"go_end" |
"go_start" |
"go_progression" |
"get_properties" |
"update_properties" |
"set_property" |
"remove_property" |
// "exact_progress" |
Expand Down
114 changes: 114 additions & 0 deletions navigator-html-injectables/src/helpers/color.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
export const colorToRgba = (color: string): { r: number; g: number; b: number; a: number; } => {
if (color.startsWith("rgb")) {
const rgb = color.match(/rgb\((\d+),\s(\d+),\s(\d+)(?:,\s(\d+))?\)/);
if (rgb) {
return {
r: parseInt(rgb[1], 10),
g: parseInt(rgb[2], 10),
b: parseInt(rgb[3], 10),
a: rgb[4] ? parseInt(rgb[4], 10) / 255 : 1,
};
}
} else if (color.startsWith("#")) {
const hex = color.slice(1);
if (hex.length === 3 || hex.length === 4) {
return {
r: parseInt(hex[0] + hex[0], 16) / 255,
g: parseInt(hex[1] + hex[1], 16) / 255,
b: parseInt(hex[2] + hex[2], 16) / 255,
a: hex.length === 4 ? parseInt(hex[3] + hex[3], 16) / 255 : 1,
};
} else if (hex.length === 6 || hex.length === 8) {
return {
r: parseInt(hex[0] + hex[1], 16) / 255,
g: parseInt(hex[2] + hex[3], 16) / 255,
b: parseInt(hex[4] + hex[5], 16) / 255,
a: hex.length === 8 ? parseInt(hex[6] + hex[7], 16) / 255 : 1,
};
}
}
return { r: 0, g: 0, b: 0, a: 1 };
};

export const getLuminance = (color: { r: number; g: number; b: number; a: number }): number => {
return 0.2126 * color.r * color.a + 0.7152 * color.g * color.a + 0.0722 * color.b * color.a;
}

export const isDarkColor = (color: string): boolean => {
const rgba = colorToRgba(color);
const luminance = getLuminance(rgba);
return luminance < 128;
};

export const isLightColor = (color: string): boolean => !isDarkColor(color);

export const checkContrast = (color1: string, color2: string): number => {
const rgba1 = colorToRgba(color1);
const rgba2 = colorToRgba(color2);
const lum1 = getLuminance(rgba1);
const lum2 = getLuminance(rgba2);
const brightest = Math.max(lum1, lum2);
const darkest = Math.min(lum1, lum2);
return (brightest + 0.05) / (darkest + 0.05);
};

export const ensureContrast = (color1: string, color2: string, contrast: number = 4.5): string[] => {
const c1 = colorToRgba(color1);
const c2 = colorToRgba(color2);

const lum1 = getLuminance(c1);
const lum2 = getLuminance(c2);
const [darkest, brightest] = lum1 < lum2 ? [lum1, lum2] : [lum2, lum1];

const contrastRatio = (brightest + 0.05) / (darkest + 0.05);
if (contrastRatio >= contrast) {
return [
`rgba(${c1.r}, ${c1.g}, ${c1.b}, ${c1.a})`,
`rgba(${c2.r}, ${c2.g}, ${c2.b}, ${c2.a})`
];
}

const adjustColor = (color: { r: number; g: number; b: number; a: number }, delta: number) => ({
r: Math.max(0, Math.min(255, color.r + delta)),
g: Math.max(0, Math.min(255, color.g + delta)),
b: Math.max(0, Math.min(255, color.b + delta)),
a: color.a
});

const delta = ((contrast - contrastRatio) * 255) / (contrastRatio + 0.05);
let correctedColor: { r: number; g: number; b: number; a: number };
let otherColor: { r: number; g: number; b: number; a: number };
if (lum1 < lum2) {
correctedColor = c1;
otherColor = c2;
} else {
correctedColor = c2;
otherColor = c1;
}

const correctedColorAdjusted = adjustColor(correctedColor, -delta);
const newLum = getLuminance(correctedColorAdjusted);
const newContrastRatio = (brightest + 0.05) / (newLum + 0.05);

if (newContrastRatio < contrast) {
const updatedDelta = ((contrast - newContrastRatio) * 255) / (newContrastRatio + 0.05);
const otherColorAdjusted = adjustColor(otherColor, updatedDelta);
return [
lum1 < lum2
? `rgba(${correctedColorAdjusted.r}, ${correctedColorAdjusted.g}, ${correctedColorAdjusted.b}, ${correctedColorAdjusted.a})`
: `rgba(${otherColorAdjusted.r}, ${otherColorAdjusted.g}, ${otherColorAdjusted.b}, ${otherColorAdjusted.a})`,
lum1 < lum2
? `rgba(${otherColorAdjusted.r}, ${otherColorAdjusted.g}, ${otherColorAdjusted.b}, ${otherColorAdjusted.a})`
: `rgba(${correctedColorAdjusted.r}, ${correctedColorAdjusted.g}, ${correctedColorAdjusted.b}, ${correctedColorAdjusted.a})`,
];
}

return [
lum1 < lum2
? `rgba(${correctedColorAdjusted.r}, ${correctedColorAdjusted.g}, ${correctedColorAdjusted.b}, ${correctedColorAdjusted.a})`
: `rgba(${otherColor.r}, ${otherColor.g}, ${otherColor.b}, ${otherColor.a})`,
lum1 < lum2
? `rgba(${otherColor.r}, ${otherColor.g}, ${otherColor.b}, ${otherColor.a})`
: `rgba(${correctedColorAdjusted.r}, ${correctedColorAdjusted.g}, ${correctedColorAdjusted.b}, ${correctedColorAdjusted.a})`,
];
};
37 changes: 37 additions & 0 deletions navigator-html-injectables/src/helpers/css.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,42 @@
import { ReadiumWindow } from "./dom";

export function getProperties(wnd: ReadiumWindow) {
const cssProperties: { [key: string]: string } = {};

const rootStyle = wnd.document.documentElement.style;

for (const prop in wnd.document.documentElement.style) {
// We check if the property belongs to the CSSStyleDeclaration instance
// We also ensure that the property is a numeric index (indicating an inline style)
if (
Object.hasOwn(rootStyle, prop) &&
!Number.isNaN(Number.parseInt(prop))
) {
cssProperties[rootStyle[prop]] = rootStyle.getPropertyValue(rootStyle[prop]);
}
}

return cssProperties;
}

export function updateProperties(wnd: ReadiumWindow, properties: { [key: string]: string }) {
const currentProperties = getProperties(wnd);

// Remove properties
Object.keys(currentProperties).forEach((key) => {
if (!properties.hasOwnProperty(key)) {
removeProperty(wnd, key);
}
});

// Update properties
Object.entries(properties).forEach(([key, value]) => {
if (currentProperties[key] !== value) {
setProperty(wnd, key, value);
}
});
}

// Easy way to get a CSS property
export function getProperty(wnd: ReadiumWindow, key: string) {
return wnd.document.documentElement.style.getPropertyValue(key);
Expand Down
47 changes: 24 additions & 23 deletions navigator-html-injectables/src/helpers/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,32 @@ export function getColumnCountPerScreen(wnd: ReadiumWindow) {
}

/**
* Having an odd number of columns when displaying two columns per screen causes snapping and page
* turning issues. To fix this, we insert a blank virtual column at the end of the resource.
* We have to make sure that the total number of columns is a multiple
* of the number of columns per screen.
* Otherwise it causes snapping and page turning issues.
* To fix this, we insert and remove blank virtual columns at the end of the resource.
*/
export function appendVirtualColumnIfNeeded(wnd: ReadiumWindow) {
const id = "readium-virtual-page";
let virtualCol = wnd.document.getElementById(id);
if (getColumnCountPerScreen(wnd) !== 2) {
if (virtualCol) {
virtualCol.remove();
}
} else {
const documentWidth = wnd.document.scrollingElement!.scrollWidth;
const colCount = documentWidth / wnd.innerWidth;
const hasOddColCount = (Math.round(colCount * 2) / 2) % 1 > 0.1;
if (hasOddColCount) {
if (virtualCol)
virtualCol.remove();
else {
virtualCol = wnd.document.createElement("div");
virtualCol.setAttribute("id", id);
virtualCol.dataset.readium = "true";
virtualCol.style.breakBefore = "column";
virtualCol.innerHTML = "&#8203;"; // zero-width space
wnd.document.body.appendChild(virtualCol);
}
const virtualCols = wnd.document.querySelectorAll("div[id^='readium-virtual-page']");
// Remove first so that we don’t end up with an incorrect scrollWidth
// Even when removing their width we risk having an incorrect scrollWidth
// so removing them entirely is the most robust solution
for (const virtualCol of virtualCols) {
virtualCol.remove();
}
const colCount = getColumnCountPerScreen(wnd);
const documentWidth = wnd.document.scrollingElement!.scrollWidth;
const neededColCount = Math.ceil(documentWidth / wnd.innerWidth) * colCount;
const totalColCount = Math.round((documentWidth / wnd.innerWidth) * colCount);
const needed = colCount === 1 ? 0 : neededColCount - totalColCount;
if (needed > 0) {
for (let i = 0; i < needed; i++) {
const virtualCol = wnd.document.createElement("div");
virtualCol.setAttribute("id", `readium-virtual-page-${ i }`);
virtualCol.dataset.readium = "true";
virtualCol.style.breakBefore = "column";
virtualCol.innerHTML = "&#8203;"; // zero-width space
wnd.document.body.appendChild(virtualCol);
}
}
}
43 changes: 0 additions & 43 deletions navigator-html-injectables/src/helpers/scrollSnapperHelper.ts

This file was deleted.

8 changes: 3 additions & 5 deletions navigator-html-injectables/src/modules/Decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@ import { Module } from "./Module";
import { rangeFromLocator } from "../helpers/locator";
import { ModuleName } from "./ModuleLibrary";
import { Rect, getClientRectsNoOverlap } from "../helpers/rect";
import { ResizeObserver as Polyfill } from '@juggle/resize-observer';
import { getProperty } from "../helpers/css";
import { ReadiumWindow } from "../helpers/dom";

// Necessary for iOS 13 and below
const ResizeObserver = window.ResizeObserver || Polyfill;
import { isDarkColor } from "../helpers/color";

export enum Width {
Wrap = "wrap", // Smallest width fitting the CSS border box.
Expand Down Expand Up @@ -254,7 +251,8 @@ class DecorationGroup {
// template.innerHTML = item.decoration.element.trim();
// TODO more styles logic

const isDarkMode = getProperty(this.wnd, "--USER__appearance") === "readium-night-on";
const isDarkMode = getProperty(this.wnd, "--USER__appearance") === "readium-night-on" ||
isDarkColor(getProperty(this.wnd, "--USER__backgroundColor"));

template.innerHTML = `
<div
Expand Down
13 changes: 12 additions & 1 deletion navigator-html-injectables/src/modules/setup/ReflowableSetup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Comms } from "../../comms/comms";
import { Setup } from "./Setup";
import { removeProperty, setProperty } from "../../helpers/css";
import { getProperties, removeProperty, setProperty, updateProperties } from "../../helpers/css";
import { ReadiumWindow } from "../../helpers/dom";

const VIEWPORT_META_TAG_ID = "readium-viewport";
Expand Down Expand Up @@ -35,6 +35,17 @@ export class ReflowableSetup extends Setup {
target: wnd
} as any); // Cheat!

comms.register("get_properties", ReflowableSetup.moduleName, (_, ack) => {
getProperties(wnd);
ack(true);
});
comms.register("update_properties", ReflowableSetup.moduleName, (data, ack) => {
// In order to keep the viewport width that is added in the setup itself,
// and don’t have EpubNavigator concerned with this, we need to add it there
(data as { [key: string]: string })["--RS__viewportWidth"] = `${ wnd.innerWidth }px`;
updateProperties(wnd, data as { [key: string]: string });
ack(true);
})
comms.register("set_property", ReflowableSetup.moduleName, (data, ack) => {
const kv = data as string[];
setProperty(wnd, kv[0], kv[1]);
Expand Down
Loading