HTML Documents Extension - #628
Conversation
✅ Preview readyYour changes are live at: https://lively-cedar-291d5d94.skr.mubilop.com/ Built from |
|
But you were right about the Python extension it didnt really add anything new. I think this does add more features that that does. I'm checking right now to see if something like this already exists but i'm pretty sure it isn't |
I see you had added a block that helps to scale appropriately (id |
|
Could you make it so that multiple pages can be displayed at once? |
Steve0Greatness
left a comment
There was a problem hiding this comment.
A bit more of a general concern, but you should put this through Prettier, because this is formatted, in my opinion, a bit badly.
| width: "470", | ||
| }, | ||
| "ids": [], | ||
| "code":"" |
There was a problem hiding this comment.
This would probably require a bit of a restructure, but there are far safer and more efficient ways to handle HTML code. Storing it as a DOM would actually be a good idea, here.
| class HTMLtoCanvas { | ||
| constructor(runtime) { | ||
| // Initialize an array holding your default dropdown menu options | ||
| this.pages = {} |
There was a problem hiding this comment.
You'll probably want to use a Map instead of just an object, since maps are more optimized to change frequently.
| if (Scratch.gui) { | ||
| Scratch.gui.getBlockly().then(ScratchBlocks => { | ||
| ScratchBlocks.BlockSvg.registerCustomNotch("htmldocuments-coolshape", | ||
| "c 2 0 3 1 4 2 l 4 4 c 1 1 4 -7 4 2 h 3 c 1 -1 2 -2 3 -3 c 1 1 2 2 3 3 l 3 0 c 0 -9 3 -1 4 -2 l 4 -4 c 1 -1 2 -2 4 -2" | ||
| ) | ||
| ScratchBlocks.BlockSvg.registerCustomNotch("htmldocuments-coolshape2", | ||
| "c 0 2 0 8 4 8 c 6 0 10 -7 14 -5 c 4 -2 8 5 14 5 c 4 0 4 -6 4 -8" | ||
| ) | ||
| }); | ||
| } |
There was a problem hiding this comment.
These currently go unused.
| const el = document.createElement("div"); | ||
| el.innerHTML = this.pages[args.PAGE].code; |
| ] | ||
| }, | ||
| attr: { | ||
| acceptReporters: false, |
There was a problem hiding this comment.
This should probably be set to true, instead of false. This would necessitate the use of a DOM, however, as the way you're currently setting attributes by their name is unsafe if you allow direct input.
| { | ||
| opcode: 'eve', | ||
| blockType: Scratch.BlockType.HAT, | ||
| text: 'When listener for [ID] activated in [PAGE]', |
There was a problem hiding this comment.
For consistency, this should start with a lowercase letter.
| this.pages[args.PAGE].code = `${this.pages[args.PAGE].code}<!--begin my style--><style>` | ||
| this.pages[page].code = `${this.pages[page].code}.htmldocumentelement${args.TYPE}element${page}${args.NAME}{${args.PROPERTY}:${value}};` | ||
| this.pages[args.PAGE].code = `${this.pages[args.PAGE].code}</style><!--end my style-->` |
There was a problem hiding this comment.
In cases like these, it's easier to read if you use += `...` instead of = `${...}...`
| this.pages[args.PAGE].data.x = 5 | ||
| this.pages[args.PAGE].data.y = 5 | ||
| console.log(this.viewing) | ||
| console.log(document.querySelector("#htmlpage")) |
There was a problem hiding this comment.
There are a few spare console logs here and there in this extension, I'd recommend removing them before this gets merged.
| 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 = ''; | ||
|
|
||
| // 1. Check if it's a Field (dropdown/fixed text) | ||
| if (block.fields && block.fields.ID && block.fields.PAGE) { | ||
| console.log(block.fields.ID.value) | ||
| hatValue = block.fields.ID.value; | ||
| hatValuea = block.fields.PAGE.value; | ||
| } | ||
| // 2. Check if it's an Input (text bubble) | ||
| else if (block.inputs && block.inputs.ID) { | ||
| const input = block.inputs.ID; | ||
| const inputa = block.inputs.PAGE; | ||
| // Dig into the 'shadow' block which holds the text value | ||
| const shadowBlock = blocks.getBlock(input.shadow); | ||
| const shadowBlocka = blocks.getBlock(inputa.shadow); | ||
| if (shadowBlock && shadowBlock.fields && shadowBlock.fields.TEXT && shadowBlocka && shadowBlocka.fields && shadowBlocka.fields.TEXT) { | ||
| hatValue = shadowBlock.fields.TEXT.value; | ||
| hatValuea = shadowBlocka.fields.TEXT.value; | ||
| } | ||
| } | ||
|
|
||
| // Compare and trigger | ||
| if (hatValue === triggerText && hatValuea === triggerTexta) { | ||
| vm.runtime._pushThread(rootBlockId, target); | ||
| } | ||
| } | ||
| }); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
runtime.startHats has the functionality to start hat blocks dependent on their values, already.
|
thanks for the feedback! i'll get to it. |
Well, there's Project Interfaces, which is a similar idea, but it doesn't allow for the creation of documents made up of HTML. |
|
i was thinking about that exact thing while i was making this. I wanted to give users more control and the ability to display and build their own webpage documents. |
|
can i use 'https://unpkg.com/html-dom-parser@latest/dist/html-dom-parser.min.js' for prettier |
|
or i can use this function function prettierInText(html) {
// Clean up existing whitespace and collapse it
let clean = html.replace(/\s*([<>])\s*/g, '$1').replace(/\s+/g, ' ');
let reg = /(<[^>]+>)/g;
let matches = clean.split(reg).filter(Boolean);
let formatted = '';
let pad = 0;
matches.forEach((token) => {
// Check if the token is a closing tag
if (token.match( /<\/\w+/ )) {
pad--;
}
// Add current line indentation
formatted += ' '.repeat(Math.max(0, pad)) + token + '\n';
// Check if the token is an opening tag (and not self-closing)
if (token.match( /<[^\/][^>]*[^>\/]>/ ) && !token.match(/<(input|img|br|hr|meta|link)/)) {
pad++;
}
});
return formatted.trim();
}
// Example Usage
const raw = '<div><h1>Title</h1><p>Text</p><img src="img.jpg"/></div>';
console.log(prettierInText(raw)); |
This seems to be very clearly AI generated. I don't know if you vibecoded this extension but if you did that's a biiiig no-no |
|
I typed this myself. But the function i just pasted was AI generated because I wanted to see if you would or would not want me to import the prettier. |
|
I don't paln on using the script I sent you but I want to verify if i'm ok to import perttier from https://unpkg.com/html-dom-parser@latest/dist/html-dom-parser.min.js' |
I built this off of my previous html to canvas extension that I made last year. |
Uh, I don't think that's Prettier, that's a DOM parser. Prettier is a code formatter, I was requesting that you reformat your code. |
|
OH. ok. it does have a html parser. You wnated me to format my code |
Yes. The JavaScript of the extension, that's what I want you to format. |
|
I'll do that when i post my new revided version that replies to your suggestions (I'm a good coder but a horrible formatter. I'm downloading prettier on vscode right now) |
Alright, you actually don't need to open a new PR, just push to the same branch that this PR is pulling from (main). |
|
Additionally, you can just use the builtin |
|
I got you. |
|
should i use that to insert elements into my iframe or change the entire this.pages[page].codeto a HTML DOM |
|
I will make it do whatever you think it should do if someone does that. I dont know what a user would expect if they did that. |
Actually, I'd argue, in part related to Jwk's argument, that this is actually a place where a DOM is better. You can set values on the thread ( Speaking of which, there should actually be a way to edit the child elements and text of an element after its creation. |
|
so the there is a thread var (an array) that contains elements to be created. i'm changing it right now to a dom |
|
changed to a DOM |
Refactor HTMLDocuments class to remove unused 'ids' property and update related methods to use 'code' for element queries.
|
Added new blocks and got rid of unessecary tracking of ids |
|
Didn't mean to close :slappingmyheademoji: |
I just made a big change in how this works so there are a lot of things to fix
IM NOT LYING THERE WERE LITERALLY 67 CONSOLE LOG STATEMENTS IN MY CODE
Steve0Greatness
left a comment
There was a problem hiding this comment.
I'll probably do a somewhat more in-depth review at some point, but I noticed you added a menu icon. It's currently 374x374px, which is far to large (note they're always displayed at very small resolutions). My personal recommendation is to scale it to 32x32.
|
yeah i´ll do that. |
and some other stuff. resolved nesting issues
|
|
|
I'll be back on Monday. |
|
back |
|
There should probably be a way to change text content of an element dynamically. |



Create HTML webpages and display them on the stage

I'll make a documentation when I know what you think of this