Skip to content
This repository has been archived by the owner on Sep 26, 2024. It is now read-only.

Storing DOM changes #27

Merged
merged 12 commits into from
Jun 5, 2024
1 change: 1 addition & 0 deletions apps/mocksi-lite/consts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const MOCKSI_RECORDING_STATE = "mocksi-recordingState";
export const MOCKSI_MODIFICATIONS = "mocksi-modifications";
export const COOKIE_NAME = "sessionid";

export enum RecordingState {
Expand Down
3 changes: 2 additions & 1 deletion apps/mocksi-lite/content/Popup/CreateDemo/DemoItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import TextField from "../../../common/TextField";
import { RecordingState } from "../../../consts";
import editIcon from "../../../public/edit-icon.png";
import exportIcon from "../../../public/export-icon.png";
import { loadModifications } from "../../../utils";
import { setEditorMode } from "../../content";
import type { Demo } from "./index";

Expand All @@ -26,7 +27,7 @@ const DemoItem = ({ name, customer, setState }: DemoItemProps) => {
<Button variant={Variant.icon} onClick={() => handleEdit()}>
<img src={editIcon} alt={"editIcon"} />
</Button>
<Button variant={Variant.icon} onClick={() => {}}>
<Button variant={Variant.icon} onClick={() => loadModifications()}>
Copy link

@coderabbitai coderabbitai bot Jun 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

The loadModifications function retrieves modifications from localStorage and applies them to the DOM elements. This functionality is different from setEditorMode(false), which likely had a different purpose related to editor state management.

  • loadModifications focuses on applying stored modifications to the DOM.
  • setEditorMode(false) likely managed the editor's state, such as toggling the editor mode off.

These functions serve different purposes, and replacing setEditorMode(false) with loadModifications might lead to unintended behavior if the editor state management is still required.

  • Ensure that the editor state management is handled appropriately elsewhere if setEditorMode(false) is removed.
Analysis chain

Change in onClick handler to use loadModifications.

Ensure that loadModifications is properly handling all expected scenarios since it replaces setEditorMode(false), which likely had a different purpose.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify all scenarios where `loadModifications` is used.

# Test: Search for the function usage. Expect: Proper error handling and functionality coverage.
rg --type typescript $'loadModifications'

Length of output: 75



Script:

#!/bin/bash
# Description: Verify all scenarios where `loadModifications` is used.

# Test: Search for the function usage. Expect: Proper error handling and functionality coverage.
rg --type ts 'loadModifications'

Length of output: 434



Script:

#!/bin/bash
# Description: Extract the implementation of `loadModifications` to verify its functionality.

# Test: Retrieve the function definition. Expect: Proper handling of scenarios and functionality coverage.
ast-grep --lang ts --pattern 'const loadModifications = () => { $$$ }'

Length of output: 1525

<img src={exportIcon} alt={"exportIcon"} />
</Button>
</div>
Expand Down
14 changes: 9 additions & 5 deletions apps/mocksi-lite/content/content.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ReactDOM from "react-dom/client";
import { MOCKSI_RECORDING_STATE, RecordingState } from "../consts";
import { saveModification } from "../utils";
import ContentApp from "./ContentApp";

let root: ReactDOM.Root;
Expand Down Expand Up @@ -133,6 +134,10 @@ function elementWithBorder(
document.createTextNode(newValue),
selectedText,
);
saveModification(
parentElement as HTMLElement,
parentElement?.innerHTML || parentElement?.innerText || "",
);
Comment on lines +137 to +140
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure consistent handling of DOM content. Consider using textContent for better security and consistency.

- parentElement?.innerHTML || parentElement?.innerText || "",
+ parentElement?.textContent || "",
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
saveModification(
parentElement as HTMLElement,
parentElement?.innerHTML || parentElement?.innerText || "",
);
saveModification(
parentElement as HTMLElement,
parentElement?.textContent || "",
);

parentElement?.normalize();
};

Expand All @@ -157,13 +162,12 @@ function onDoubleClickText(event: MouseEvent) {
parentElement?.normalize();
}
const targetedElement: HTMLElement = event.target as HTMLElement;
const { startOffset, endOffset } =
window.getSelection()?.getRangeAt(0) || {};
if (startOffset !== undefined && endOffset !== undefined) {
applyEditor(targetedElement, window.getSelection(), event.shiftKey);
const selection = window.getSelection();
if (selection?.toString()) {
applyEditor(targetedElement, selection, event.shiftKey);
document.getElementById("mocksiTextArea")?.focus();
} else {
console.log("ERROR! no offset detected", targetedElement);
console.log("ERROR! no selection detected", targetedElement);
}
}
}
Expand Down
61 changes: 60 additions & 1 deletion apps/mocksi-lite/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { COOKIE_NAME, MOCKSI_RECORDING_STATE, RecordingState } from "./consts";
import {
COOKIE_NAME,
MOCKSI_MODIFICATIONS,
MOCKSI_RECORDING_STATE,
RecordingState,
} from "./consts";

export const setRootPosition = (state: RecordingState) => {
const extensionRoot = document.getElementById("extension-root");
Expand All @@ -13,3 +18,57 @@ export const logout = () => {
document.cookie = `${COOKIE_NAME}=`;
localStorage.setItem(MOCKSI_RECORDING_STATE, RecordingState.UNAUTHORIZED);
};

export const saveModification = (
parentElement: HTMLElement,
newText: string,
) => {
const prevModifications = JSON.parse(
localStorage.getItem(MOCKSI_MODIFICATIONS) || "{}",
);
let keyToSave = parentElement.localName;
if (parentElement.id) {
keyToSave += `#${parentElement.id}`;
}
if (parentElement.className) {
keyToSave += `.${parentElement.className}`;
}
// here we check if the key we built is sufficient to get an unique element when querying
const elements = document.querySelectorAll(keyToSave);
if (elements.length === 1) {
localStorage.setItem(
MOCKSI_MODIFICATIONS,
JSON.stringify({ ...prevModifications, [keyToSave]: newText }),
);
} else {
// if not unique, we search for the index and put it on the key.
keyToSave += `[${[...elements].indexOf(parentElement)}]`;
localStorage.setItem(
MOCKSI_MODIFICATIONS,
JSON.stringify({ ...prevModifications, [keyToSave]: newText }),
);
}
};

export const loadModifications = () => {
const modifications = JSON.parse(
localStorage.getItem(MOCKSI_MODIFICATIONS) || "{}",
);
for (const modification of Object.entries(modifications)) {
// value here is encoded, SHOULD NOT be a security risk to put it in the innerHTML
const [querySelector, value] = modification;
const hasIndex = querySelector.match(/\[[0-9]+\]/);
if (hasIndex) {
const index: number = +hasIndex[0].replace("[", "").replace("]", "");
const elemToModify = document.querySelectorAll(
querySelector.replace(hasIndex[0], ""),
)[index];
//@ts-ignore
elemToModify.innerHTML = value;
} else {
const [elemToModify] = document.querySelectorAll(querySelector);
//@ts-ignore
elemToModify.innerHTML = value;
}
}
};
Loading