Skip to content

Commit

Permalink
New API: scratchClass
Browse files Browse the repository at this point in the history
  • Loading branch information
rgantzos committed Nov 30, 2024
1 parent e8fa05e commit 4b74d5e
Show file tree
Hide file tree
Showing 18 changed files with 130 additions and 51 deletions.
63 changes: 60 additions & 3 deletions api/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,24 @@ ScratchTools.Storage = {};
ScratchTools.Resources = {};
ste.console.log("ScratchTools API Created", "ste-main");

ScratchTools.cssFiles = [];
async function updateCSSFiles() {
let activeCSSFiles = Array.from(document.styleSheets)
.filter((sheet) => sheet.href)
.map((sheet) => sheet.href)
.filter((el) => new URL(el).host === "scratch.mit.edu");
activeCSSFiles = activeCSSFiles.filter(
(el) => !ScratchTools.cssFiles.find((e) => e.url === el)
);

for (var i in activeCSSFiles) {
ScratchTools.cssFiles.push({
url: activeCSSFiles[i],
data: await (await fetch(activeCSSFiles[i])).text(),
});
}
}

if (
window.location.href.startsWith("https://scratch.mit.edu/projects/") &&
window.location.href.includes("/editor")
Expand Down Expand Up @@ -159,6 +177,7 @@ function enableScratchToolsSelectorsMutationObserver() {
enableScratchToolsSelectorsMutationObserver();

function returnScratchToolsSelectorsMutationObserverCallbacks() {
updateCSSFiles()
Object.keys(allWaitInstances).forEach(function (key) {
var waitInstance = allWaitInstances[key];
if (!waitInstance.removed) {
Expand Down Expand Up @@ -340,6 +359,39 @@ ScratchTools.styles = {
},
};

function scratchClass(name) {
let element = document.querySelector(`[class*='${name}']`);
if (element) {
let classes = [...element.classList];
return classes.find((el) => el.includes(name));
} else {
let text = []

for (var i in ScratchTools.cssFiles) {
text.push(ScratchTools.cssFiles[i].data)
}

text = text.join("\n\n")
let classes = getClassNamesFromCSSText(text)

let relClass = classes.find((el) => el.includes(name))
return relClass
}
}

ScratchTools.getClassNamesFromCSSText = function(cssText) {
const classNames = new Set();

const classRegex = /\.([a-zA-Z0-9_-]+)\b/g;

let match;
while ((match = classRegex.exec(cssText)) !== null) {
classNames.add(match[1]);
}

return Array.from(classNames);
}

ScratchTools.waitForElements(
"ul[class*='menu_menu_'][class*='menu_right_']",
function (ul) {
Expand All @@ -351,7 +403,10 @@ ScratchTools.waitForElements(
if (!ul.querySelector(".ste-menu-full-settings")) {
var li = document.createElement("li");
li.className =
"ste-menu-full-settings menu_menu-item_3EwYA menu_hoverable_3u9dt";
"ste-menu-full-settings " +
scratchClass("menu_menu-item_") +
" " +
scratchClass("menu_hoverable_");

var div = document.createElement("div");
div.className = "settings-menu_option_3rMur";
Expand Down Expand Up @@ -391,6 +446,8 @@ async function blockliveDetection() {
Object.keys(app).find((key) => key.startsWith("__reactContainer"))
].child.stateNode.store.getState()?.scratchGui;
if (!gui?.projectState) return;
let detectBlocklive = await import("./blocklive-detection/blocklive-detect.js");
let detectBlocklive = await import(
"./blocklive-detection/blocklive-detect.js"
);
detectBlocklive.default();
}
}
22 changes: 22 additions & 0 deletions api/module.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
let allFeatures = []
let alreadyInjected = [];

function scratchClass(name) {
let element = document.querySelector(`[class*='${name}']`);
if (element) {
let classes = [...element.classList];
return classes.find((el) => el.includes(name));
} else {
let text = []

for (var i in ScratchTools.cssFiles) {
text.push(ScratchTools.cssFiles[i].data)
}

text = text.join("\n\n")
let classes = getClassNamesFromCSSText(text)

let relClass = classes.find((el) => el.includes(name))
return relClass
}
}

ScratchTools.modules.forEach(async function (script) {
var feature = await import(ScratchTools.dir + "/api/feature/index.js");
var shouldBeRun = true;
Expand All @@ -20,6 +40,7 @@ ScratchTools.modules.forEach(async function (script) {
allFeatures.push(featureGenerated)
fun.default({
feature: featureGenerated,
scratchClass,
console: {
log: function (content) {
ste.console.log(content, script.feature.id);
Expand Down Expand Up @@ -56,6 +77,7 @@ ScratchTools.injectModule = async function (script) {
allFeatures.push(featureGenerated)
fun.default({
feature: featureGenerated,
scratchClass,
console: {
log: function (content) {
ste.console.log(content, script.feature.id);
Expand Down
6 changes: 3 additions & 3 deletions features/dark-paint-editor/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default async function ({ feature, console }) {
export default async function ({ feature, console, scratchClass }) {
let isDark;

const BACKGROUND_LIGHT = "#FFFFFF";
Expand All @@ -18,10 +18,10 @@ export default async function ({ feature, console }) {
if (document.querySelector(".ste-dark-paint-btn")) return;

let button = document.createElement("div")
button.className = "button-group_button-group_2_h4y ste-dark-paint-btn"
button.className = `${scratchClass("button-group_button-group_2_")} ste-dark-paint-btn`

let span = document.createElement("span")
span.className = "button_button_u6SE2 paint-editor_button-group-button_1I1tm"
span.className = `${scratchClass("button_button_")} ${scratchClass("paint-editor_button-group-button_")}`
span.role = "button"
button.appendChild(span)

Expand Down
2 changes: 1 addition & 1 deletion features/delete-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ function checkForContextMenu() {
) {
var div = document.createElement("div");
div.className =
"react-contextmenu-item context-menu_menu-item_3cioN context-menu_menu-item-bordered_29CJG context-menu_menu-item-danger_1tJg0 scratchtools deleteall";
`react-contextmenu-item ${scratchClass("context-menu_menu-item_")} ${scratchClass("context-menu_menu-item-bordered_")} ${scratchClass("context-menu_menu-item-danger_")} scratchtools deleteall`;
div.role = "menuitem";
div.tabindex = "-1";
div.arialDisabled = "false";
Expand Down
6 changes: 3 additions & 3 deletions features/echo-effect/script.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export default function ({ feature, console }) {
export default function ({ feature, console, scratchClass }) {
ScratchTools.waitForElements(
"div[class^='sound-editor_row_'][class*='sound-editor_row-reverse_']",
function (container) {
if (container.querySelector(".ste-echo")) return;
let button = document.createElement("div");
button.className =
"icon-button_container_278u5 sound-editor_effect-button_2zuzT ste-echo";
`${scratchClass("icon-button_container_")} ${scratchClass("sound-editor_effect-button_")} ste-echo`;
button.role = "button";

feature.self.hideOnDisable(button)
Expand All @@ -20,7 +20,7 @@ export default function ({ feature, console }) {
button.appendChild(img);

let title = document.createElement("div");
title.className = "icon-button_title_36ChS";
title.className = scratchClass("icon-button_title_");
title.textContent = feature.msg("echo");
button.appendChild(title);

Expand Down
2 changes: 1 addition & 1 deletion features/go-to-parent/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ if (
if (data.remix !== undefined) {
if (data.remix.parent !== null) {
var div = document.createElement("div");
div.className = "menu-bar_menu-bar-item_oLDa- scratchtools remix";
div.className = `${scratchClass("menu-bar_menu-bar-item_")} scratchtools remix`;
div.innerHTML = `<a href="https://scratch.mit.edu/projects/${data.remix.parent}/editor" style="color: white;"><span class="button_outlined-button_1bS__ menu-bar_menu-bar-button_3IDN0 community-button_community-button_2Lo_g" role="button"><div class="button_content_3jdgj"><span>Go to Parent</span></div></span></a>`;
document.querySelectorAll("div").forEach(function (el) {
if (el.className.includes("menu-bar_main-menu_")) {
Expand Down
2 changes: 1 addition & 1 deletion features/last-key-pressed.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function addKeyPressed() {

function addKeyPressedEditor() {
var div = document.createElement("div");
div.className = "menu-bar_file-group_1_CHX scratchtools navlastkey";
div.className = `${scratchClass("menu-bar_file-group_1_")} scratchtools navlastkey`;
div.innerHTML = `
<span>No Key Pressed</span>
`;
Expand Down
10 changes: 5 additions & 5 deletions features/more-block-themes/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default async function ({ feature, console }) {
export default async function ({ feature, console, scratchClass }) {
let CIRCLE = await (await fetch(feature.self.getResource("circle"))).text();

let COLORS = document.createElement("link")
Expand Down Expand Up @@ -118,18 +118,18 @@ export default async function ({ feature, console }) {

let li = document.createElement("li");
li.dataset.id = THEMES[i].id;
li.className = "menu_menu-item_3EwYA menu_hoverable_3u9dt ste-custom";
li.className = `${scratchClass("menu_menu-item_")} ${scratchClass("menu_hoverable_")} ste-custom`;

let div = document.createElement("div");
div.className = "settings-menu_option_3rMur";
div.className = scratchClass("settings-menu_option_");

let check = document.createElement("img");
check.className = "settings-menu_check_3ssaq";
check.className = scratchClass("settings-menu_check_");
check.src = feature.self.getResource("check");

let img = document.createElement("span");
img.innerHTML = CIRCLE.replaceAll("-fill", "-circle-fill" + THEMES[i].id).replaceAll("-stroke", "-circle-stroke-" + THEMES[i].id);
img.className = "settings-menu_icon_3QaRk";
img.className = scratchClass("settings-menu_icon_");

let circleCSS = document.createElement("style");
circleCSS.textContent = css.replaceAll("-fill", "-circle-fill" + THEMES[i].id).replaceAll("-stroke", "-circle-stroke-" + THEMES[i].id)
Expand Down
8 changes: 4 additions & 4 deletions features/more-editor-fonts/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default async function ({ feature, console }) {
export default async function ({ feature, console, scratchClass }) {
let { default: openTypeDefault } = await import(
"../../libraries/opentype.js"
);
Expand Down Expand Up @@ -26,20 +26,20 @@ export default async function ({ feature, console }) {
button.currentitem = false;
button.ariaLabel = "Add Font";
button.className =
"action-menu_button_1qbot action-menu_more-button_1fMGZ ste-more-fonts-btn";
`${scratchClass("action-menu_button_")} ${scratchClass("action-menu_more-button_")} ste-more-fonts-btn`;
div.appendChild(button);

let img = Object.assign(document.createElement("img"), {
src: feature.self.getResource("more-text-icon"),
draggable: false,
className: "action-menu_more-icon_TJUQ7",
className: scratchClass("action-menu_more-icon_"),
width: 10,
});
button.appendChild(img);

let tooltip = Object.assign(document.createElement("div"), {
className:
"__react_component_tooltip place-right type-dark action-menu_tooltip_3Bkh5",
`__react_component_tooltip place-right type-dark ${scratchClass("action-menu_tooltip_")}`,
id: `ste-${id}-Add Font`,
textContent: "Add Font",
});
Expand Down
8 changes: 4 additions & 4 deletions features/more-paint-functions/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default async function ({ feature, console }) {
export default async function ({ feature, console, scratchClass }) {
function unite() {
let paper = feature.traps.getPaper();
let items = paper.project.selectedItems;
Expand Down Expand Up @@ -133,20 +133,20 @@ export default async function ({ feature, console }) {
function makeButton({ name, icon, callback }) {
let span = document.createElement("span");
span.className =
"button_button_u6SE2 labeled-icon-button_mod-edit-field_1bXYC ste-more-functions";
`${scratchClass("button_button_")} ${scratchClass("labeled-icon-button_mod-edit-field_")} ste-more-functions`;
span.role = "button";

let img = document.createElement("img");
img.src = feature.self.getResource(icon);
img.className = "labeled-icon-button_edit-field-icon_3j-Pf";
img.className = scratchClass("labeled-icon-button_edit-field-icon_");
img.alt = name;
img.title = name;
img.draggable = false;
span.appendChild(img);

let label = document.createElement("span");
label.textContent = name;
label.className = "labeled-icon-button_edit-field-title_1ZoEV";
label.className = scratchClass("labeled-icon-button_edit-field-title_");
span.appendChild(label);

span.addEventListener("click", function (e) {
Expand Down
2 changes: 1 addition & 1 deletion features/move-project-title-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ ScratchTools.waitForElements(
if (!document.querySelector(".st-new-title-input") && !document.querySelector("span[class*='menu-bar_remix-button_']")) {
var input = document.createElement("input");
input.className =
"input_input-form_l9eYg project-title-input_title-field_en5Gd menu-bar_title-field-growable_3qr4G";
`${scratchClass("input_input-form_")} ${scratchClass("project-title-input_title-field_")} ${scratchClass("menu-bar_title-field-growable_")}`;
input.value = window.newTitle || ScratchTools.Scratch.scratchGui().projectTitle;
input.placeholder = "Title";
input.style.width = "100%";
Expand Down
12 changes: 6 additions & 6 deletions features/opacity-slider/script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function ({ feature, console }) {
export default function ({ feature, console, scratchClass }) {
ScratchTools.waitForElements(".Popover-body", function (body) {
if (!feature.traps.paint().modals.fillColor) return;
if (!feature.traps.paint().selectedItems[0]) return;
Expand All @@ -11,15 +11,15 @@ export default function ({ feature, console }) {
feature.self.hideOnDisable(div);

let data = document.createElement("div");
data.className = "color-picker_row-header_173LQ";
data.className = scratchClass("color-picker_row-header_");
div.appendChild(data);

let name = document.createElement("span");
name.className = "color-picker_label-name_17igY";
name.className = scratchClass("color-picker_label-name_");
name.textContent = "Opacity";

let value = document.createElement("span");
value.className = "color-picker_label-readout_9vjb2";
value.className = scratchClass("color-picker_label-readout_");
value.textContent = Math.floor(
(feature.traps.paint().selectedItems[0]?.opacity || 1) * 100
)?.toString();
Expand All @@ -29,7 +29,7 @@ export default function ({ feature, console }) {

let slider = document.createElement("div");
slider.className =
"ste-opacity-slider-checkered slider_container_o2aIb slider_last_10jvO";
`ste-opacity-slider-checkered ${scratchClass("slider_container_")} ${scratchClass("slider_last_")}`;
div.appendChild(slider);

let sliderBg = document.createElement("div");
Expand All @@ -41,7 +41,7 @@ export default function ({ feature, console }) {

let handle = document.createElement("div");
handleSlider(handle, value);
handle.className = "ste-opacity-handle slider_handle_3f0xk";
handle.className = `ste-opacity-handle ${scratchClass("slider_handle_")}`;
handle.style.left = "124px";
if (feature.traps.paint().selectedItems[0]?.opacity) {
handle.style.left =
Expand Down
8 changes: 4 additions & 4 deletions features/paint-align/script.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
export default async function ({ feature }) {
export default async function ({ feature, scratchClass }) {
ScratchTools.waitForElements(
"div[class^='mode-tools_mod-labeled-icon-height_']",
function (row) {
if (row.querySelector(".ste-align-items")) return;

let span = document.createElement("span");
span.className =
"button_button_u6SE2 labeled-icon-button_mod-edit-field_1bXYC ste-align-items";
`${scratchClass("button_button_")} ${scratchClass("labeled-icon-button_mod-edit-field_")} ste-align-items`;
span.role = "button";

let img = document.createElement("img");
img.src = feature.self.getResource("paint-align");
img.className = "labeled-icon-button_edit-field-icon_3j-Pf";
img.className = scratchClass("labeled-icon-button_edit-field-icon_");
img.alt = feature.msg("align");
img.title = feature.msg("align");
img.draggable = false;
span.appendChild(img);

let label = document.createElement("span");
label.textContent = feature.msg("align");
label.className = "labeled-icon-button_edit-field-title_1ZoEV";
label.className = scratchClass("labeled-icon-button_edit-field-title_");
span.appendChild(label);

span.addEventListener("click", function (e) {
Expand Down
Loading

0 comments on commit 4b74d5e

Please sign in to comment.