Skip to content

Commit

Permalink
Merge pull request #181 from ator-dev/elements-isolate
Browse files Browse the repository at this point in the history
Make modules handle their elements (incl. styles)
  • Loading branch information
ator-dev authored Sep 7, 2024
2 parents f5d78a2 + 3325d01 commit 5422b73
Show file tree
Hide file tree
Showing 17 changed files with 329 additions and 266 deletions.
21 changes: 5 additions & 16 deletions src/content.mts
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,6 @@ const startHighlighting = (
);
};

/**
* Inserts a uniquely identified CSS stylesheet to perform all extension styling.
*/
const styleElementsInsert = () => {
if (!document.getElementById(EleID.DRAW_CONTAINER)) {
const container = document.createElement("div");
container.id = EleID.DRAW_CONTAINER;
document.body.insertAdjacentElement("afterend", container);
}
};

// TODO decompose this horrible generator function
/**
* Returns a generator function to consume individual command objects and produce their desired effect.
Expand Down Expand Up @@ -254,7 +243,7 @@ interface TermAppender<Async = true> {
}
const termsOld: ReadonlyArray<MatchTerm> = [ ...terms ];
terms = termsNew;
styleManager.updateStyle(terms, termTokens, hues, highlighter);
styleManager.updateStyle(terms, termTokens, hues);
updateToolbar(termsOld, terms, null, getToolbar(), commands);
// Give the interface a chance to redraw before performing highlighting.
setTimeout(() => {
Expand All @@ -270,7 +259,7 @@ interface TermAppender<Async = true> {
} else {
terms = terms.slice(0, termIndex).concat(terms.slice(termIndex + 1));
}
styleManager.updateStyle(terms, termTokens, hues, highlighter);
styleManager.updateStyle(terms, termTokens, hues);
updateToolbar(termsOld, terms, { term, termIndex }, getToolbar(), commands);
// Give the interface a chance to redraw before performing highlighting.
setTimeout(() => {
Expand All @@ -280,7 +269,7 @@ interface TermAppender<Async = true> {
appendTerm: term => {
const termsOld: ReadonlyArray<MatchTerm> = [ ...terms ];
terms = terms.concat(term);
styleManager.updateStyle(terms, termTokens, hues, highlighter);
styleManager.updateStyle(terms, termTokens, hues);
updateToolbar(termsOld, terms, { term, termIndex: termsOld.length }, getToolbar(), commands);
// Give the interface a chance to redraw before performing highlighting.
setTimeout(() => {
Expand Down Expand Up @@ -351,7 +340,6 @@ interface TermAppender<Async = true> {
if (queuingPromise) {
await queuingPromise;
}
styleElementsInsert();
if (message.highlighter !== undefined) {
highlighter.removeEngine();
highlighter.signalPaintEngineMethod(message.highlighter.paintEngine.method);
Expand Down Expand Up @@ -441,7 +429,8 @@ interface TermAppender<Async = true> {
if (messageQueue.length === 1) {
sendBackgroundMessage({ initializationGet: true }).then(initMessage => {
if (!initMessage) {
assert(false, "not initialized, so highlighting remains inactive", "no init response was received");
assert(false, "not initialized, so highlighting remains inactive",
"no init response was received");
return;
}
const initialize = () => {
Expand Down
7 changes: 2 additions & 5 deletions src/modules/common.mts
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,11 @@ const compatibility = new Compatibility();
const [ Z_INDEX_MIN, Z_INDEX_MAX ] = [ -(2**31), 2**31 - 1 ];

enum EleID {
STYLE_PAINT = "markmysearch--style-paint",
STYLE_PAINT_SPECIAL = "markmysearch--style-paint-special",
BAR = "markmysearch--bar",
MARKER_GUTTER = "markmysearch--markers",
DRAW_CONTAINER = "markmysearch--draw-container",
DRAW_ELEMENT = "markmysearch--draw",
ELEMENT_CONTAINER_SPECIAL = "markmysearch--element-container-special",
INPUT = "markmysearch--input",
DRAW_ELEMENT = "markmysearch--draw-",
INPUT = "markmysearch--input-",
}

enum EleClass {
Expand Down
16 changes: 2 additions & 14 deletions src/modules/highlight/engine-manager.mts
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,6 @@ class EngineManager implements AbstractEngineManager {
this.#updateTermStatus = updateTermStatus;
}

readonly getCSS = {
misc: (): string => (
this.#engineData?.engine.getCSS.misc() ?? ""
),
termHighlights: (): string => (
this.#engineData?.engine.getCSS.termHighlights() ?? ""
),
termHighlight: (terms: ReadonlyArray<MatchTerm>, hues: ReadonlyArray<number>, termIndex: number): string => (
this.#engineData?.engine.getCSS.termHighlight(terms, hues, termIndex) ?? ""
),
};

getTermBackgroundStyle (colorA: string, colorB: string, cycle: number): string {
return this.#engineData?.engine.getTermBackgroundStyle(colorA, colorB, cycle) ?? "";
}
Expand Down Expand Up @@ -127,7 +115,7 @@ class EngineManager implements AbstractEngineManager {
async setEngine (preference: Engine) {
const highlighting = this.#highlighting;
if (highlighting && this.#engineData) {
this.#engineData.engine.endHighlighting();
this.#engineData.engine.deactivate();
}
this.#engineData = await this.constructAndLinkEngineData(compatibility.highlighting.engineToUse(preference));
}
Expand Down Expand Up @@ -232,7 +220,7 @@ class EngineManager implements AbstractEngineManager {

removeEngine () {
if (this.#highlighting && this.#engineData) {
this.#engineData.engine.endHighlighting();
this.#engineData.engine.deactivate();
}
this.#engineData = null;
}
Expand Down
16 changes: 3 additions & 13 deletions src/modules/highlight/engine.mts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ interface AbstractEngine extends Highlighter {
readonly terms: RContainer<ReadonlyArray<MatchTerm>>;
readonly hues: RContainer<ReadonlyArray<number>>;

readonly deactivate: () => void

readonly addHighlightingUpdatedListener: (listener: Generator) => void

readonly getHighlightedElements: () => Iterable<HTMLElement>
Expand All @@ -24,21 +26,9 @@ interface AbstractEngine extends Highlighter {
interface Highlighter extends HighlighterCSSInterface, HighlightingInterface {}

interface HighlighterCSSInterface {
readonly getCSS: EngineCSS

readonly getTermBackgroundStyle: (colorA: string, colorB: string, cycle: number) => string
}

type EngineCSS = Readonly<{
misc: () => string
termHighlights: () => string
termHighlight: (
terms: ReadonlyArray<MatchTerm>,
hues: ReadonlyArray<number>,
termIndex: number,
) => string
}>

interface HighlightingInterface {
/**
* Removes previous highlighting, then highlights the document using the terms supplied.
Expand All @@ -59,6 +49,6 @@ interface HighlightingInterface {
export type {
AbstractEngine,
Highlighter,
HighlighterCSSInterface, EngineCSS,
HighlighterCSSInterface,
HighlightingInterface,
};
81 changes: 53 additions & 28 deletions src/modules/highlight/engines/element.mts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import type { FlowMutationObserver } from "/dist/modules/highlight/flow-mutation
import { highlightTags } from "/dist/modules/highlight/highlight-tags.mjs";
import * as TermCSS from "/dist/modules/highlight/term-css.mjs";
import type { MatchTerm, TermTokens, TermPatterns } from "/dist/modules/match-term.mjs";
import { EleID, EleClass, AtRuleID, elementsPurgeClass, getTermClass, createContainer } from "/dist/modules/common.mjs";
import { StyleManager } from "/dist/modules/style-manager.mjs";
import { HTMLStylesheet } from "/dist/modules/stylesheets/html.mjs";
import { EleID, EleClass, elementsPurgeClass, getTermClass, createContainer } from "/dist/modules/common.mjs";

class ElementEngine implements AbstractTreeEditEngine {
readonly class = "ELEMENT";
Expand All @@ -23,6 +25,9 @@ class ElementEngine implements AbstractTreeEditEngine {

readonly #elementsJustHighlighted = new Set<HTMLElement>();

readonly #styleManager = new StyleManager(new HTMLStylesheet(document.head));
readonly #termStyleManagerMap = new Map<MatchTerm, StyleManager<Record<never, never>>>();

readonly terms = createContainer<ReadonlyArray<MatchTerm>>([]);
readonly hues = createContainer<ReadonlyArray<number>>([]);

Expand All @@ -32,6 +37,14 @@ class ElementEngine implements AbstractTreeEditEngine {
) {
this.#termTokens = termTokens;
this.#termPatterns = termPatterns;
this.#styleManager.setStyle(`
${HIGHLIGHT_TAG} {
font: inherit !important;
border-radius: 2px !important;
visibility: visible !important;
}
`
);
{
const rejectSelector = Array.from(highlightTags.reject).join(", ");
const elements = new Set<HTMLElement>();
Expand Down Expand Up @@ -108,33 +121,9 @@ class ElementEngine implements AbstractTreeEditEngine {
}
}

readonly getCSS = {
misc: () => "",
termHighlights: () => {
return (`
${HIGHLIGHT_TAG} {
font: inherit;
border-radius: 2px;
visibility: visible;
}
.${EleClass.FOCUS_CONTAINER} {
animation: ${AtRuleID.FLASH} 1s;
}`
);
},
termHighlight: (terms: ReadonlyArray<MatchTerm>, hues: ReadonlyArray<number>, termIndex: number) => {
const term = terms[termIndex];
const hue = hues[termIndex % hues.length];
const cycle = Math.floor(termIndex / hues.length);
return (`
#${EleID.BAR} ~ body .${EleClass.FOCUS_CONTAINER} ${HIGHLIGHT_TAG}.${getTermClass(term, this.#termTokens)},
#${EleID.BAR}.${EleClass.HIGHLIGHTS_SHOWN} ~ body ${HIGHLIGHT_TAG}.${getTermClass(term, this.#termTokens)} {
background: ${this.getTermBackgroundStyle(`hsl(${hue} 100% 60% / 0.4)`, `hsl(${hue} 100% 88% / 0.4)`, cycle)};
box-shadow: 0 0 0 1px hsl(${hue} 100% 20% / 0.35);
}`
);
},
};
deactivate () {
this.endHighlighting();
}

readonly getTermBackgroundStyle = TermCSS.getDiagonalStyle;

Expand All @@ -144,17 +133,22 @@ ${HIGHLIGHT_TAG} {
termsToPurge: ReadonlyArray<MatchTerm>,
hues: ReadonlyArray<number>,
) {
// Clean up.
this.#flowMutations.unobserveMutations();
this.undoHighlights(termsToPurge);
this.removeTermStyles();
// MAIN
this.terms.assign(terms);
this.hues.assign(hues);
this.addTermStyles(terms, hues);
this.generateTermHighlightsUnderNode(termsToHighlight, document.body);
this.#flowMutations.observeMutations();
}

endHighlighting () {
this.#flowMutations.unobserveMutations();
this.undoHighlights();
this.removeTermStyles();
}

/**
Expand All @@ -179,6 +173,37 @@ ${HIGHLIGHT_TAG} {
elementsPurgeClass(EleClass.FOCUS, root);
}

addTermStyles (terms: ReadonlyArray<MatchTerm>, hues: ReadonlyArray<number>) {
for (let i = 0; i < terms.length; i++) {
const styleManager = new StyleManager(new HTMLStylesheet(document.head));
styleManager.setStyle(this.getTermCSS(terms, hues, i));
this.#termStyleManagerMap.set(terms[i], styleManager);
}
}

removeTermStyles () {
for (const styleManager of this.#termStyleManagerMap.values()) {
styleManager.deactivate();
}
this.#termStyleManagerMap.clear();
}

getTermCSS (terms: ReadonlyArray<MatchTerm>, hues: ReadonlyArray<number>, termIndex: number) {
const term = terms[termIndex];
const hue = hues[termIndex % hues.length];
const cycle = Math.floor(termIndex / hues.length);
return `
#${EleID.BAR} ~ body .${EleClass.FOCUS_CONTAINER} ${HIGHLIGHT_TAG}.${getTermClass(term, this.#termTokens)},
#${EleID.BAR}.${EleClass.HIGHLIGHTS_SHOWN} ~ body ${HIGHLIGHT_TAG}.${getTermClass(term, this.#termTokens)} {
background: ${this.getTermBackgroundStyle(
`hsl(${hue} 100% 60% / 0.4)`, `hsl(${hue} 100% 88% / 0.4)`, cycle,
)} !important;
box-shadow: 0 0 0 1px hsl(${hue} 100% 20% / 0.35) !important;
}
`
;
}

getHighlightedElements (): Iterable<HTMLElement> {
return this.getHighlightedElementsForTerms(this.terms.current);
}
Expand Down
Loading

0 comments on commit 5422b73

Please sign in to comment.