Skip to content

Commit

Permalink
Merge pull request #107 from asieduernest12/master
Browse files Browse the repository at this point in the history
Feat bolden newly added text nodes on dynamic sites automatically
  • Loading branch information
asieduernest12 authored Jun 3, 2022
2 parents c3e27e7 + d804139 commit 2f1d48c
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 19 deletions.
66 changes: 47 additions & 19 deletions src/ContentScript/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import Logger from '../Logger';
import NodeObserver from './observer';

const runTimeHandler = typeof browser === 'undefined' ? chrome : browser;

const FIXATION_BREAK_RATIO = 0.33;
Expand All @@ -6,7 +9,10 @@ const DEFAULT_SACCADES_INTERVAL = 0;
const DEFAULT_FIXATION_STRENGTH = 3;

// which tag's content should be ignored from bolded
const IGNORE_NODE_TAGS = ['STYLE', 'SCRIPT'];
const IGNORE_NODE_TAGS = ['STYLE', 'SCRIPT', 'BR-SPAN', 'BR-FIXATION', 'BR-BOLD'];

/** @type {NodeObserver} */
let observer;

// making half of the letters in a word bold
function highlightText(sentenceText) {
Expand Down Expand Up @@ -40,7 +46,7 @@ function makeFixations(/** @type string */ textContent) {

function parseNode(/** @type Element */ node) {
// some websites add <style>, <script> tags in the <body>, ignore these tags
if (IGNORE_NODE_TAGS.includes(node.parentElement.tagName)) {
if (!node?.parentElement?.tagName || IGNORE_NODE_TAGS.includes(node.parentElement.tagName)) {
return;
}

Expand All @@ -62,28 +68,50 @@ function parseNode(/** @type Element */ node) {
if (node.hasChildNodes()) [...node.childNodes].forEach(parseNode);
}

const ToggleReading = (enableReading) => {
console.time('ToggleReading-Time');
const boldedElements = document.getElementsByTagName('br-bold');
function mutationCallback(/** @type MutationRecord[] */ mutationRecords) {
Logger.logInfo('mutationCallback fired ', mutationRecords.length);
mutationRecords.forEach(({ type, addedNodes }) => {
if (type !== 'childList') return;

if (boldedElements.length < 1) {
addStyles();
[...document.body.children].forEach(parseNode);
}
addedNodes?.forEach(parseNode);
});
}

if (document.body.classList.contains('br-bold') || enableReading === false) {
document.body.classList.remove('br-bold');
console.timeEnd('ToggleReading-Time');
return;
}
const ToggleReading = (enableReading) => {
const endTimer = Logger.logTime('ToggleReading-Time');
try {
const boldedElements = document.getElementsByTagName('br-bold');

if (!document.body.classList.contains('br-bold')) {
document.body.classList.add('br-bold');
}
if (boldedElements.length < 1) {
addStyles();
}

if (enableReading) document.body.classList.add('br-bold');
if (document.body.classList.contains('br-bold') || enableReading === false) {
document.body.classList.remove('br-bold');
observer.destroy();
observer = null;
return;
}

console.timeEnd('ToggleReading-Time');
/**
* add .br-bold if it was not present or if enableReading is true
* enableReading = true means add .br-bold to document.body when a page loads
*/
if (!document.body.classList.contains('br-bold') || enableReading) {
document.body.classList.add('br-bold');
[...document.body.children].forEach(parseNode);

/** make an observer if one does not exist and .br-bold is present on body/active */
if (!observer) {
observer = new NodeObserver(document.body, null, mutationCallback);
observer.observe();
}
}
} catch (error) {
Logger.logError(error);
} finally {
endTimer();
}
};

const onChromeRuntimeMessage = (message, sender, sendResponse) => {
Expand Down
29 changes: 29 additions & 0 deletions src/ContentScript/observer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export default class NodeObserver {
#DEFAULT_MUTATION_OPTIONS = { childList: true, subtree: true };

/** @type MutationObserver */
#observer;

/** @type MutationCallback */
#callback;

/** @type OberverOptions */
#options;

/** @type Node */
#target;

constructor(target, options, /** @type MutationCallback */ callback) {
this.#observer = new MutationObserver(callback);
this.#options = options ?? this.#DEFAULT_MUTATION_OPTIONS;
this.#target = target;
}

observe() {
this.#observer.observe(this.#target, this.#options);
}

destroy() {
this.#observer.disconnect();
}
}
40 changes: 40 additions & 0 deletions src/Logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
*
* provide development utility functions for reporting errors, logging data and logging time
*/

/* eslint-disable no-console */
export default class Logger {
static #isProductionEnv = () => process.env.NODE_ENV === 'production';

static logError = (error) => {
if (this.#isProductionEnv()) return;
console.error(error);
};

/**
*
* @param {...any} data
* @returns {void}
*/
static logInfo = (...data) => {
if (this.#isProductionEnv()) return;

console.log(...data);
};

/**
*
* @param {String} label
* @returns {Function} end and display time when called in non production environment
*/
static logTime = (label) => {
if (this.#isProductionEnv()) {
return () => {
// no-op}
};
}
console.time(label);
return () => console.timeEnd(label);
};
}

0 comments on commit 2f1d48c

Please sign in to comment.