diff --git a/src/lib/Documentation/HtmlDocuments.md b/src/lib/Documentation/HtmlDocuments.md new file mode 100644 index 000000000..c35d0a330 --- /dev/null +++ b/src/lib/Documentation/HtmlDocuments.md @@ -0,0 +1,258 @@ +# HTML Documents +Create HTML webpages and display them on the stage! + +## Blocks + +```scratch +create new page named [my-page] :: #e34f26 +``` + +Create a new blank page +(Clicking this after you have already made a page with that name will clear all content and reset all display settings) + +--- + +```scratch +clear content of [my-page] :: #e34f26 +``` + +Clear HTML content of the page, but keep display settings + +--- + +```scratch +all pages :: #e34f26 reporter +``` + +Returns an array of all created pages + +--- + +```scratch +[my-page] html [code v] :: #e34f26 reporter +``` + +Based on the dropdown: +* **code:** Returns the html code of the page +* **preview:** Returns a visual preview of the page +Both options return the same value, just in different visual forms + +--- + +```scratch +display page [my-page] :: #e34f26 +``` + +Display the page on the stage + +--- + +```scratch +hide page [my-page] :: #e34f26 +``` + +Hide the page + +--- + +```scratch +hide all pages :: #e34f26 +``` + +Hide all pages + +--- + +```scratch +current pages displayed:: #e34f26 reporter +``` + +Returns an array of all pages currently displayed on the stage + +--- + +```scratch +add [div v] if [new-el] to [my-page] { +}:: #e34f26 +``` + +Add an element to the page. These elements can have children, like ```div``` and ```h1``` + +--- + +```scratch +add [input v] if [new-el] to [my-page]:: #e34f26 +``` + +Add a self-closing element to the page. These elements cannot have children, like ```input``` and ```img``` + +--- + +```scratch +add [hr v] to [my-page]:: #e34f26 +``` + +Add a self-closing unidentified element to the page. Only ```hr``` and ```br``` elements can be unidentified. iF an element is unidentified it cannot be removed, styled, or accessed alone. + +--- + +```scratch +remove element with id [new-el] from [my-page]:: #e34f26 +``` + +Remove an element from the page. If it has children, they will be removed, too. + +--- + +```scratch +set [class v] of [new-el] to [new-class] in [my-page]:: #e34f26 +``` + +Set an attribute for an element + +--- + +```scratch +change [new-el] in [my-page] to { +}:: #e34f26 +``` + +Change the inner HTML, or content, of an element. Not used for self-closing elements. + +--- + +```scratch +set (color v) for [id v] [new-el] to [red] in [my-page]:: #2965f1 +``` + +Set a CSS property + +--- + +```scratch +get (color v) for [id v] [new-el] in [my-page]:: #2965f1 reporter +``` + +Get the defined property of an element + +--- + +```scratch +clear styling for [id v] [new-el] in [my-page]:: #2965f1 +``` + +Clear the styling for a certain selector + +--- + +```scratch +clear styling of [my-page]:: #2965f1 +``` + +Clear all styling in the page + +--- + +```scratch +when listener for [new-el] activated in [my-page]:: #e34f26 hat +``` + +Hat is started when the event listener is triggered + +--- + +```scratch +add event listener [click v] for [new-el] n [my-page]:: #e34f26 +``` + +Add an event listener for an element. Use this after the element has been added. + +--- + +```scratch +remove event listener from [new-el] in [my-page]:: #e34f26 +``` + +Remove the event listener from the element + +--- + +```scratch +listener of [new-el] in [my-page]:: #e34f26 reporter +``` + +Returns the current listener attached to the element + +--- + +```scratch +all elements in [my-page]:: #e34f26 reporter +``` + +Returns an array of all elements in the page + +--- + +```scratch +[inner HTML v] in [my-page]:: #e34f26 reporter +``` + +Returns a value based on the dropdown: +* **inner HTML:** The html contnt inside of the element +* **text content:** The text content inside of the element +* **children:** An array of all elements inside of the element +* **parent element:** The element's parent +* **tag name:** The element's tag name +* **value:** The value of the element, if an input +* **checked:** The status of an element, if a checkbox input +* **class list:** The classes of an element +* **offset width:** Thw width of an element when displayed +* **offset height:** Thw height of an element when displayed +* **scroll width:** Thw scroll width of an element when displayed +* **scroll height:** Thw scroll height of an element when displayed +* **disabled:** If the inout is disabled + +--- + +```scratch +move [my-page] to x: [50] y: [50]:: #e34f26 +``` + +Move the page to a different location on the stage + +--- + +```scratch +resize [my-page] to x: [50] y: [50]:: #e34f26 +``` + +Resize the page + +--- + +```scratch +set [my-page] display settings to stage size :: #e34f26 +``` + +Automatically set the display settings to fit the stage size + +--- + +```scratch +[x position v] of [my-page] :: #e34f26 reporter +``` + +Returns the page display settings. Based on the dropdown: +* **x position:** The x position of the page +* **y position:** The y position of the page +* **width:** The width of the page +* **height:** The height of the page + +--- + +```scratch +[width v] of the stage:: #e34f26 reporter +``` + +Get the width or height of the stage in pixels + diff --git a/src/lib/Documentation/pages.js b/src/lib/Documentation/pages.js index 1fbb683a2..9ba6d59a7 100644 --- a/src/lib/Documentation/pages.js +++ b/src/lib/Documentation/pages.js @@ -42,6 +42,8 @@ import ProjectInterfaces from "./ProjectInterfaces.md?raw"; // Date Format V2 import DateFormatV2 from "./DateFormatV2.md?raw"; +// HTML Documents +import HTMLDocuments from "./HtmlDocuments.md?raw"; // ODE import ODE from "./ODE.md?raw"; @@ -84,6 +86,10 @@ export default { // Project Interfaces "ProjectInterfaces": ProjectInterfaces, + "DateFormatV2": DateFormatV2 + + // HTML Documents + "HTMLDocuments": HTMLDocuments, "DateFormatV2": DateFormatV2, // ODE diff --git a/src/lib/extensions.js b/src/lib/extensions.js index 77b887d29..7dc2ee88b 100644 --- a/src/lib/extensions.js +++ b/src/lib/extensions.js @@ -338,6 +338,15 @@ export default [ banner: "NamelessCat/corsproxy.avif", creator: "NamelessCat", }, + { + name: "HTML Documents", + description: "Create HTML webpages and display them on the stage.", + code: "ScrTwPm/htmldocuments.js", + banner: "ScrTwPm/htmldocs.png", + creator: "ScrTwPm", + documentation: "HTMLDocuments", + isGitHub: true, + }, { name: "Translation Keys", description: "Use translation keys in your projects for multi-language support", diff --git a/static/extensions/ScrTwPm/htmldocuments.js b/static/extensions/ScrTwPm/htmldocuments.js new file mode 100644 index 000000000..37a76d50a --- /dev/null +++ b/static/extensions/ScrTwPm/htmldocuments.js @@ -0,0 +1,2633 @@ +(function (Scratch) { + 'use strict'; + + const dom = new DOMParser() + const toAString = new XMLSerializer() + + class PrevHTML { + constructor(html) { + this.customId = "scrtwpmhtmldocuments_prevhtml" + this.html = html + } + toString() { + return this.html + } + toReporterContent() { + let wrap = document.createElement('iframe') + wrap.setAttribute("srcdoc", this.html) + wrap.style.height = "95%" + wrap.style.width = "95%" + return wrap; + } + } + + + class HtmlCode { + constructor(html) { + this.customId = "scrtwpmhtmldocuments_htmlcode" + this.html = html + } + toString() { + return this.html + } + toReporterContent() { + let wrap = document.createElement('div') + wrap.innerText = this.html + // wrap.style.backgroundColor = "black" + // wrap.style.color = "white" + // wrap.style.border = "solid 10px black" + wrap.style.border = "solid 10px #ffffff00" + wrap.style.backgroundColor = "#ffffff00" + wrap.style.boxSizing = "border-box" + wrap.style.fontFamily = "Consolas" + wrap.style.height = "fit-content" + wrap.style.width = "fit-content" + return wrap; + } + } + + class HTMLDocuments { + constructor(runtime) { + Scratch.vm.runtime.registerSerializer( + "scrtwpmhtmldocuments_htmlcode", + instance => ({ html: instance.html }), + instance => { + return (new HtmlCode(instance.html)) + } + ); + Scratch.vm.runtime.registerSerializer( + "scrtwpmhtmldocuments_prevhtml", + instance => ({ html: instance.html }), + instance => { + return (new PrevHTML(instance.html)) + } + ); + + this.pages = new Map() + this.changePx = [ + "block-size", + "border-block-end-width", + "border-block-start-width", + "border-block-width", + "border-bottom-left-radius", + "border-bottom-right-radius", + "border-bottom-width", + "border-image-outset", + "border-image-width", + "border-inline-end-width", + "border-inline-start-width", + "border-inline-width", + "border-left-width", + "border-right-width", + "border-spacing", + "border-top-left-radius", + "border-top-right-radius", + "border-top-width", + "border-width", + "bottom", + "column-gap", + "column-rule-width", + "column-width", + "contain-intrinsic-block-size", + "contain-intrinsic-height", + "contain-intrinsic-inline-size", + "contain-intrinsic-size", + "contain-intrinsic-width", + "cx", + "cy", + "font-size", + "gap", + "grid-auto-columns", + "grid-auto-rows", + "grid-template-columns", + "grid-template-rows", + "height", + "inline-size", + "left", + "letter-spacing", + "margin-block-end", + "margin-block-start", + "margin-block", + "margin-bottom", + "margin-inline-end", + "margin-inline-start", + "margin-inline", + "margin-left", + "margin-right", + "margin-top", + "max-block-size", + "max-height", + "max-inline-size", + "max-width", + "min-block-size", + "min-height", + "min-inline-size", + "min-width", + "object-position", + "offset-distance", + "offset-path", + "outline-offset", + "outline-width", + "padding-block-end", + "padding-block-start", + "padding-block", + "padding-bottom", + "padding-inline-end", + "padding-inline-start", + "padding-inline", + "padding-left", + "padding-right", + "padding-top", + "perspective", + "perspective-origin", + "r", + "right", + "row-gap", + "rx", + "ry", + "scroll-margin-bottom", + "scroll-margin-left", + "scroll-margin-right", + "scroll-margin-top", + "scroll-padding-bottom", + "scroll-padding-left", + "scroll-padding-right", + "scroll-padding-top", + "shape-margin", + "tab-size", + "text-decoration-thickness", + "text-indent", + "top", + "transform-origin", + "translate", + "width", + "word-spacing", + "x", + "y" + ] + this.viewing = [] + this.runtime = runtime + } + getInfo() { + return { + id: 'scrtwpmhtmldocuments', + name: 'HTML Documents', + color1: '#e34f26', + menuIconURI: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADAklEQVRYR8WWX0hTURzHf+e6tRmaUdOGmwaRPQwpwwrESHroIbI/DxXZS6nR36fqoQejVRASQYQE/UMTKk2yhzYpqIdCKgRfIrBSNDLT/mgMN3W72909cc68h7uzP/dOXfu83O/vbNzz4dzzu/cgyDBIPf+PnWswK9KM3T1A586IAA4Hoej5t4URyDKyqEk4FLkKgoQLn30VSJ63QK41i2UtfL/C9GqqPjSSf6yhmOSMCFhvvdpnsK/szJiAzdVvRgiJsQLVJRhQ1BCYWt6xHA+LxcJyIrxHHfSqPAKlAwjRAtuLx8FgjrrjvAWkEHhPrqNRU+B37dYLoYnRS2xg/gI44L6Ngu4mWmgK/D272+Ef+NzHBjgB+doJCPV9YDUht1B/H2oKEPhWVAvgsWEInj/IaoLeNsQyhqk/Ms1zFiCIdZUsE/QKSH4Z/JORW6cm0PwW1J0xV4HpiTDIEl0KsHcN6hcwXn0KQr6V1TwamzCmBQEJYHd90S+QtasODHvqWc2TqoB57cZBy5VHJbTQI4ADPjC3fWQ1T6oCy50tl7M3bHbSQo+AFvweWHKnL2rP8AI2V/9qhNAQLdIicPcTywReQN0BhFiBHatmQDBkswGuFcXDFeSDzupkAjgUBN+pMpp1C4ztX/9E9k/vZQO8wJEtAPLsjtYQCL53Q6D1HM26BXwPmxyTHTcTvo7FhgMAP0dYnUzA17AN8PhoJOsVIPD7gH8bKpAlzn7shJzT99iYGm99CTuzpUWAkKwNlQ0oiRj8ntjvAEGXAGAMphtdAHnL2JBCIgHv8VIAOTIpew3PWYBHDoOptYdGRUB8+QDEzkaaeZTlx5IIRS+GF0BABb8J46EILCoth4LG9v8roExOWHrxfmtOeWUtG0jHCvg9YZDoeTcWW0dvBVqcF3l2s8QVUBirKZPlqZmk/8kpENhJJy5YBmtzd7thRWH0UWqWpDdXg32eqtGaTW/4Y3s8UG4e2Np6tf+YigCP5/qZ79Ovu4pIxqEA2N1DVcho7FZ+18s/56x1ML2/L6YAAAAQZGVCR0UxN0MwMUY2QkVFNEM0NUbEID3rAAAAAElFTkSuQmCC', + // blockIconURI: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADAklEQVRYR8WWX0hTURzHf+e6tRmaUdOGmwaRPQwpwwrESHroIbI/DxXZS6nR36fqoQejVRASQYQE/UMTKk2yhzYpqIdCKgRfIrBSNDLT/mgMN3W72909cc68h7uzP/dOXfu83O/vbNzz4dzzu/cgyDBIPf+PnWswK9KM3T1A586IAA4Hoej5t4URyDKyqEk4FLkKgoQLn30VSJ63QK41i2UtfL/C9GqqPjSSf6yhmOSMCFhvvdpnsK/szJiAzdVvRgiJsQLVJRhQ1BCYWt6xHA+LxcJyIrxHHfSqPAKlAwjRAtuLx8FgjrrjvAWkEHhPrqNRU+B37dYLoYnRS2xg/gI44L6Ngu4mWmgK/D272+Ef+NzHBjgB+doJCPV9YDUht1B/H2oKEPhWVAvgsWEInj/IaoLeNsQyhqk/Ms1zFiCIdZUsE/QKSH4Z/JORW6cm0PwW1J0xV4HpiTDIEl0KsHcN6hcwXn0KQr6V1TwamzCmBQEJYHd90S+QtasODHvqWc2TqoB57cZBy5VHJbTQI4ADPjC3fWQ1T6oCy50tl7M3bHbSQo+AFvweWHKnL2rP8AI2V/9qhNAQLdIicPcTywReQN0BhFiBHatmQDBkswGuFcXDFeSDzupkAjgUBN+pMpp1C4ztX/9E9k/vZQO8wJEtAPLsjtYQCL53Q6D1HM26BXwPmxyTHTcTvo7FhgMAP0dYnUzA17AN8PhoJOsVIPD7gH8bKpAlzn7shJzT99iYGm99CTuzpUWAkKwNlQ0oiRj8ntjvAEGXAGAMphtdAHnL2JBCIgHv8VIAOTIpew3PWYBHDoOptYdGRUB8+QDEzkaaeZTlx5IIRS+GF0BABb8J46EILCoth4LG9v8roExOWHrxfmtOeWUtG0jHCvg9YZDoeTcWW0dvBVqcF3l2s8QVUBirKZPlqZmk/8kpENhJJy5YBmtzd7thRWH0UWqWpDdXg32eqtGaTW/4Y3s8UG4e2Np6tf+YigCP5/qZ79Ovu4pIxqEA2N1DVcho7FZ+18s/56x1ML2/L6YAAAAQZGVCR0UxN0MwMUY2QkVFNEM0NUbEID3rAAAAAElFTkSuQmCC', + blocks: [ + + { + opcode: 'createPage', + blockType: Scratch.BlockType.COMMAND, + text: 'create new page named [PAGE]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + } + } + }, + { + opcode: 'deletePage', + blockType: Scratch.BlockType.COMMAND, + text: 'delete page named [PAGE]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + } + } + }, + { + opcode: 'clearPage', + blockType: Scratch.BlockType.COMMAND, + text: 'clear content of [PAGE]', + // notchAccepts: "htmldocuments-coolshape", + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + } + } + }, + { + opcode: 'duplicatePage', + blockType: Scratch.BlockType.COMMAND, + text: 'duplicate page [PAGE] as [PAGE2]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + PAGE2: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page-2" + } + } + }, + { + opcode: 'allPages', + blockType: Scratch.BlockType.REPORTER, + text: 'all pages', + disableMonitor: true, + }, + { + opcode: 'getHTML', + blockType: Scratch.BlockType.REPORTER, + text: '[PAGE] html [GET]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + GET: { + type: Scratch.ArgumentType.STRING, + menu: "get" + } + } + }, + // { + // opcode: 'get', + // blockType: Scratch.BlockType.REPORTER, + // text: 'get', + // }, + { blockType: Scratch.BlockType.LABEL, text: "Render HTML" }, + { + opcode: 'displayPage', + blockType: Scratch.BlockType.COMMAND, + text: 'display page [PAGE]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + } + } + }, + { + opcode: 'hidePage', + blockType: Scratch.BlockType.COMMAND, + text: 'hide page [PAGE]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + } + } + }, + { + opcode: 'hidePageAll', + blockType: Scratch.BlockType.COMMAND, + text: 'hide all pages', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + } + } + }, + { + opcode: 'current', + blockType: Scratch.BlockType.REPORTER, + text: 'current pages displayed', + disableMonitor: true + }, + { blockType: Scratch.BlockType.LABEL, text: "Element Management" }, + { + opcode: 'nestEl', + blockType: Scratch.BlockType.CONDITIONAL, + text: 'add [EL] id [ID] to [PAGE]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + ID: { + type: Scratch.ArgumentType.STRING, + defaultValue: "new-el" + }, + EL: { + type: Scratch.ArgumentType.STRING, + menu: "nest", + defaultValue: "div" + } + } + }, + { + opcode: 'noNestEl', + blockType: Scratch.BlockType.COMMAND, + text: 'add [EL] id [ID] to [PAGE]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + ID: { + type: Scratch.ArgumentType.STRING, + defaultValue: "new-el" + }, + EL: { + type: Scratch.ArgumentType.STRING, + menu: "nonest", + defaultValue: "input" + }, + } + }, + { + opcode: 'hrbr', + blockType: Scratch.BlockType.COMMAND, + text: 'add [EL] to [PAGE]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + EL: { + type: Scratch.ArgumentType.STRING, + menu: "hrbr", + defaultValue: "hr" + }, + } + }, + { + opcode: 'text', + blockType: Scratch.BlockType.COMMAND, + text: 'add text [TEXT] to [PAGE]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + TEXT: { + type: Scratch.ArgumentType.STRING, + defaultValue: "Hello World!" + }, + } + }, + { + opcode: 'removeEl', + blockType: Scratch.BlockType.COMMAND, + text: 'remove element with id [ID] from [PAGE]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + ID: { + type: Scratch.ArgumentType.STRING, + defaultValue: "new-el" + }, + } + }, + { + opcode: 'setAttr', + blockType: Scratch.BlockType.COMMAND, + text: 'set [ATTR] of [ID] to [VAL] in [PAGE]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + ID: { + type: Scratch.ArgumentType.STRING, + defaultValue: "new-el" + }, + VAL: { + type: Scratch.ArgumentType.STRING, + defaultValue: "new-class" + }, + ATTR: { + type: Scratch.ArgumentType.STRING, + defaultValue: "class", + menu: "attr" + }, + } + + }, + + + { + opcode: 'changeHTML', + blockType: Scratch.BlockType.CONDITIONAL, + text: 'change [ID] in [PAGE] to', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + ID: { + type: Scratch.ArgumentType.STRING, + defaultValue: "new-el" + }, + EL: { + type: Scratch.ArgumentType.STRING, + menu: "nonest", + defaultValue: "input" + }, + } + }, + + { blockType: Scratch.BlockType.LABEL, text: "CSS Styles" }, + + // { + // opcode: 'styleEl', + // blockType: Scratch.BlockType.CONDITIONAL, + // text: 'add style to [PAGE]', + // branchCount: 1, + // // notchAccepts: "htmldocuments-coolshape", + // branches: [ + // { accepts: "htmldocuments-coolshape2" }, + // ], + // arguments: { + // PAGE: { + // type: Scratch.ArgumentType.STRING, + // defaultValue: "my-page" + // }, + // } + // }, + { + opcode: 'property', + blockType: Scratch.BlockType.COMMAND, + text: 'set [PROPERTY] for [TYPE] [NAME] to [VALUE] in [PAGE]', + // notchAccepts: "htmldocuments-coolshape2", + arguments: { + PROPERTY: { + type: Scratch.ArgumentType.STRING, + menu: "properties", + defaultValue: "color" + }, + TYPE: { + type: Scratch.ArgumentType.STRING, + menu: "types" + }, + NAME: { + type: Scratch.ArgumentType.STRING, + defaultValue: "new-el" + }, + VALUE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "red", + }, + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page", + }, + }, + color1: "#2965f1", + color2: "#255bd9", + color3: "#255bd9", + // blockIconURI: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABOElEQVRYR2NkGGDAiGy/mu+T/3AODcGtzTJwe4e+A5gleGGeIQj+vvgMpqkaAqMOIDYEYMEPAiRFwdF57HA2NiAiIgJnYwNaaZ/A9KBxwP9/f/7c3qrACnUf/UMAOfhBgGAUEALoaSDG7i9DVYwgnI8eBTR3wLVZfGCLYIAkB4AAqaGAHgJUdwC1cwFdHVA55yPDxlMQPw6IA2C+H9oOIATwJUL0+AcBktMACCAnROukn3A2CIw6gJQQQA9+EMAQIBQFMACLCpgD0AsgEKCpA2AAX0FElgNAAN0RA+4AZIDuGOQQSOv9yHDkJqafKA4BfAA9EWIDI88ByCUfMiA6CkCA2GgARcH/f/8Z/r36AhfDBrBZDgJYBdGBqveDf4xMLESphQFcFqIDohShA1yhQ6ylyIBkDdQGAJCZFDDWLCQVAAAAEGRlQkc3OTYwRjM3Mzk1MUE0MTk1IBDo1wAAAABJRU5ErkJggg==' + }, + + { + opcode: 'getProperty', + blockType: Scratch.BlockType.REPORTER, + text: 'get [PROPERTY] of [TYPE] [NAME] in [PAGE]', + arguments: { + PROPERTY: { + type: Scratch.ArgumentType.STRING, + menu: "properties", + defaultValue: "color" + }, + TYPE: { + type: Scratch.ArgumentType.STRING, + menu: "types" + }, + NAME: { + type: Scratch.ArgumentType.STRING, + defaultValue: "new-el" + }, + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page", + }, + }, + color1: "#2965f1", + color2: "#255bd9", + color3: "#255bd9", + // blockIconURI: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABOElEQVRYR2NkGGDAiGy/mu+T/3AODcGtzTJwe4e+A5gleGGeIQj+vvgMpqkaAqMOIDYEYMEPAiRFwdF57HA2NiAiIgJnYwNaaZ/A9KBxwP9/f/7c3qrACnUf/UMAOfhBgGAUEALoaSDG7i9DVYwgnI8eBTR3wLVZfGCLYIAkB4AAqaGAHgJUdwC1cwFdHVA55yPDxlMQPw6IA2C+H9oOIATwJUL0+AcBktMACCAnROukn3A2CIw6gJQQQA9+EMAQIBQFMACLCpgD0AsgEKCpA2AAX0FElgNAAN0RA+4AZIDuGOQQSOv9yHDkJqafKA4BfAA9EWIDI88ByCUfMiA6CkCA2GgARcH/f/8Z/r36AhfDBrBZDgJYBdGBqveDf4xMLESphQFcFqIDohShA1yhQ6ylyIBkDdQGAJCZFDDWLCQVAAAAEGRlQkc3OTYwRjM3Mzk1MUE0MTk1IBDo1wAAAABJRU5ErkJggg==' + }, + + { + opcode: 'removeStyle', + blockType: Scratch.BlockType.COMMAND, + text: 'clear styling for [TYPE] [NAME] in [PAGE]', + arguments: { + TYPE: { + type: Scratch.ArgumentType.STRING, + menu: "types" + }, + NAME: { + type: Scratch.ArgumentType.STRING, + defaultValue: "new-el" + }, + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + }, + color1: "#2965f1", + color2: "#255bd9", + color3: "#255bd9", + // blockIconURI: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABOElEQVRYR2NkGGDAiGy/mu+T/3AODcGtzTJwe4e+A5gleGGeIQj+vvgMpqkaAqMOIDYEYMEPAiRFwdF57HA2NiAiIgJnYwNaaZ/A9KBxwP9/f/7c3qrACnUf/UMAOfhBgGAUEALoaSDG7i9DVYwgnI8eBTR3wLVZfGCLYIAkB4AAqaGAHgJUdwC1cwFdHVA55yPDxlMQPw6IA2C+H9oOIATwJUL0+AcBktMACCAnROukn3A2CIw6gJQQQA9+EMAQIBQFMACLCpgD0AsgEKCpA2AAX0FElgNAAN0RA+4AZIDuGOQQSOv9yHDkJqafKA4BfAA9EWIDI88ByCUfMiA6CkCA2GgARcH/f/8Z/r36AhfDBrBZDgJYBdGBqveDf4xMLESphQFcFqIDohShA1yhQ6ylyIBkDdQGAJCZFDDWLCQVAAAAEGRlQkc3OTYwRjM3Mzk1MUE0MTk1IBDo1wAAAABJRU5ErkJggg==' + }, + + { + opcode: 'removeAllStyle', + blockType: Scratch.BlockType.COMMAND, + text: 'clear styling of [PAGE]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + }, + color1: "#2965f1", + color2: "#255bd9", + color3: "#255bd9", + // blockIconURI: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABOElEQVRYR2NkGGDAiGy/mu+T/3AODcGtzTJwe4e+A5gleGGeIQj+vvgMpqkaAqMOIDYEYMEPAiRFwdF57HA2NiAiIgJnYwNaaZ/A9KBxwP9/f/7c3qrACnUf/UMAOfhBgGAUEALoaSDG7i9DVYwgnI8eBTR3wLVZfGCLYIAkB4AAqaGAHgJUdwC1cwFdHVA55yPDxlMQPw6IA2C+H9oOIATwJUL0+AcBktMACCAnROukn3A2CIw6gJQQQA9+EMAQIBQFMACLCpgD0AsgEKCpA2AAX0FElgNAAN0RA+4AZIDuGOQQSOv9yHDkJqafKA4BfAA9EWIDI88ByCUfMiA6CkCA2GgARcH/f/8Z/r36AhfDBrBZDgJYBdGBqveDf4xMLESphQFcFqIDohShA1yhQ6ylyIBkDdQGAJCZFDDWLCQVAAAAEGRlQkc3OTYwRjM3Mzk1MUE0MTk1IBDo1wAAAABJRU5ErkJggg==' + }, + + { blockType: Scratch.BlockType.LABEL, text: "Event Listeners" }, + + + { + opcode: 'eve', + blockType: Scratch.BlockType.HAT, + text: 'when listener for [ID] activated in [PAGE]', + isEdgeActivated: false, + arguments: { + ID: { + type: Scratch.ArgumentType.STRING, + defaultValue: "new-el", + // defaultValue: '{"Hello":"Item 1", "Bye":"Item 2"}' + }, + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + } + }, + { + opcode: 'addeve', + blockType: Scratch.BlockType.COMMAND, + text: 'add event listener [EVE] for [ID] in [PAGE]', + arguments: { + EVE: { type: Scratch.ArgumentType.STRING, menu: 'eves', defaultValue: 'click' }, + ID: { type: Scratch.ArgumentType.STRING, defaultValue: 'new-el' }, + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + } + }, + { + opcode: 'remeve', + blockType: Scratch.BlockType.COMMAND, + text: 'remove event listener from [ID] in [PAGE]', + arguments: { + EVE: { type: Scratch.ArgumentType.STRING, menu: 'eves', defaultValue: 'click' }, + ID: { type: Scratch.ArgumentType.STRING, defaultValue: 'new-el' }, + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + } + }, + { + opcode: 'listener', + blockType: Scratch.BlockType.REPORTER, + text: 'listener of [ID] in [PAGE]', + arguments: { + ID: { type: Scratch.ArgumentType.STRING, defaultValue: 'new-el' }, + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + } + }, + + { blockType: Scratch.BlockType.LABEL, text: "Webpage Data" }, + + { + opcode: 'allEls', + blockType: Scratch.BlockType.REPORTER, + text: 'all elements in [PAGE]', + arguments: { + EVE: { type: Scratch.ArgumentType.STRING, menu: 'eves', defaultValue: 'click' }, + ID: { type: Scratch.ArgumentType.STRING, defaultValue: 'new-el' }, + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + } + }, + { + opcode: 'dataEl', + blockType: Scratch.BlockType.REPORTER, + text: '[OPTS] of [ID] in [PAGE]', + arguments: { + EVE: { type: Scratch.ArgumentType.STRING, menu: 'eves', defaultValue: 'click' }, + ID: { type: Scratch.ArgumentType.STRING, defaultValue: 'new-el' }, + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + OPTS: { + type: Scratch.ArgumentType.STRING, + menu: "opts" + }, + } + }, + + + { blockType: Scratch.BlockType.LABEL, text: "Webpage Positioning" }, + + { + opcode: 'movePage', + blockType: Scratch.BlockType.COMMAND, + text: 'move [PAGE] to x: [X] y: [Y]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + X: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: "50" + }, + Y: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: "50" + }, + } + }, + { + opcode: 'resizePage', + blockType: Scratch.BlockType.COMMAND, + text: 'resize [PAGE] to x: [X] y: [Y]', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + X: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: "300" + }, + Y: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: "200" + }, + } + }, + { + opcode: 'resetDefault', + blockType: Scratch.BlockType.COMMAND, + text: 'set [PAGE] display settings to stage size', + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + X: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: "300" + }, + Y: { + type: Scratch.ArgumentType.NUMBER, + defaultValue: "200" + }, + } + }, + { + opcode: 'ppos', + blockType: Scratch.BlockType.REPORTER, + text: '[AXIS] of [PAGE]', + disableMonitor: true, + arguments: { + PAGE: { + type: Scratch.ArgumentType.STRING, + defaultValue: "my-page" + }, + AXIS: { + type: Scratch.ArgumentType.STRING, + menu: "axis" + }, + } + }, + { + opcode: 'spw', + blockType: Scratch.BlockType.REPORTER, + text: '[WH] of the stage', + disableMonitor: true, + arguments: { + WH: { + type: Scratch.ArgumentType.STRING, + menu: "wh" + }, + } + }, + + ], + menus: { + nonest: { + acceptReporters: false, + items: + [ + "area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "script", "source", "textarea", "track", "wbr" + ] + }, + hrbr: { + acceptReporters: false, + items: + [ + "br", "hr" + ] + }, + nest: { + acceptReporters: false, + items: + [ + "a", "abbr", "address", "article", "aside", "audio", "b", "bdi", "bdo", "blockquote", "button", "canvas", "caption", "cite", "code", "colgroup", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt", "em", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "header", "hgroup", "i", "iframe", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "menu", "meter", "nav", "object", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "section", "select", "slot", "small", "span", "strong", "sub", "summary", "sup", "table", "tbody", "td", "template", "tfoot", "th", "thead", "time", "tr", "u", "ul", "var", "video" + ] + }, + types: { + acceptReporters: false, + items: [ + { text: "id", value: "#" }, + { text: "class", value: "." }, + { text: "tag", value: "" }, + // {text: "animation", value: "@keyframes "}, + ] + }, + get: { + acceptReporters: false, + items: [ + { text: "code", value: "code" }, + { text: "preview", value: "preview" }, + ] + }, + sel: { + acceptReporters: false, + items: [ + { text: "declaration", value: "dec" }, + { text: "computed style", value: "comp" }, + ] + }, + opts: { + acceptReporters: false, + items: [ + { text: "inner HTML", value: "innerHTML" }, + { text: "text content", value: "textContent" }, + { text: "children", value: "children" }, + { text: "parent element", value: "parentElement" }, + { text: "tag name", value: "tagName" }, + // { text: "style", value: "style" }, + { text: "value", value: "value" }, + { text: "checked", value: "checked" }, + { text: "class list", value: "classList" }, + { text: "offset width", value: "offsetWidth" }, + { text: "offset height", value: "offsetHeight" }, + { text: "scroll width", value: "scrollWidth" }, + { text: "scroll height", value: "scrollHeight" }, + { text: "disabled", value: "disabled" }, + // { text: "all data of", value: "all" }, + ] + }, + properties: { + acceptReporters: true, + items: [ + + 'align-content', 'align-items', 'align-self', 'all', 'animation', 'animation-delay', 'animation-direction', 'animation-duration', 'animation-fill-mode', 'animation-iter-count', 'animation-name', 'animation-play-state', 'animation-timing-fn', 'backface-visibility', 'background', 'background-attachment', 'background-blend-mode', 'background-clip', 'background-color', 'background-image', 'background-origin', 'background-position', 'background-repeat', 'background-size', 'border', 'border-bottom', 'border-bottom-color', 'border-bottom-left-rad', 'border-bottom-right-ra', 'border-bottom-style', 'border-bottom-width', 'border-collapse', 'border-color', 'border-image', 'border-image-outset', 'border-image-repeat', 'border-image-slice', 'border-image-source', 'border-image-width', 'border-left', 'border-left-color', 'border-left-style', 'border-left-width', 'border-radius', 'border-right', 'border-right-color', 'border-right-style', 'border-right-width', 'border-spacing', 'border-style', 'border-top', 'border-top-color', 'border-top-left-radius', 'border-top-right-radius', 'border-top-style', 'border-top-width', 'border-width', 'bottom', 'box-decoration-break', 'box-shadow', 'box-sizing', 'caption-side', 'caret-color', + 'clear', 'clip', 'clip-path', 'color', 'column-count', 'column-fill', 'column-gap', 'column-rule', 'column-rule-color', 'column-rule-style', 'column-rule-width', 'column-span', 'column-width', 'columns', 'content', 'counter-increment', 'counter-reset', 'cursor', 'direction', 'display', 'empty-cells', 'filter', 'flex', 'flex-basis', 'flex-direction', 'flex-flow', 'flex-grow', 'flex-shrink', 'flex-wrap', 'float', 'font', + 'font-family', 'font-kerning', 'font-size', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'gap', 'grid', 'grid-area', 'grid-auto-columns', 'grid-auto-flow', 'grid-auto-rows', 'grid-column', 'grid-column-end', 'grid-column-gap', 'grid-column-start', 'grid-gap', 'grid-row', 'grid-row-end', 'grid-row-gap', 'grid-row-start', 'grid-template', 'grid-template-areas', 'grid-template-columns', 'grid-template-rows', 'height', 'hyphens', + 'justify-content', + 'left', 'letter-spacing', 'line-height', 'list-style', 'list-style-image', 'list-style-position', 'list-style-type', 'margin', 'margin-bottom', 'margin-left', 'margin-right', 'margin-top', 'max-height', 'max-width', + 'min-height', 'min-width', 'object-fit', 'object-position', 'opacity', 'order', 'outline', 'outline-color', 'outline-offset', 'outline-style', 'outline-width', 'overflow', 'overflow-x', 'overflow-y', 'padding', 'padding-bottom', 'padding-left', 'padding-right', 'padding-top', 'page-break-after', 'page-break-before', 'page-break-inside', 'perspective', 'perspective-origin', 'pointer-events', 'position', 'quotes', 'right', 'row-gap', 'scroll-behavior', 'table-layout', 'text-align', 'text-align-last', 'text-decoration', 'text-decoration-color', 'text-decoration-line', 'text-decoration-style', 'text-indent', 'text-justify', 'text-overflow', 'text-shadow', 'text-transform', 'top', 'transform', 'transform-origin', 'transform-style', 'transition', 'transition-delay', 'transition-duration', 'transition-property', 'transition-timing-fn', 'user-select', 'vertical-align', 'visibility', 'white-space', 'width', 'word-break', 'word-spacing', 'word-wrap', 'writing-mode', 'z-index' + + ] + }, + jsproperties: { + acceptReporters: false, + items: [ + { "text": "align-content", "value": "alignContent" }, { "text": "align-items", "value": "alignItems" }, { "text": "align-self", "value": "alignSelf" }, { "text": "all", "value": "all" }, { "text": "animation", "value": "animation" }, { "text": "animation-delay", "value": "animationDelay" }, { "text": "animation-direction", "value": "animationDirection" }, { "text": "animation-duration", "value": "animationDuration" }, { "text": "animation-fill-mode", "value": "animationFillMode" }, { "text": "animation-iter-count", "value": "animationIterCount" }, { "text": "animation-name", "value": "animationName" }, { "text": "animation-play-state", "value": "animationPlayState" }, { "text": "animation-timing-fn", "value": "animationTimingFn" }, { "text": "backface-visibility", "value": "backfaceVisibility" }, { "text": "background", "value": "background" }, { "text": "background-attachment", "value": "backgroundAttachment" }, { "text": "background-blend-mode", "value": "backgroundBlendMode" }, { "text": "background-clip", "value": "backgroundClip" }, { "text": "background-color", "value": "backgroundColor" }, { "text": "background-image", "value": "backgroundImage" }, { "text": "background-origin", "value": "backgroundOrigin" }, { "text": "background-position", "value": "backgroundPosition" }, { "text": "background-repeat", "value": "backgroundRepeat" }, { "text": "background-size", "value": "backgroundSize" }, { "text": "border", "value": "border" }, { "text": "border-bottom", "value": "borderBottom" }, { "text": "border-bottom-color", "value": "borderBottomColor" }, { "text": "border-bottom-left-rad", "value": "borderBottomLeftRad" }, { "text": "border-bottom-right-ra", "value": "borderBottomRightRa" }, { "text": "border-bottom-style", "value": "borderBottomStyle" }, { "text": "border-bottom-width", "value": "borderBottomWidth" }, { "text": "border-collapse", "value": "borderCollapse" }, { "text": "border-color", "value": "borderColor" }, { "text": "border-image", "value": "borderImage" }, { "text": "border-image-outset", "value": "borderImageOutset" }, { "text": "border-image-repeat", "value": "borderImageRepeat" }, { "text": "border-image-slice", "value": "borderImageSlice" }, { "text": "border-image-source", "value": "borderImageSource" }, { "text": "border-image-width", "value": "borderImageWidth" }, { "text": "border-left", "value": "borderLeft" }, { "text": "border-left-color", "value": "borderLeftColor" }, { "text": "border-left-style", "value": "borderLeftStyle" }, { "text": "border-left-width", "value": "borderLeftWidth" }, { "text": "border-radius", "value": "borderRadius" }, { "text": "border-right", "value": "borderRight" }, { "text": "border-right-color", "value": "borderRightColor" }, { "text": "border-right-style", "value": "borderRightStyle" }, { "text": "border-right-width", "value": "borderRightWidth" }, { "text": "border-spacing", "value": "borderSpacing" }, { "text": "border-style", "value": "borderStyle" }, { "text": "border-top", "value": "borderTop" }, { "text": "border-top-color", "value": "borderTopColor" }, { "text": "border-top-left-radius", "value": "borderTopLeftRadius" }, { "text": "border-top-right-radius", "value": "borderTopRightRadius" }, { "text": "border-top-style", "value": "borderTopStyle" }, { "text": "border-top-width", "value": "borderTopWidth" }, { "text": "border-width", "value": "borderWidth" }, { "text": "bottom", "value": "bottom" }, { "text": "box-decoration-break", "value": "boxDecorationBreak" }, { "text": "box-shadow", "value": "boxShadow" }, { "text": "box-sizing", "value": "boxSizing" }, { "text": "caption-side", "value": "captionSide" }, { "text": "caret-color", "value": "caretColor" }, { "text": "clear", "value": "clear" }, { "text": "clip", "value": "clip" }, { "text": "clip-path", "value": "clipPath" }, { "text": "color", "value": "color" }, { "text": "column-count", "value": "columnCount" }, { "text": "column-fill", "value": "columnFill" }, { "text": "column-gap", "value": "columnGap" }, { "text": "column-rule", "value": "columnRule" }, { "text": "column-rule-color", "value": "columnRuleColor" }, { "text": "column-rule-style", "value": "columnRuleStyle" }, { "text": "column-rule-width", "value": "columnRuleWidth" }, { "text": "column-span", "value": "columnSpan" }, { "text": "column-width", "value": "columnWidth" }, { "text": "columns", "value": "columns" }, { "text": "content", "value": "content" }, { "text": "counter-increment", "value": "counterIncrement" }, { "text": "counter-reset", "value": "counterReset" }, { "text": "cursor", "value": "cursor" }, { "text": "direction", "value": "direction" }, { "text": "display", "value": "display" }, { "text": "empty-cells", "value": "emptyCells" }, { "text": "filter", "value": "filter" }, { "text": "flex", "value": "flex" }, { "text": "flex-basis", "value": "flexBasis" }, { "text": "flex-direction", "value": "flexDirection" }, { "text": "flex-flow", "value": "flexFlow" }, { "text": "flex-grow", "value": "flexGrow" }, { "text": "flex-shrink", "value": "flexShrink" }, { "text": "flex-wrap", "value": "flexWrap" }, { "text": "float", "value": "float" }, { "text": "font", "value": "font" }, { "text": "font-family", "value": "fontFamily" }, { "text": "font-kerning", "value": "fontKerning" }, { "text": "font-size", "value": "fontSize" }, { "text": "font-stretch", "value": "fontStretch" }, { "text": "font-style", "value": "fontStyle" }, { "text": "font-variant", "value": "fontVariant" }, { "text": "font-weight", "value": "fontWeight" }, { "text": "gap", "value": "gap" }, { "text": "grid", "value": "grid" }, { "text": "grid-area", "value": "gridArea" }, { "text": "grid-auto-columns", "value": "gridAutoColumns" }, { "text": "grid-auto-flow", "value": "gridAutoFlow" }, { "text": "grid-auto-rows", "value": "gridAutoRows" }, { "text": "grid-column", "value": "gridColumn" }, { "text": "grid-column-end", "value": "gridColumnEnd" }, { "text": "grid-column-gap", "value": "gridColumnGap" }, { "text": "grid-column-start", "value": "gridColumnStart" }, { "text": "grid-gap", "value": "gridGap" }, { "text": "grid-row", "value": "gridRow" }, { "text": "grid-row-end", "value": "gridRowEnd" }, { "text": "grid-row-gap", "value": "gridRowGap" }, { "text": "grid-row-start", "value": "gridRowStart" }, { "text": "grid-template", "value": "gridTemplate" }, { "text": "grid-template-areas", "value": "gridTemplateAreas" }, { "text": "grid-template-columns", "value": "gridTemplateColumns" }, { "text": "grid-template-rows", "value": "gridTemplateRows" }, { "text": "height", "value": "height" }, { "text": "hyphens", "value": "hyphens" }, { "text": "justify-content", "value": "justifyContent" }, { "text": "left", "value": "left" }, { "text": "letter-spacing", "value": "letterSpacing" }, { "text": "line-height", "value": "lineHeight" }, { "text": "list-style", "value": "listStyle" }, { "text": "list-style-image", "value": "listStyleImage" }, { "text": "list-style-position", "value": "listStylePosition" }, { "text": "list-style-type", "value": "listStyleType" }, { "text": "margin", "value": "margin" }, { "text": "margin-bottom", "value": "marginBottom" }, { "text": "margin-left", "value": "marginLeft" }, { "text": "margin-right", "value": "marginRight" }, { "text": "margin-top", "value": "marginTop" }, { "text": "max-height", "value": "maxHeight" }, { "text": "max-width", "value": "maxWidth" }, { "text": "min-height", "value": "minHeight" }, { "text": "min-width", "value": "minWidth" }, { "text": "object-fit", "value": "objectFit" }, { "text": "object-position", "value": "objectPosition" }, { "text": "opacity", "value": "opacity" }, { "text": "order", "value": "order" }, { "text": "outline", "value": "outline" }, { "text": "outline-color", "value": "outlineColor" }, { "text": "outline-offset", "value": "outlineOffset" }, { "text": "outline-style", "value": "outlineStyle" }, { "text": "outline-width", "value": "outlineWidth" }, { "text": "overflow", "value": "overflow" }, { "text": "overflow-x", "value": "overflowX" }, { "text": "overflow-y", "value": "overflowY" }, { "text": "padding", "value": "padding" }, { "text": "padding-bottom", "value": "paddingBottom" }, { "text": "padding-left", "value": "paddingLeft" }, { "text": "padding-right", "value": "paddingRight" }, { "text": "padding-top", "value": "paddingTop" }, { "text": "page-break-after", "value": "pageBreakAfter" }, { "text": "page-break-before", "value": "pageBreakBefore" }, { "text": "page-break-inside", "value": "pageBreakInside" }, { "text": "perspective", "value": "perspective" }, { "text": "perspective-origin", "value": "perspectiveOrigin" }, { "text": "pointer-events", "value": "pointerEvents" }, { "text": "position", "value": "position" }, { "text": "quotes", "value": "quotes" }, { "text": "right", "value": "right" }, { "text": "row-gap", "value": "rowGap" }, { "text": "scroll-behavior", "value": "scrollBehavior" }, { "text": "table-layout", "value": "tableLayout" }, { "text": "text-align", "value": "textAlign" }, { "text": "text-align-last", "value": "textAlignLast" }, { "text": "text-decoration", "value": "textDecoration" }, { "text": "text-decoration-color", "value": "textDecorationColor" }, { "text": "text-decoration-line", "value": "textDecorationLine" }, { "text": "text-decoration-style", "value": "textDecorationStyle" }, { "text": "text-indent", "value": "textIndent" }, { "text": "text-justify", "value": "textJustify" }, { "text": "text-overflow", "value": "textOverflow" }, { "text": "text-shadow", "value": "textShadow" }, { "text": "text-transform", "value": "textTransform" }, { "text": "top", "value": "top" }, { "text": "transform", "value": "transform" }, { "text": "transform-origin", "value": "transformOrigin" }, { "text": "transform-style", "value": "transformStyle" }, { "text": "transition", "value": "transition" }, { "text": "transition-delay", "value": "transitionDelay" }, { "text": "transition-duration", "value": "transitionDuration" }, { "text": "transition-property", "value": "transitionProperty" }, { "text": "transition-timing-fn", "value": "transitionTimingFn" }, { "text": "user-select", "value": "userSelect" }, { "text": "vertical-align", "value": "verticalAlign" }, { "text": "visibility", "value": "visibility" }, { "text": "white-space", "value": "whiteSpace" }, { "text": "width", "value": "width" }, { "text": "word-break", "value": "wordBreak" }, { "text": "word-spacing", "value": "wordSpacing" }, { "text": "word-wrap", "value": "wordWrap" }, { "text": "writing-mode", "value": "writingMode" }, { "text": "z-index", "value": "zIndex" } + ] + }, + axis: { + acceptReporters: false, + items: [ + { text: "x position", value: "x" }, { text: "y position", value: "y" }, "width", "height" + ] + }, + wh: { + acceptReporters: false, + items: [ + "width", "height" + ] + }, + eves: { + acceptReporters: false, + items: [ + // Mouse & Pointer + "click", "dblclick", "mousedown", "mouseup", "mouseenter", + "mouseleave", "mousemove", "mouseover", "mouseout", "contextmenu", "wheel", + + // Keyboard + "keydown", "keyup", "keypress", + + // Form & Input + "submit", "input", "change", "focus", "blur", "reset", "invalid", + + // Window & Document + "load", "DOMContentLoaded", "beforeunload", "unload", "resize", + "scroll", "error", "visibilitychange", + + // Drag & Drop + "dragstart", "drag", "dragenter", "dragover", "dragleave", "drop", "dragend", + + // Mobile & Media + "touchstart", "touchmove", "touchend", "play" + ] + }, + attr: { + acceptReporters: false, + items: [ + "accesskey", "autocapitalize", "autofocus", "class", "contenteditable", + "dir", "draggable", "enterkeyhint", "hidden", "inert", "inputmode", + "lang", "nonce", "part", "popover", "role", "slot", "style", "tabindex", + "title", "translate", "virtualkeyboardpolicy", + "accept", "accept-charset", "action", "align", "allow", "alt", "as", + "async", "autocomplete", "autoplay", "background", "bgcolor", "border", + "capture", "charset", "checked", "cite", "color", "cols", "colspan", + "content", "controls", "coords", "crossorigin", "csp", "data", "datetime", + "decoding", "default", "defer", "disabled", "download", "enctype", "for", + "form", "formaction", "formenctype", "formmethod", "formnovalidate", + "formtarget", "headers", "height", "high", "href", "hreflang", "http-equiv", + "imagesizes", "imagesrcset", "integrity", "ismap", "kind", "label", "list", + "loading", "loop", "low", "max", "maxlength", "min", "minlength", "media", + "method", "multiple", "muted", "name", "novalidate", "open", "optimum", + "pattern", "ping", "placeholder", "playsinline", "poster", "preload", + "readonly", "referrerpolicy", "rel", "required", "reversed", "rows", + "rowspan", "sandbox", "scope", "selected", "shape", "size", "sizes", + "span", "src", "srcdoc", "srclang", "srcset", "start", "step", "target", + "type", "usemap", "value", "width", "wrap" + ] + + } + + } + }; + } + + createPage(args, util) { + if (!this.pages.has(args.PAGE)) { + if (args.PAGE !== "") { + this.pages.set(args.PAGE, new Map().set("data", new Map().set("x", 5).set("y", 5).set("width", 470).set("height", 350)).set("code", dom.parseFromString("", 'text/html')).set("eves", new Map())) + + } else { + throw new Error("Name cannot be empty") + } + } + } + + duplicatePage(args, util) { + if ((this.pages).has(args.PAGE)) { + if (!this.pages.has(args.PAGE2)) { + if (args.PAGE !== "" && args.PAGE2 !== "") { + this.pages.set(args.PAGE2, new Map().set("data", this.pages.get(args.PAGE).get("data")).set("code", this.pages.get(args.PAGE).get("code")).set("eves", this.pages.get(args.PAGE).get("eves"))) + + } else { + throw new Error("Name cannot be empty") + } + } else { + throw new Error("Page already exists") + } + } else { + throw new Error("Page does not exist") + } + } + clearPage(args, util) { + + // //if (Object.keys(this.pages).includes(args.PAGE)) { + // let pages = this.pages + + this.pages.get(args.PAGE)?.set("code", dom.parseFromString("", 'text/html')) + this.pages.get(args.PAGE)?.set("eves", new Map()) + // } + } + deletePage(args, util) { + + //if (Object.keys(this.pages).includes(args.PAGE)) { + this.pages.delete(args.PAGE) + if (this.viewing.includes(args.PAGE)) { + const elements = document.querySelectorAll(`.htmlpage.display${args.PAGE}`); + elements.forEach(el => el.remove()); + } + + // } + } + allPages() { + return (JSON.stringify(Array.from(this.pages.keys()))) + } + get() { + if (Object.keys(this.pages).includes("my-page")) { + return (JSON.stringify(this.pages["my-page"].code)) + } + } + + + displayPage(args, util) { + return new Promise((resolve, reject) => { + try { + const elements = document.querySelectorAll(`.htmlpage.display${args.PAGE}`); + elements.forEach(el => el.remove()); + const el = document.createElement("iframe"); + el.setAttribute("srcdoc", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + el.setAttribute("class", `htmlpage display${args.PAGE}`) + el.style.position = 'absolute'; + el.style.pointerEvents = 'auto'; + el.style.zIndex = '10'; + el.style.left = `${this.pages.get(args.PAGE).get("data").get("x")}px`; + el.style.top = `${this.pages.get(args.PAGE).get("data").get("y")}px`; + el.setAttribute("width", `${this.pages.get(args.PAGE).get("data").get("width")}px`) + el.setAttribute("height", `${this.pages.get(args.PAGE).get("data").get("height")}px`) + el.style.border = "1px solid black" + const container = Scratch.renderer.canvas.parentElement; + container.appendChild(el); + if (!this.viewing.includes(args.PAGE)) { + this.viewing.push(args.PAGE) + } + el.onload = () => { + for (const [key, value] of this.pages.get(args.PAGE)?.get("eves")) { + // + + el.contentDocument.querySelector(`#${key}`).addEventListener(value, () => { + const triggerText = String(key); + const triggerTexta = String(args.PAGE); + + const targetOpcode = 'scrtwpmhtmldocuments_eve'; + const vm = Scratch.vm; + + vm.runtime.targets.forEach(target => { + const blocks = target.blocks; + const scripts = blocks.getScripts(); + + scripts.forEach(rootBlockId => { + const block = blocks.getBlock(rootBlockId); + + if (block && block.opcode === targetOpcode) { + let hatValue = ''; + let hatValuea = ''; + + if (block.fields && block.fields.ID && block.fields.PAGE) { + hatValue = block.fields.ID.value; + hatValuea = block.fields.PAGE.value; + } + else if (block.inputs && block.inputs.ID && block.inputs.PAGE) { + const inputID = block.inputs.ID; + const inputPAGE = block.inputs.PAGE; + + const shadowBlockID = blocks.getBlock(inputID.shadow); + const shadowBlockPAGE = blocks.getBlock(inputPAGE.shadow); + + if (shadowBlockID && shadowBlockID.fields) { + const fieldKey = Object.keys(shadowBlockID.fields)[0]; + hatValue = shadowBlockID.fields[fieldKey]?.value || ''; + } + if (shadowBlockPAGE && shadowBlockPAGE.fields) { + const fieldKeya = Object.keys(shadowBlockPAGE.fields)[0]; + hatValuea = shadowBlockPAGE.fields[fieldKeya]?.value || ''; + } + } + + if (hatValue === triggerText && hatValuea === triggerTexta) { + vm.runtime._pushThread(rootBlockId, target); + } + } + }); + }); + } + + ) + + + } + } + } catch (error) { } + resolve(); + }); + } + + hidePageAll(args, util) { + const elements = document.querySelectorAll('.htmlpage'); + elements.forEach(el => el.remove()); + this.viewing = [] + } + + hidePage(args, util) { + const elements = document.querySelectorAll(`.htmlpage.display${args.PAGE}`); + elements.forEach(el => el.remove()); + this.viewing.splice(this.viewing.indexOf(args.PAGE), 1) + } + + noNestEl(args, util) { + if ((this.pages).has(args.PAGE)) { + if (args.ID !== "") { + if (!this.pages.get(args.PAGE)?.get("code").querySelector(`#${args.ID}`)) { + + + // + const blockContainer = util.thread.blockContainer; + const currentBlockId = util.thread.peekStack(); + const currentBlock = blockContainer.getBlock(currentBlockId); + const target = util.thread.target; + + + + let parentBlockId = "" + let parentBlock = "" + + + let childId = currentBlockId; + let blockId = target.blocks.getBlock(currentBlockId)?.parent; + + let nest = "" + const loopOpcodes = [ + 'scrtwpmhtmldocuments_nestEl', + 'scrtwpmhtmldocuments_changeHTML', + ]; + // let blockId = currentBlockId; + + + + + + + while (blockId) { + const parentBlock = target.blocks.getBlock(blockId); + // if (!parentBlock) break; + + + if (loopOpcodes.includes(parentBlock.opcode)) { + + + const substackId = parentBlock.inputs?.SUBSTACK?.block; + // const substack2Id = parentBlock.inputs?.SUBSTACK2?.block; + + // + + if (substackId === childId) { + + + parentBlockId = blockId; + + const pB = blockContainer.getBlock(parentBlockId) + + if (pB && pB.el.bin.includes(currentBlockId) && pB.el.page === args.PAGE) { + nest = pB.el.el + + + + let body = this.pages.get(args.PAGE)?.get("code").querySelector(nest === "" ? "body" : `#${nest}`) + // + let el = document.createElement(args.EL) + el.setAttribute("id", `${args.ID}`) + el = body.appendChild(el) + + return + } + + } + + + if (substackId) { + let checkId = substackId; + while (checkId) { + if (checkId === childId) { + } + checkId = target.blocks.getBlock(checkId)?.next; + } + } + + + // if (substack2Id) { + // let checkId = substack2Id; + // while (checkId) { + // if (checkId === childId) return blockId; + // checkId = target.blocks.getBlock(checkId)?.next; + // } + // } + } + + + childId = blockId; + blockId = parentBlock.parent; + } + + + + // + // + // if (currentBlock && currentBlock.parent){ + // const parentBlockId = currentBlock.parent; + // const parentBlock = blockContainer.getBlock(parentBlockId) + // if(parentBlock && parentBlock.el){ + // + // nest = parentBlock.el.el + // } + // } + // this.pages.get(args.PAGE)?.set("code", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + // + + + // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}<${args.EL} id="${args.ID}">`) + // this.pages.get(args.PAGE)?.set("code", document.createRange().createContextualFragment(this.pages.get(args.PAGE).get("code"))) + // + + + + let body = this.pages.get(args.PAGE)?.get("code").querySelector(nest === "" ? "body" : `#${nest}`) + // + let el = document.createElement(args.EL) + el.setAttribute("id", `${args.ID}`) + el = body.appendChild(el) + } else { + throw new Error(`Only one element with the id "${args.ID}" can exist in the document`) + } + } else { + throw new Error(`Element must have an id`) + + // this.pages.get(args.PAGE)?.set("code", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}<${args.EL} >`) + } + } + } + + hrbr(args, util) { + if ((this.pages).has(args.PAGE)) { + // if (args.ID !== "") { + // if (!this.pages.get(args.PAGE)?.get("code").querySelector(`#${args.ID}`)) { + + + // + const blockContainer = util.thread.blockContainer; + const currentBlockId = util.thread.peekStack(); + const currentBlock = blockContainer.getBlock(currentBlockId); + const target = util.thread.target; + + + + let parentBlockId = "" + let parentBlock = "" + + + let childId = currentBlockId; + let blockId = target.blocks.getBlock(currentBlockId)?.parent; + + let nest = "" + const loopOpcodes = [ + 'scrtwpmhtmldocuments_nestEl', + 'scrtwpmhtmldocuments_changeHTML', + ]; + // let blockId = currentBlockId; + + + + + + + while (blockId) { + const parentBlock = target.blocks.getBlock(blockId); + // if (!parentBlock) break; + + + if (loopOpcodes.includes(parentBlock.opcode)) { + + + const substackId = parentBlock.inputs?.SUBSTACK?.block; + // const substack2Id = parentBlock.inputs?.SUBSTACK2?.block; + + // + + if (substackId === childId) { + + + parentBlockId = blockId; + + const pB = blockContainer.getBlock(parentBlockId) + + if (pB && pB.el.bin.includes(currentBlockId) && pB.el.page === args.PAGE) { + nest = pB.el.el + + + + let body = this.pages.get(args.PAGE)?.get("code").querySelector(nest === "" ? "body" : `#${nest}`) + // + let el = document.createElement(args.EL) + el = body.appendChild(el) + + return + } + + } + + + if (substackId) { + let checkId = substackId; + while (checkId) { + if (checkId === childId) { + } + checkId = target.blocks.getBlock(checkId)?.next; + } + } + + + // if (substack2Id) { + // let checkId = substack2Id; + // while (checkId) { + // if (checkId === childId) return blockId; + // checkId = target.blocks.getBlock(checkId)?.next; + // } + // } + } + + + childId = blockId; + blockId = parentBlock.parent; + } + + + + // + // + // if (currentBlock && currentBlock.parent){ + // const parentBlockId = currentBlock.parent; + // const parentBlock = blockContainer.getBlock(parentBlockId) + // if(parentBlock && parentBlock.el){ + // + // nest = parentBlock.el.el + // } + // } + // this.pages.get(args.PAGE)?.set("code", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + // + + + // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}<${args.EL} id="${args.ID}">`) + // this.pages.get(args.PAGE)?.set("code", document.createRange().createContextualFragment(this.pages.get(args.PAGE).get("code"))) + // + + + + let body = this.pages.get(args.PAGE)?.get("code").querySelector(nest === "" ? "body" : `#${nest}`) + // + let el = document.createElement(args.EL) + el = body.appendChild(el) + // } else { + // throw new Error(`Only one element with the id "${args.ID}" can exist in the document`) + // } + // } else { + // throw new Error(`Element must have an id`) + + // // this.pages.get(args.PAGE)?.set("code", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + // // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}<${args.EL} >`) + // } + } + } + + nestEl(args, util) { + if ((this.pages).has(args.PAGE)) { + if (util.stackFrame.startedBranch) { + // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}`) + // this.pages.get(args.PAGE)?.set("code", document.createRange().createContextualFragment(this.pages.get(args.PAGE).get("code"))) + // + util.stackFrame.startedBranch = false; + return; + } + if (args.ID !== "") { + if (!this.pages.get(args.PAGE)?.get("code").querySelector(`#${args.ID}`)) { + const blockContainer = util.thread.blockContainer; + const currentBlockId = util.thread.peekStack(); // + const currentBlock = blockContainer.getBlock(currentBlockId); + if (!currentBlock) { + let body = this.pages.get(args.PAGE)?.get("code").querySelector("body") + // + let el = document.createElement(args.EL) + el.setAttribute("id", `${args.ID}`) + el = body.appendChild(el) + return + } + let blocksInLoop = [] + function fn() { + + const bc = util.thread.target.blocks; + + const substackInput = currentBlock.inputs.SUBSTACK; + if (!substackInput || !substackInput.block) { + + return; + } + + const branchBlockIds = []; + // Helper function to recursively collect block IDs down the chain + const scanChain = (startBlockId) => { + let nextBlockId = startBlockId; + + while (nextBlockId) { + branchBlockIds.push(nextBlockId); + + const blockInfo = blockContainer.getBlock(nextBlockId); + if (!blockInfo) break; + + // If this block is ANOTHER loop, dive inside its mouth first! + if (blockInfo.inputs && blockInfo.inputs.SUBSTACK && blockInfo.inputs.SUBSTACK.block) { + scanChain(blockInfo.inputs.SUBSTACK.block); + } + + // If it's an If-Else block, it might also have a SUBSTACK2 mouth + if (blockInfo.inputs && blockInfo.inputs.SUBSTACK2 && blockInfo.inputs.SUBSTACK2.block) { + scanChain(blockInfo.inputs.SUBSTACK2.block); + } + + // Move to the next block directly underneath + nextBlockId = blockInfo.next; + } + }; + + // Start scanning from the very first block inside your custom loop + scanChain(substackInput.block); + + blocksInLoop = branchBlockIds + + } + + fn() + + if (currentBlock) { + currentBlock.el = { + el: args.ID, + compiledScope: 'global', + bin: blocksInLoop, + page: args.PAGE + }; + } + // + + const target = util.thread.target; + + + let parentBlockId = "" + let parentBlock = "" + let nest = "" + const loopOpcodes = [ + 'scrtwpmhtmldocuments_nestEl', + 'scrtwpmhtmldocuments_changeHTML', + ]; + let blockId = currentBlockId; + while (blockId) { + const block = target.blocks.getBlock(blockId); + if (!block) break; + + if (loopOpcodes.includes(block.opcode) && block !== currentBlock) { + // blockId = block.parent; + + parentBlockId = block; + + parentBlock = blockContainer.getBlock(parentBlockId) + // const pB = blockContainer.getBlock(parentBlockId) + if (parentBlockId && parentBlockId.el.bin.includes(currentBlockId) && parentBlockId.el.page === args.PAGE) { + nest = parentBlockId.el.el + + + + let body = this.pages.get(args.PAGE)?.get("code").querySelector(nest === "" ? "body" : `#${nest}`) + // + let el = document.createElement(args.EL) + el.setAttribute("id", `${args.ID}`) + el = body.appendChild(el) + + + util.stackFrame.startedBranch = true; + util.startBranch(1); + return + } + + + } + + blockId = block.parent; // Move to the parent block [3] + + } + // + // if (currentBlock && currentBlock.parent && currentBlock.parent.el){ + // nest = currentBlock.parent.el + // } + // + // this.pages.get(args.PAGE)?.set("code", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + let body = this.pages.get(args.PAGE)?.get("code").querySelector(nest === "" ? "body" : `#${nest}`) + // + let el = document.createElement(args.EL) + el.setAttribute("id", `${args.ID}`) + el = body.appendChild(el) + // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}<${args.EL} id="${args.ID}">`) + } else { + throw new Error(`Only one element with the id "${args.ID}" can exist in the document`) + } + } else { + throw new Error(`Element must have an id`) + // this.pages.get(args.PAGE)?.set("code", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}<${args.EL} >`) + } + util.stackFrame.startedBranch = true; + util.startBranch(1, true); + } + } + + + changeHTML(args, util) { + if ((this.pages).has(args.PAGE)) { + if (util.stackFrame.startedBranch) { + // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}`) + // this.pages.get(args.PAGE)?.set("code", document.createRange().createContextualFragment(this.pages.get(args.PAGE).get("code"))) + // + return new Promise((resolve, reject) => { + if (this.viewing.includes(args.PAGE) && document.querySelector(".htmlpage")) { + try { + const elements = document.querySelectorAll(`.htmlpage.display${args.PAGE}`); + elements.forEach(el => el.remove()); + const el = document.createElement("iframe"); + el.setAttribute("srcdoc", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + el.setAttribute("class", `htmlpage display${args.PAGE}`) + el.style.position = 'absolute'; + el.style.pointerEvents = 'auto'; + el.style.zIndex = '10'; + el.style.left = `${this.pages.get(args.PAGE).get("data").get("x")}px`; + el.style.top = `${this.pages.get(args.PAGE).get("data").get("y")}px`; + el.setAttribute("width", `${this.pages.get(args.PAGE).get("data").get("width")}px`) + el.setAttribute("height", `${this.pages.get(args.PAGE).get("data").get("height")}px`) + el.style.border = "1px solid black" + const container = Scratch.renderer.canvas.parentElement; + container.appendChild(el); + if (!this.viewing.includes(args.PAGE)) { + this.viewing.push(args.PAGE) + } + el.onload = () => { + for (const [key, value] of this.pages.get(args.PAGE)?.get("eves")) { + // + + el.contentDocument.querySelector(`#${key}`).addEventListener(value, () => { + const triggerText = String(key); + const triggerTexta = String(args.PAGE); + + const targetOpcode = 'scrtwpmhtmldocuments_eve'; + const vm = Scratch.vm; + + vm.runtime.targets.forEach(target => { + const blocks = target.blocks; + const scripts = blocks.getScripts(); + + scripts.forEach(rootBlockId => { + const block = blocks.getBlock(rootBlockId); + + if (block && block.opcode === targetOpcode) { + let hatValue = ''; + let hatValuea = ''; + + if (block.fields && block.fields.ID && block.fields.PAGE) { + hatValue = block.fields.ID.value; + hatValuea = block.fields.PAGE.value; + } + else if (block.inputs && block.inputs.ID && block.inputs.PAGE) { + const inputID = block.inputs.ID; + const inputPAGE = block.inputs.PAGE; + + const shadowBlockID = blocks.getBlock(inputID.shadow); + const shadowBlockPAGE = blocks.getBlock(inputPAGE.shadow); + + if (shadowBlockID && shadowBlockID.fields) { + const fieldKey = Object.keys(shadowBlockID.fields)[0]; + hatValue = shadowBlockID.fields[fieldKey]?.value || ''; + } + if (shadowBlockPAGE && shadowBlockPAGE.fields) { + const fieldKeya = Object.keys(shadowBlockPAGE.fields)[0]; + hatValuea = shadowBlockPAGE.fields[fieldKeya]?.value || ''; + } + } + + if (hatValue === triggerText && hatValuea === triggerTexta) { + vm.runtime._pushThread(rootBlockId, target); + } + } + }); + }); + } + + ) + + + } + } + } catch (error) { } + } + resolve(); + + }); + + + } + let blocksInLoop = [] + if (args.ID !== "") { + if (this.pages.get(args.PAGE)?.get("code").querySelector(`#${args.ID}`)) { + + + if (this.getInfo().menus.nest.items.includes(this.pages.get(args.PAGE)?.get("code").querySelector(`#${args.ID}`).tagName.toLowerCase())) { + const blockContainer = util.thread.blockContainer; + const currentBlockId = util.thread.peekStack(); // + const currentBlock = blockContainer.getBlock(currentBlockId); + if (!currentBlock) { + return + } + function fn() { + const bc = util.thread.target.blocks; + const currentBlock = bc.getBlock(currentBlockId); + if (!currentBlock) return; + + // 3. Find the ID of the first block inside the loop's C-shaped slot (SUBSTACK) + const substackInput = currentBlock.inputs.SUBSTACK; + if (!substackInput || !substackInput.block) { + + return; + } + + const branchBlockIds = []; + let nextBlockId = substackInput.block; + + // 4. Follow the chain of linked blocks sequentially down the branch + while (nextBlockId) { + branchBlockIds.push(nextBlockId); + + const blockInfo = bc.getBlock(nextBlockId); + // Move down to the next block inline, stopping if there are no more + nextBlockId = blockInfo ? blockInfo.next : null; + } + + // 5. Output the list of specific IDs + blocksInLoop = (branchBlockIds); + } + + fn() + + if (currentBlock) { + currentBlock.el = { + el: args.ID, + compiledScope: 'global', + bin: blocksInLoop, + page: args.PAGE + }; + } + let body = this.pages.get(args.PAGE)?.get("code").querySelector(`#${args.ID}`) + body.innerHTML = "" + // + + // const target = util.thread.target; + + + // let parentBlockId = "" + // let parentBlock = "" + // let nest = "" + // const loopOpcodes = [ + // 'scrtwpmhtmldocuments_nestEl', + // ]; + // let blockId = currentBlockId; + // while (blockId) { + // const block = target.blocks.getBlock(blockId); + // if (!block) break; + + // if (loopOpcodes.includes(block.opcode) && block !== currentBlock) { + // // blockId = block.parent; + // + // parentBlockId = block; + // + // parentBlock = blockContainer.getBlock(parentBlockId) + // nest = parentBlockId.el.el + // + + + // // let body = this.pages.get(args.PAGE)?.get("code").querySelector(nest === "" ? "body" : `#${nest}`) + // // // + // // let el = document.createElement(args.EL) + // // el.setAttribute("id", `${args.ID}`) + // // el = body.appendChild(el) + + + // util.stackFrame.startedBranch = true; + // util.startBranch(1); + // return + + + + // } + + // blockId = block.parent; // Move to the parent block [3] + + // } + // + // if (currentBlock && currentBlock.parent && currentBlock.parent.el){ + // nest = currentBlock.parent.el + // } + // + // this.pages.get(args.PAGE)?.set("code", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + // let body = this.pages.get(args.PAGE)?.get("code").querySelector(nest === "" ? "body" : `#${nest}`) + // // + // let el = document.createElement(args.EL) + // el.setAttribute("id", `${args.ID}`) + // el = body.appendChild(el) + // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}<${args.EL} id="${args.ID}">`) + } else { + const blockContainer = util.thread.blockContainer; + const currentBlockId = util.thread.peekStack(); // + const currentBlock = blockContainer.getBlock(currentBlockId); + if (currentBlock) { + currentBlock.el = { + el: args.ID, + compiledScope: 'global', + bin: blocksInLoop, + page: args.PAGE + }; + } + } + } else { + throw new Error(`An element with the id "${args.ID}" doesn't exist in the page`) + } + } else { + // throw new Error(`Element must have an id`) + // this.pages.get(args.PAGE)?.set("code", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}<${args.EL} >`) + } + util.stackFrame.startedBranch = true; + util.startBranch(1, true); + } + } + + text(args, util) { + //if (Object.keys(this.pages).includes(args.PAGE)) { + + // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}${text}`) + + + + if ((this.pages).has(args.PAGE)) { + // if (args.ID !== "") { + // if (!this.pages.get(args.PAGE)?.get("code").querySelector(`#${args.ID}`)) { + // + const blockContainer = util.thread.blockContainer; + const currentBlockId = util.thread.peekStack(); + const currentBlock = blockContainer.getBlock(currentBlockId); + const target = util.thread.target; + + + + let parentBlockId = "" + let parentBlock = "" + + + let childId = currentBlockId; + let blockId = target.blocks.getBlock(currentBlockId)?.parent; + + let nest = "" + const loopOpcodes = [ + 'scrtwpmhtmldocuments_nestEl', + 'scrtwpmhtmldocuments_changeHTML', + + ]; + // let blockId = currentBlockId; + + + + + + + while (blockId) { + const parentBlock = target.blocks.getBlock(blockId); + // if (!parentBlock) break; + + + if (loopOpcodes.includes(parentBlock.opcode)) { + + + const substackId = parentBlock.inputs?.SUBSTACK?.block; + // const substack2Id = parentBlock.inputs?.SUBSTACK2?.block; + + // + + if (substackId === childId) { + + + parentBlockId = blockId; + + const pB = blockContainer.getBlock(parentBlockId) + + if (pB && pB.el.bin.includes(currentBlockId) && pB.el.page === args.PAGE) { + nest = pB.el.el + + + let body = this.pages.get(args.PAGE)?.get("code").querySelector(nest === "" ? "body" : `#${nest}`) + // + + let text = document.createRange().createContextualFragment(args.TEXT) + let elements = text.querySelectorAll(`script`); + elements.forEach(el => el.remove()); + text = toAString.serializeToString(text) + body.innerHTML += text + + + return + } + } + + + if (substackId) { + let checkId = substackId; + while (checkId) { + if (checkId === childId) { + } + checkId = target.blocks.getBlock(checkId)?.next; + } + } + + // if (substack2Id) { + // let checkId = substack2Id; + // while (checkId) { + // if (checkId === childId) return blockId; + // checkId = target.blocks.getBlock(checkId)?.next; + // } + // } + } + childId = blockId; + blockId = parentBlock.parent; + } + // + // + // if (currentBlock && currentBlock.parent){ + // const parentBlockId = currentBlock.parent; + // const parentBlock = blockContainer.getBlock(parentBlockId) + // if(parentBlock && parentBlock.el){ + // + // nest = parentBlock.el.el + // } + // } + // this.pages.get(args.PAGE)?.set("code", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + // + + + // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}<${args.EL} id="${args.ID}">`) + // this.pages.get(args.PAGE)?.set("code", document.createRange().createContextualFragment(this.pages.get(args.PAGE).get("code"))) + // + // } else { + // throw new Error(`Only one element with the id "${args.ID}" can exist in the document`) + // } + // } else { + // throw new Error(`Element must have an id`) + + // // this.pages.get(args.PAGE)?.set("code", toAString.serializeToString(this.pages.get(args.PAGE).get("code"))) + // // this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}<${args.EL} >`) + // } + + let body = this.pages.get(args.PAGE)?.get("code").querySelector(nest === "" ? "body" : `#${nest}`) + // + + let text = document.createRange().createContextualFragment(args.TEXT) + let elements = text.querySelectorAll(`script`); + elements.forEach(el => el.remove()); + text = toAString.serializeToString(text) + body.innerHTML += text + + } + + + + // } + } + + removeEl(args, util) { + //if (Object.keys(this.pages).includes(args.PAGE)) { + if (this.pages.get(args.PAGE)?.get("code").querySelector(`#${args.ID}`)) { + + + if (this.pages.get(args.PAGE)?.get("code").querySelector(`#${args.ID}`)) { + let el = this.pages.get(args.PAGE)?.get("code").querySelector(`#${args.ID}`) + // + el.remove() + } + + + } + // } + + } + + styleEl(args, util) { + //if (Object.keys(this.pages).includes(args.PAGE)) { + + + if (util.stackFrame.startedBranch) { + this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}`) + + util.stackFrame.startedBranch = false; + return; + } + + const blockContainer = util.thread.blockContainer; + const currentBlockId = util.thread.peekStack(); // + const currentBlock = blockContainer.getBlock(currentBlockId); + if (currentBlock) { + currentBlock.stylePage = { + page: args.PAGE, + compiledScope: 'global', + }; + } + this.pages.get(args.PAGE)?.set("code", `${this.pages.get(args.PAGE)?.get("code")}` + + // util.stackFrame.startedBranch = false; + // return; + // } + // //do before + // const blockContainer = util.thread.blockContainer; + // const currentBlockId = util.thread.peekStack(); // + // const currentBlock = blockContainer.getBlock(currentBlockId); + // if (currentBlock) { + // currentBlock.stylePage = { + // page: args.PAGE, + // compiledScope: 'global', + // }; + + // this.pages[args.PAGE].code += `