A kódbázis kommentek nélkül marad
ci/woodpecker/push/woodpecker Pipeline was successful

Kérésre: minden magyarázó komment kikerült a forrásfájlokból — 89 Ruby, 16
TypeScript, 14 Vue, plusz a CSS/JS/CJS. Nem soralapú kereséssel: a Ruby-t a
Ripper tokenizálta, a JS/TS/CSS-t állapotgép járta végig, hogy az URL-ekben,
reguláris kifejezésekben és heredocokban álló // és # jelek helyükön
maradjanak.

Három komment maradt, mert nélkülük nem indul a kód: az entrypoint.sh
shebangja, a vite-env.d.ts hármas perjeles referenciája, és a sanitize
teszt @vitest-environment direktívája (ez utóbbi a magyarázó része nélkül).

Egy helyen kódot is kellett írni: a CommandBlock másolás-hibaágán a komment
volt a catch egyetlen tartalma, és üres blokkot az eslint nem enged — a
copied jelző visszaállítása került a helyére.

A yaml, Dockerfile, Makefile, erb és markdown fájlokat nem érintettem.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-20 12:52:47 +02:00
co-authored by Claude Opus 5
parent e431e2b85b
commit ebe3684d44
126 changed files with 117 additions and 1107 deletions
+1 -4
View File
@@ -3,8 +3,6 @@ ActiveAdmin.register Store do
menu priority: 5, label: "🛒 Stores"
# Active first and by default: the registry is what clients actually read, so the
# useful question on opening this page is "what is being offered right now".
scope("Active", default: true) { |scope| scope.active }
scope("Inactive") { |scope| scope.where(active: false) }
scope :all
@@ -21,8 +19,7 @@ ActiveAdmin.register Store do
end
column :updated_at
actions defaults: true do |store|
# One click, because this is the thing an admin comes to this page to do — and
# the alternative is Edit, a checkbox and Save for a single boolean.
link_to store.active? ? "Hide" : "List",
toggle_admin_store_path(store),
method: :put
+1 -2
View File
@@ -1,2 +1 @@
//= link active_admin.css
//= link active_admin.js
@@ -1,5 +1,3 @@
//= require active_admin/base
(function() {
var PATH_INPUT_SELECTOR = 'input[id*="release_assets_attributes"][id$="_path"]:not([data-browse-added])';
var _pickerTarget = null;
@@ -89,7 +87,6 @@
var html = '';
// Breadcrumb
var parts = dir ? dir.split('/').filter(function(p){return p;}) : [];
html += '<div class="fm-breadcrumbs"><a href="#" data-dir="">softwares/</a>';
var acc = '';
@@ -99,19 +96,16 @@
}
html += '</div>';
// Upload bar (also a drop zone)
html += '<div class="fm-actions fm-dropzone" id="fm-picker-dropzone">';
html += '<input type="file" id="fm-picker-file" />';
html += '<button class="fm-btn" id="fm-picker-upload-btn">Upload</button>';
html += '<span class="fm-drop-hint">or drag &amp; drop files here</span>';
html += '</div>';
// Table
html += '<table class="fm-table"><thead><tr>';
html += '<th style="width:50px">Type</th><th>Name</th><th style="width:90px">Size</th>';
html += '<th style="width:80px"></th></tr></thead><tbody>';
// Parent dir
if (dir) {
var parentDir = dir.indexOf('/') >= 0 ? dir.substring(0, dir.lastIndexOf('/')) : '';
html += '<tr><td class="fm-type">DIR</td>';
@@ -139,10 +133,8 @@
html += '</tbody></table>';
body.innerHTML = html;
// Event delegation
body.addEventListener('click', handlePickerClick);
// Drag & drop
var dropzone = document.getElementById('fm-picker-dropzone');
if (dropzone) {
['dragenter', 'dragover'].forEach(function(evt) {
@@ -162,21 +154,18 @@
function handlePickerClick(e) {
var t = e.target;
// Navigate directory
if (t.tagName === 'A' && t.hasAttribute('data-dir')) {
e.preventDefault();
loadDir(t.getAttribute('data-dir'));
return;
}
// Select file/folder
if (t.hasAttribute('data-select')) {
e.preventDefault();
selectPath(t.getAttribute('data-select'));
return;
}
// Upload button
if (t.id === 'fm-picker-upload-btn') {
e.preventDefault();
var fileInput = document.getElementById('fm-picker-file');
@@ -233,7 +222,6 @@
return (bytes / 1048576).toFixed(1) + ' MB';
}
// Live image preview for software_images image_id selects
function addImagePreviewListeners() {
var selects = document.querySelectorAll('select[id*="image_id"]:not([data-preview-added])');
selects.forEach(function(sel) {
@@ -241,7 +229,6 @@
sel.addEventListener('change', function() {
var hint = sel.closest('li').querySelector('.inline-hints');
if (!hint) {
// Create hint element if it doesn't exist
hint = document.createElement('p');
hint.className = 'inline-hints';
sel.closest('li').appendChild(hint);
@@ -255,7 +242,6 @@
});
}
// Standalone Files page drag & drop
function initPageDropzone() {
var dz = document.getElementById('fm-page-dropzone');
if (!dz) return;
@@ -2,7 +2,6 @@
@import "active_admin/base";
@import "activeadmin_blaze_theme/theme";
// Force utility navigation visible (blaze theme may hide it)
#utility_nav { display: flex !important; visibility: visible !important; }
#utility_nav #site_link a {
color: #fff !important;
@@ -11,7 +10,6 @@
&:hover { text-decoration: underline; }
}
// File Manager
.fm-breadcrumbs {
background: #f5f5f5; padding: 10px 14px; border-radius: 4px; margin-bottom: 16px; font-family: monospace; font-size: 14px;
a { color: #5a6268; text-decoration: none; &:hover { text-decoration: underline; } }
@@ -37,7 +35,6 @@
.fm-icon-danger:hover { filter: brightness(1.3); }
.fm-danger { color: #dc3545; }
// Emoji action buttons in AA index tables
.table_actions {
a.view_link, a.edit_link, a.delete_link {
font-size: 0 !important;
@@ -61,14 +58,12 @@
.fm-dropzone { transition: background 0.15s, border-color 0.15s; border: 2px dashed transparent; }
.fm-dropzone.fm-dragover { background: #e8f4fd !important; border-color: #4a90d9 !important; }
// Browse button in release forms
.fm-browse-btn {
display: inline-block; margin-left: 8px; padding: 4px 10px; background: #6c757d; color: #fff !important; border-radius: 3px; font-size: 11px; text-decoration: none !important; vertical-align: middle;
&:hover { background: #5a6268; color: #fff !important; }
&:visited { color: #fff !important; }
}
// Inline file picker modal
.fm-modal-overlay {
position: fixed; inset: 0; z-index: 9999; background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center;
}
@@ -26,7 +26,7 @@ class Api::WikiController < ApiController
end
property :error, String, desc: "Error message (null on success)"
end
# GET /api/wiki/pages?tag=blog|howto[&limit=30][&body=1]
def index
render json: WikiService.new.index(
tag: params[:tag],
-15
View File
@@ -1,14 +1,3 @@
# A store a client can install from: a name and a WarpEngine catalog.
#
# That is the whole record, and deliberately so. A client takes identity from it — the
# name, the catalog, and a slug derived from the catalog host — and everything else from
# the store engine it carries. How a store behaves is fixed per installed client, which
# knows its own machine; a copy of it here would be a second authority over decisions
# the client has already made, including which directories it may delete from.
#
# This is deliberately not part of WarpEngine. The engine serves one catalog and has no
# business knowing which stores exist for it; the registry is a property of this site,
# which is what the graphical client asks.
class Store < ApplicationRecord
URL = %r{\Ahttps?://\S+\z}
@@ -17,10 +6,6 @@ class Store < ApplicationRecord
default_scope { where(deleted_at: nil) }
# Two different "not listed". Soft deletion is "this store is gone"; `active` is
# "not right now" — a catalog still being set up, or one pulled from the picker for
# a while. The client cannot tell the difference and should not have to: it lists
# whatever /api/stores hands it.
scope :active, -> { where(active: true) }
scope :ordered, -> { order(:name) }
+1 -2
View File
@@ -2,7 +2,6 @@ class StoreSerializer < Blueprinter::Base
include WarpEngine::TimestampFields
field :name
# camelCase, as the catalog's own payloads use — one convention for a client
# that reads both.
field(:catalogUrl) { |store| store.catalog_url }
end
+1 -3
View File
@@ -1,7 +1,5 @@
class StoreService
# Only the active ones. An inactive store is simply absent from the registry — the
# client has no state for "there but switched off", and inventing one would mean
# every client release having an opinion about it.
def index
StoreSerializer.render_as_hash(Store.active.ordered)
end
-18
View File
@@ -1,23 +1,6 @@
require "net/http"
require "json"
# Fetches wiki pages (blog, howto, …) from the Grav backend, filtered by tag.
#
# Grav exposes: GET {WIKI_GRAV_URL}/custom/pages.json?tag=<tag>[&limit=<n>][&body=1]
# and returns:
# {
# "tag": "howto", "count": 24,
# "pages": [
# { "id", "path", "title", "description",
# "createdAt", "updatedAt", "locale", "route", "tags",
# # with body=1 also:
# "render" (rendered HTML),
# "content" (raw markdown) }
# ]
# }
#
# This replaces the frontend's direct WikiJS GraphQL calls with a simple GET,
# and points at Grav (which is taking over from wiki.teletypegames.org).
class WikiService
GRAV_URL = ENV.fetch("WIKI_GRAV_URL", "http://localhost:8080").freeze
@@ -44,6 +27,5 @@ class WikiService
{ "tag" => tag, "count" => 0, "pages" => [], "error" => e.message }
end
# Az RSS feedek ezen a néven hívják.
alias_method :pages, :index
end