Skip to content

Commit

Permalink
move helper functions downward
Browse files Browse the repository at this point in the history
  • Loading branch information
Casheeew committed Dec 25, 2023
1 parent 1f04a56 commit 047c581
Showing 1 changed file with 115 additions and 114 deletions.
229 changes: 115 additions & 114 deletions ext/js/dom/dom-text-scanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,120 @@ export class DOMTextScanner {

// Private

/**
* Seeks forward in a text node.
* @param {Text} textNode The text node to use.
* @param {boolean} resetOffset Whether or not the text offset should be reset.
* @returns {boolean} `true` if scanning should continue, or `false` if the scan length has been reached.
*/
_seekTextNodeForward(textNode, resetOffset) {
const nodeValue = /** @type {string} */ (textNode.nodeValue);
const nodeValueLength = nodeValue.length;
const {preserveNewlines, preserveWhitespace} = this._getWhitespaceSettings(textNode);

let done = false;
let lineHasWhitespace = this._lineHasWhitespace;
let lineHasContent = this._lineHasContent;
let content = this._content;
let offset = resetOffset ? 0 : this._offset;
let remainder = this._remainder;
let newlines = this._newlines;

while (offset < nodeValueLength) {
const char = StringUtil.readCodePointsForward(nodeValue, offset, 1);
offset += char.length;
const charAttributes = DOMTextScanner.getCharacterAttributes(char, preserveNewlines, preserveWhitespace);
/** @type {import('dom-text-scanner').SeekTextNoteDetails} */
const seekTextNoteDetails = {done, lineHasWhitespace, lineHasContent, content, offset, remainder, newlines};

({done, lineHasWhitespace, lineHasContent, content, offset, remainder, newlines} = this._checkCharacterForward(char, charAttributes, seekTextNoteDetails));
if (done) { break; }
}

this._lineHasWhitespace = lineHasWhitespace;
this._lineHasContent = lineHasContent;
this._content = content;
this._offset = offset;
this._remainder = remainder;
this._newlines = newlines;

return (remainder > 0);
}

/**
* Seeks backward in a text node.
* This function is nearly the same as _seekTextNodeForward, with the following differences:
* - Iteration condition is reversed to check if offset is greater than 0.
* - offset is reset to nodeValueLength instead of 0.
* - offset is decremented instead of incremented.
* - offset is decremented before getting the character.
* - offset is reverted by incrementing instead of decrementing.
* - content string is prepended instead of appended.
* @param {Text} textNode The text node to use.
* @param {boolean} resetOffset Whether or not the text offset should be reset.
* @returns {boolean} `true` if scanning should continue, or `false` if the scan length has been reached.
*/
_seekTextNodeBackward(textNode, resetOffset) {
const nodeValue = /** @type {string} */ (textNode.nodeValue);
const nodeValueLength = nodeValue.length;
const {preserveNewlines, preserveWhitespace} = this._getWhitespaceSettings(textNode);

let done = false;
let lineHasWhitespace = this._lineHasWhitespace;
let lineHasContent = this._lineHasContent;
let content = this._content;
let offset = resetOffset ? nodeValueLength : this._offset;
let remainder = this._remainder;
let newlines = this._newlines;

while (offset > 0) {
const char = StringUtil.readCodePointsBackward(nodeValue, offset - 1, 1);
offset -= char.length;
const charAttributes = DOMTextScanner.getCharacterAttributes(char, preserveNewlines, preserveWhitespace);

/** @type {import('dom-text-scanner').SeekTextNoteDetails} */
const seekTextNoteDetails = {done, lineHasWhitespace, lineHasContent, content, offset, remainder, newlines};

({done, lineHasWhitespace, lineHasContent, content, offset, remainder, newlines} = this._checkCharacterBackward(char, charAttributes, seekTextNoteDetails));
if (done) { break; }
}

this._lineHasWhitespace = lineHasWhitespace;
this._lineHasContent = lineHasContent;
this._content = content;
this._offset = offset;
this._remainder = remainder;
this._newlines = newlines;

return (remainder > 0);
}

/**
* Gets information about how whitespace characters are treated.
* @param {Text} textNode The text node to check.
* @returns {{preserveNewlines: boolean, preserveWhitespace: boolean}} Information about the whitespace.
* The value of `preserveNewlines` indicates whether or not newline characters are treated as line breaks.
* The value of `preserveWhitespace` indicates whether or not sequences of whitespace characters are collapsed.
*/
_getWhitespaceSettings(textNode) {
if (this._forcePreserveWhitespace) {
return {preserveNewlines: true, preserveWhitespace: true};
}
const element = DOMTextScanner.getParentElement(textNode);
if (element !== null) {
const style = window.getComputedStyle(element);
switch (style.whiteSpace) {
case 'pre':
case 'pre-wrap':
case 'break-spaces':
return {preserveNewlines: true, preserveWhitespace: true};
case 'pre-line':
return {preserveNewlines: true, preserveWhitespace: false};
}
}
return {preserveNewlines: false, preserveWhitespace: false};
}

/**
* @param {string} char
* @param {import('dom-text-scanner').CharacterAttributesEnum} charAttributes
Expand Down Expand Up @@ -220,6 +334,7 @@ export class DOMTextScanner {

return {done, lineHasWhitespace, lineHasContent, content, offset, remainder, newlines};
}

/**
* @param {string} char
* @param {import('dom-text-scanner').CharacterAttributesEnum} charAttributes
Expand Down Expand Up @@ -282,120 +397,6 @@ export class DOMTextScanner {
return {done, lineHasWhitespace, lineHasContent, content, offset, remainder, newlines};
}

/**
* Seeks forward in a text node.
* @param {Text} textNode The text node to use.
* @param {boolean} resetOffset Whether or not the text offset should be reset.
* @returns {boolean} `true` if scanning should continue, or `false` if the scan length has been reached.
*/
_seekTextNodeForward(textNode, resetOffset) {
const nodeValue = /** @type {string} */ (textNode.nodeValue);
const nodeValueLength = nodeValue.length;
const {preserveNewlines, preserveWhitespace} = this._getWhitespaceSettings(textNode);

let done = false;
let lineHasWhitespace = this._lineHasWhitespace;
let lineHasContent = this._lineHasContent;
let content = this._content;
let offset = resetOffset ? 0 : this._offset;
let remainder = this._remainder;
let newlines = this._newlines;

while (offset < nodeValueLength) {
const char = StringUtil.readCodePointsForward(nodeValue, offset, 1);
offset += char.length;
const charAttributes = DOMTextScanner.getCharacterAttributes(char, preserveNewlines, preserveWhitespace);
/** @type {import('dom-text-scanner').SeekTextNoteDetails} */
const seekTextNoteDetails = {done, lineHasWhitespace, lineHasContent, content, offset, remainder, newlines};

({done, lineHasWhitespace, lineHasContent, content, offset, remainder, newlines} = this._checkCharacterForward(char, charAttributes, seekTextNoteDetails));
if (done) { break; }
}

this._lineHasWhitespace = lineHasWhitespace;
this._lineHasContent = lineHasContent;
this._content = content;
this._offset = offset;
this._remainder = remainder;
this._newlines = newlines;

return (remainder > 0);
}

/**
* Seeks backward in a text node.
* This function is nearly the same as _seekTextNodeForward, with the following differences:
* - Iteration condition is reversed to check if offset is greater than 0.
* - offset is reset to nodeValueLength instead of 0.
* - offset is decremented instead of incremented.
* - offset is decremented before getting the character.
* - offset is reverted by incrementing instead of decrementing.
* - content string is prepended instead of appended.
* @param {Text} textNode The text node to use.
* @param {boolean} resetOffset Whether or not the text offset should be reset.
* @returns {boolean} `true` if scanning should continue, or `false` if the scan length has been reached.
*/
_seekTextNodeBackward(textNode, resetOffset) {
const nodeValue = /** @type {string} */ (textNode.nodeValue);
const nodeValueLength = nodeValue.length;
const {preserveNewlines, preserveWhitespace} = this._getWhitespaceSettings(textNode);

let done = false;
let lineHasWhitespace = this._lineHasWhitespace;
let lineHasContent = this._lineHasContent;
let content = this._content;
let offset = resetOffset ? nodeValueLength : this._offset;
let remainder = this._remainder;
let newlines = this._newlines;

while (offset > 0) {
const char = StringUtil.readCodePointsBackward(nodeValue, offset - 1, 1);
offset -= char.length;
const charAttributes = DOMTextScanner.getCharacterAttributes(char, preserveNewlines, preserveWhitespace);

/** @type {import('dom-text-scanner').SeekTextNoteDetails} */
const seekTextNoteDetails = {done, lineHasWhitespace, lineHasContent, content, offset, remainder, newlines};

({done, lineHasWhitespace, lineHasContent, content, offset, remainder, newlines} = this._checkCharacterBackward(char, charAttributes, seekTextNoteDetails));
if (done) { break; }
}

this._lineHasWhitespace = lineHasWhitespace;
this._lineHasContent = lineHasContent;
this._content = content;
this._offset = offset;
this._remainder = remainder;
this._newlines = newlines;

return (remainder > 0);
}

/**
* Gets information about how whitespace characters are treated.
* @param {Text} textNode The text node to check.
* @returns {{preserveNewlines: boolean, preserveWhitespace: boolean}} Information about the whitespace.
* The value of `preserveNewlines` indicates whether or not newline characters are treated as line breaks.
* The value of `preserveWhitespace` indicates whether or not sequences of whitespace characters are collapsed.
*/
_getWhitespaceSettings(textNode) {
if (this._forcePreserveWhitespace) {
return {preserveNewlines: true, preserveWhitespace: true};
}
const element = DOMTextScanner.getParentElement(textNode);
if (element !== null) {
const style = window.getComputedStyle(element);
switch (style.whiteSpace) {
case 'pre':
case 'pre-wrap':
case 'break-spaces':
return {preserveNewlines: true, preserveWhitespace: true};
case 'pre-line':
return {preserveNewlines: true, preserveWhitespace: false};
}
}
return {preserveNewlines: false, preserveWhitespace: false};
}

// Static helpers

/**
Expand Down

0 comments on commit 047c581

Please sign in to comment.