Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/single-file.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Create single file build

on:
push:
branches: ["**"]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: "single-file-build"
cancel-in-progress: false
Comment thread
NellowTCS marked this conversation as resolved.

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: "Build/package-lock.json"

- name: Install dependencies
working-directory: Build
run: npm ci

- name: Build
working-directory: Build
run: npm run build:single

- name: Rename for distribution
working-directory: Build/dist
run: mv index.html HTMLRunner.html

- name: Upload Build Artifact
uses: actions/upload-artifact@v4
with:
name: HTMLRunner-Standalone
path: Build/dist/HTMLRunner.html
if-no-files-found: error
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
44 changes: 21 additions & 23 deletions .github/workflows/static.yml
Original file line number Diff line number Diff line change
@@ -1,45 +1,43 @@
# .github/workflows/static.yml
name: Deploy static content to Pages
# Simple workflow for deploying static content to GitHub Pages
name: Deploy browser build to GitHub Pages

on:
push:
branches: ["main"]
workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
contents: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: true
cancel-in-progress: false

jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: "20"

- name: Run build script
run: |
chmod +x Build/Buildscripts/build.sh
./Build/Buildscripts/build.sh
- name: Install dependencies
working-directory: Build
run: npm i

- name: Upload GitHub Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'Build/dist'
- name: Build
working-directory: Build
run: npm run build

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
- name: Deploy browser build to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: Build/dist
16 changes: 0 additions & 16 deletions Build/Buildscripts/build-all.sh

This file was deleted.

67 changes: 0 additions & 67 deletions Build/Buildscripts/build-inline.sh

This file was deleted.

21 changes: 0 additions & 21 deletions Build/Buildscripts/build.sh

This file was deleted.

1 change: 1 addition & 0 deletions Build/dev-dist/registerSW.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions Build/eslint.config.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import js from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";
import json from "@eslint/json";
import markdown from "@eslint/markdown";
import css from "@eslint/css";
import { defineConfig } from "eslint/config";

export default defineConfig([
{ files: ["**/*.{js,mjs,cjs,ts,mts,cts}"], plugins: { js }, extends: ["js/recommended"], languageOptions: { globals: globals.browser } },
Comment thread
NellowTCS marked this conversation as resolved.
tseslint.configs.recommended,
{ files: ["**/*.md"], plugins: { markdown }, language: "markdown/gfm", extends: ["markdown/recommended"] },
{ files: ["**/*.css"], plugins: { css }, language: "css/css", extends: ["css/recommended"] },
]);
135 changes: 135 additions & 0 deletions Build/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTMLRunner</title>
<link rel="stylesheet" href="./styles/styles.css">
</head>
<body>
<div class="loading" id="loading">
<div class="spinner"></div>
</div>
<div class="error-message" id="error-message"></div>
<div class="container">
<div class="menubar">
<div class="menubar-left">
<span class="logo">HTMLRunner</span>
<div class="menu-items">
<div class="menu-item" data-menu="file">File</div>
<div class="menu-item" data-menu="edit">Edit</div>
<div class="menu-item" data-menu="view">View</div>
<div class="menu-item" data-menu="run">Run</div>
<div class="menu-item" data-menu="git-menu">Git</div>
<div class="menu-item" data-menu="help">Help</div>
</div>
</div>
<div class="menubar-right">
<button class="btn btn-run"><i class="fas fa-play"></i> Run</button>
<button class="btn btn-format" title="Format Code"><i class="fas fa-code"></i></button>
<button class="btn btn-auto-run" title="Toggle Auto-Run"><i class="fas fa-sync"></i> <span id="auto-run-status">Off</span></button>
<button class="theme-toggle" title="Toggle Theme">
<i class="fas fa-moon"></i>
<span>Dark Mode</span>
</button>
</div>
</div>
<div class="menu-dropdown" id="menu-file">
<div class="menu-dropdown-item" data-action="addFile"><i class="fas fa-plus"></i> New File</div>
<div class="menu-dropdown-item" data-action="addFolder"><i class="fas fa-folder-plus"></i> New Folder</div>
<div class="menu-dropdown-item" data-action="importFiles"><i class="fas fa-folder-open"></i> Import Files</div>
<div class="menu-dropdown-separator"></div>
<div class="menu-dropdown-item" data-action="exportAsZip"><i class="fas fa-download"></i> Export ZIP</div>
<div class="menu-dropdown-separator"></div>
<div class="menu-dropdown-item" data-action="resetCode"><i class="fas fa-undo"></i> Reset to Defaults</div>
</div>
<div class="menu-dropdown" id="menu-edit">
<div class="menu-dropdown-item" data-action="undo"><i class="fas fa-undo"></i> Undo</div>
<div class="menu-dropdown-item" data-action="redo"><i class="fas fa-redo"></i> Redo</div>
<div class="menu-dropdown-separator"></div>
<div class="menu-dropdown-item" data-action="toggleSearch"><i class="fas fa-search"></i> Find</div>
<div class="menu-dropdown-item" data-action="toggleReplace"><i class="fas fa-exchange-alt"></i> Find &amp; Replace</div>
<div class="menu-dropdown-separator"></div>
<div class="menu-dropdown-item" data-action="formatCode"><i class="fas fa-code"></i> Format Code</div>
</div>
<div class="menu-dropdown" id="menu-view">
<div class="menu-dropdown-item" data-action="toggleSidebar"><i class="fas fa-columns"></i> Toggle Sidebar</div>
<div class="menu-dropdown-item" data-action="switchOutput-preview"><i class="fas fa-eye"></i> Show Preview</div>
<div class="menu-dropdown-item" data-action="switchOutput-console"><i class="fas fa-terminal"></i> Show Console</div>
<div class="menu-dropdown-item" data-action="switchOutput-terminal"><i class="fas fa-window-terminal"></i> Show Terminal</div>
<div class="menu-dropdown-separator"></div>
<div class="menu-dropdown-item" data-action="toggleDarkMode"><i class="fas fa-moon"></i> Toggle Dark Mode</div>
<div class="menu-dropdown-item" data-action="toggleAutoRun"><i class="fas fa-sync"></i> Toggle Auto-Run</div>
</div>
<div class="menu-dropdown" id="menu-run">
<div class="menu-dropdown-item" data-action="runCode"><i class="fas fa-play"></i> Run Code</div>
<div class="menu-dropdown-separator"></div>
<div class="menu-dropdown-item" data-action="clearConsole"><i class="fas fa-trash"></i> Clear Console</div>
</div>
<div class="menu-dropdown" id="menu-git-menu">
<div class="menu-dropdown-item" data-action="gitStatus"><i class="fas fa-info-circle"></i> Status</div>
<div class="menu-dropdown-item" data-action="gitDiff"><i class="fas fa-code-branch"></i> Diff</div>
<div class="menu-dropdown-item" data-action="gitLog"><i class="fas fa-history"></i> Log</div>
<div class="menu-dropdown-separator"></div>
<div class="menu-dropdown-item" data-action="gitCommit"><i class="fas fa-check"></i> Commit</div>
<div class="menu-dropdown-item" data-action="gitPush"><i class="fas fa-cloud-upload-alt"></i> Push</div>
<div class="menu-dropdown-item" data-action="gitPull"><i class="fas fa-cloud-download-alt"></i> Pull</div>
<div class="menu-dropdown-separator"></div>
<div class="menu-dropdown-item" data-action="gitClone"><i class="fas fa-clone"></i> Clone</div>
</div>
<div class="menu-dropdown" id="menu-help">
<div class="menu-dropdown-item" data-action="about"><i class="fas fa-info-circle"></i> About HTMLRunner</div>
<div class="menu-dropdown-separator"></div>
<div class="menu-dropdown-item" data-action="openShortcuts"><i class="fas fa-keyboard"></i> Keyboard Shortcuts</div>
</div>
<div class="main">
<div class="editor-panel" id="editor-panel">
<div class="editor-header">
<div class="file-tabs" id="file-tabs"></div>
</div>
<div class="editor-body">
<div class="sidebar" id="sidebar">
<div class="sidebar-header">
<span>FILES</span>
<div class="sidebar-actions">
<button class="sidebar-new-btn" id="sidebar-new-btn" title="New File"><i class="fas fa-plus"></i></button>
<button class="sidebar-folder-btn" id="sidebar-folder-btn" title="New Folder"><i class="fas fa-folder-plus"></i></button>
<button class="sidebar-import-btn" id="sidebar-import-btn" title="Import Files"><i class="fas fa-folder-open"></i></button>
</div>
</div>
<div class="file-tree" id="file-tree"></div>
<div class="sidebar-section">
<div class="sidebar-header">
<span>GIT</span>
<button class="sidebar-git-btn" id="sidebar-git-btn" title="Commit"><i class="fas fa-check"></i></button>
</div>
<div class="git-status" id="git-status"></div>
</div>
</div>
<div class="editor-container" id="editor-container"></div>
</div>
</div>
<div class="output-panel" id="output-panel">
<div class="output-tabs">
<div class="tab active" data-output="preview">Preview</div>
<div class="tab" data-output="console">Console</div>
<div class="tab" data-output="terminal">Terminal</div>
</div>
<div class="output-content">
<button class="preview-open-btn" id="preview-open-btn" title="Open preview in new tab"><i class="fas fa-external-link-alt"></i></button>
<iframe id="preview" class="preview active"></iframe>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Sandbox the preview iframe.

This runner executes user code inside #preview. Without a sandbox attribute, previewed scripts can reach the parent app and its storage through window.parent, which breaks isolation.

🔒 Minimal hardening
-                    <iframe id="preview" class="preview active"></iframe>
+                    <iframe id="preview" class="preview active" sandbox="allow-scripts"></iframe>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Build/index.html` at line 59, The preview iframe (<iframe id="preview"
class="preview active">) lacks a sandbox attribute allowing previewed scripts to
access the parent; add a sandbox attribute to harden isolation (e.g.,
sandbox="allow-scripts" for running user scripts but preventing access to
window.parent/storage) on the iframe with id="preview" and avoid including
permissions like allow-same-origin or allow-top-navigation unless explicitly
required.

<div id="console" class="console"></div>
<div id="terminal" class="terminal-panel"></div>
</div>
</div>
</div>
</div>
<div class="status-bar" id="status-bar">
<span class="cursor-position" id="cursor-position">Ln 1, Col 1</span>
<span class="status-bar-right">
<span class="file-encoding">UTF-8</span>
</span>
</div>
<script type="module" src="./src/main.ts"></script>
</body>
</html>
Loading
Loading