This commit is contained in:
Christoph Haas 2025-04-11 09:39:33 +02:00
parent 7cd9c68a10
commit 36984ff1d4
20 changed files with 321 additions and 391 deletions

View file

@ -11,9 +11,9 @@ gem 'puma', '>= 5.0'
# Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails] # Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]
# gem 'jsbundling-rails' # gem 'jsbundling-rails'
# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev] # Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
# gem "turbo-rails" gem 'turbo-rails'
# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev] # Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
# gem "stimulus-rails" gem 'stimulus-rails'
# Bundle and process CSS [https://github.com/rails/cssbundling-rails] # Bundle and process CSS [https://github.com/rails/cssbundling-rails]
# gem 'cssbundling-rails' # gem 'cssbundling-rails'
# Build JSON APIs with ease [https://github.com/rails/jbuilder] # Build JSON APIs with ease [https://github.com/rails/jbuilder]
@ -168,4 +168,6 @@ gem 'rails-healthcheck'
# https://github.com/bkeepers/dotenv # https://github.com/bkeepers/dotenv
gem 'dotenv' gem 'dotenv'
gem "cssbundling-rails", "~> 1.4" gem 'cssbundling-rails', '~> 1.4'
gem "importmap-rails", "~> 2.1"

View file

@ -183,6 +183,10 @@ GEM
image_processing (1.14.0) image_processing (1.14.0)
mini_magick (>= 4.9.5, < 6) mini_magick (>= 4.9.5, < 6)
ruby-vips (>= 2.0.17, < 3) ruby-vips (>= 2.0.17, < 3)
importmap-rails (2.1.0)
actionpack (>= 6.0.0)
activesupport (>= 6.0.0)
railties (>= 6.0.0)
io-console (0.8.0) io-console (0.8.0)
irb (1.15.1) irb (1.15.1)
pp (>= 0.6.0) pp (>= 0.6.0)
@ -479,6 +483,8 @@ GEM
net-sftp (>= 2.1.2) net-sftp (>= 2.1.2)
net-ssh (>= 2.8.0) net-ssh (>= 2.8.0)
ostruct ostruct
stimulus-rails (1.3.4)
railties (>= 6.0.0)
stringio (3.1.5) stringio (3.1.5)
swd (2.0.3) swd (2.0.3)
activesupport (>= 3) activesupport (>= 3)
@ -494,6 +500,9 @@ GEM
thruster (0.1.12-x86_64-linux) thruster (0.1.12-x86_64-linux)
tilt (2.6.0) tilt (2.6.0)
timeout (0.4.3) timeout (0.4.3)
turbo-rails (2.0.13)
actionpack (>= 7.1.0)
railties (>= 7.1.0)
tzinfo (2.0.6) tzinfo (2.0.6)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
unicode-display_width (3.1.4) unicode-display_width (3.1.4)
@ -556,6 +565,7 @@ DEPENDENCIES
guard-minitest guard-minitest
guard-rails guard-rails
image_processing image_processing
importmap-rails (~> 2.1)
jbuilder jbuilder
kamal kamal
listen (~> 3.5) listen (~> 3.5)
@ -580,7 +590,9 @@ DEPENDENCIES
shrine (~> 3.0) shrine (~> 3.0)
slim-rails slim-rails
sqlite3 (>= 2.1) sqlite3 (>= 2.1)
stimulus-rails
thruster thruster
turbo-rails
web-console web-console
will_paginate will_paginate
will_paginate-foundation will_paginate-foundation

View file

@ -14,12 +14,14 @@
// window.$ = window.jQuery = jQuery; // Expose globally (if needed) // window.$ = window.jQuery = jQuery; // Expose globally (if needed)
// import "./foundation-sites/dist/js/foundation.min"; // import "./foundation-sites/dist/js/foundation.min";
import "./controllers";
import "@hotwired/turbo-rails";
// import jquery from "jquery"; import jQuery from "./jquery.js";
// window.jQuery = jquery; // window.jQuery = jquery;
// window.$ = jquery; window.$ = jQuery;
$(function () { $(function () {
$(document).foundation(); $(document).foundation();
@ -43,89 +45,3 @@ $(function () {
// ); // );
// }; // };
// Initialize the upload form.
function upload_form_init() {
// Disable the submit button if Javascript is supported.
// Upload will start right after selecting images.
$('#file-submit').hide();
// Install event handler to notice when files were selected.
$('#file').on('change', upload_form_files_selected);
};
function upload_form_files_selected() {
no_files = this.files.length;
if (no_files > 0) {
$('#file-label').html(no_files+" files selected - uploading…"); // change label
$('#file-select-button').attr('disabled','disabled'); // disable select button
$('#file-form').trigger('submit'); // start upload
}
};
// Handle Ctrl-V to paste an image directly
function upload_paste_handler(event)
{
console.log("paste!");
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
// /*Make Sure Only One File is Copied*/
// if (items.length != 1) {
// return;
// }
for (var i = 0 ; i < items.length ; i++)
{
var item = items[i];
console.log(item);
console.log("item size="+item.size);
if (!item.type.startsWith('image/'))
{
console.log("Skipping file with type "+item.type);
continue
}
console.log(item.type);
var file = item.getAsFile();
console.log(file);
upload_file_with_ajax(file);
}
}
function upload_file_with_ajax(file)
{
if (file==null)
{
console.log("File was null. Strange.");
display_error('Maybe the image was too large.');
return;
}
var formData = new FormData();
formData.append('file', file);
$.ajax(ajax_upload_url,
{
type: 'POST',
contentType: false,
processData: false,
data: formData,
//dataType: 'json',
error: function(xhr, txt, err)
{
console.log("AJAX file upload returned error: "+txt+" / "+err);
response = JSON.parse(xhr.responseText);
display_error(response);
},
success: function(res)
{
console.log("AJAX file upload was ok");
// Go back to details page to show the new upload
window.location.replace(after_upload_url);
}
});
}
function display_error(msg)
{
$('#messages').html(
'<div class="callout alert alert-callout-subtle radius">Sorry, pasting did not work. ' + msg + '</div>')
}

2
app/assets/javascripts/foundation.js vendored Normal file

File diff suppressed because one or more lines are too long

2
app/assets/javascripts/jquery.js vendored Normal file

File diff suppressed because one or more lines are too long

2
app/assets/stylesheets/foundation.css vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -4,15 +4,15 @@ class WelcomeController < ApplicationController
def home def home
@newest_upload = Screenshot.where(approved: true).first @newest_upload = Screenshot.where(approved: true).first
#@most_popular_package = Package.with_screenshots.order(visits: :desc).first # @most_popular_package = Package.with_screenshots.order(visits: :desc).first
@random_pick = Package.with_public_screenshots.order("RANDOM()").first @random_pick = Package.with_public_screenshots.order('RANDOM()').first
@package_count = Package.count @package_count = Package.count
# Get up 100 screenshots where the packages have the most visits # Get up 100 screenshots where the packages have the most visits
query = Package.without_screenshots #.order(visits: :desc) query = Package.without_screenshots # .order(visits: :desc)
count = query.count count = query.count
random_offset = rand( [100, count].min ) random_offset = rand([100, count].min)
@most_wanted_package = query.offset(random_offset).first @most_wanted_package = query.offset(random_offset).first
end end

View file

@ -1,62 +1,34 @@
// Entry point for the build script in your package.json // Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
// import "@hotwired/turbo-rails"; import "@hotwired/turbo-rails"
// import "jquery"; import "controllers"
import "foundation-sites";
// import 'foundation-sites/dist/css/foundation.min.css'; // CSS
import "./controllers";
// // Entry point for the build script in your package.json
import jquery from "jquery";
window.jQuery = jquery;
window.$ = jquery;
$(function () {
$(document).foundation();
});
// Load reviews on package's details page
// load_reviews = function() {
// // Display message while loading reviews
// // $('#reviews').html("<i>Loading reviews...</i>");
// // Hide the DIV so that in can be faded in later
// $('#reviews').hide();
// // The URL is specified in the #reviews's DIV data attribute
// var url = $('#reviews').attr('data-package-reviews-url');
// $('#reviews').load(url, null,
// // Fade in the reviews as soon as the DIV is loaded and filled
// function(){
// $(this).fadeIn('slow')
// }
// );
// };
// Initialize the upload form. // Initialize the upload form.
function upload_form_init() { function upload_form_init() {
// Disable the submit button if Javascript is supported. // Disable the submit button if Javascript is supported.
// Upload will start right after selecting images. // Upload will start right after selecting images.
$('#file-submit').hide(); // $("#file-submit").hide();
document.getElementById("file-submit").style.display = "none";
// Install event handler to notice when files were selected. // Install event handler to notice when files were selected.
$('#file').on('change', upload_form_files_selected); // $("#file").on("change", upload_form_files_selected);
}; document.getElementById("file").addEventListener("change", upload_form_files_selected);
}
function upload_form_files_selected() { function upload_form_files_selected() {
no_files = this.files.length; no_files = this.files.length;
if (no_files > 0) { if (no_files > 0) {
$('#file-label').html(no_files+" files selected - uploading…"); // change label document.getElementById("file-label").innerHTML = `${no_files} files selected - uploading…`;
$('#file-select-button').attr('disabled','disabled'); // disable select button document.getElementById("file-select-button").disabled = true;
$('#file-form').trigger('submit'); // start upload document.getElementById("file-form").submit();
}
};
// $("#file-label").html(no_files + " files selected - uploading…"); // change label
// $("#file-select-button").attr("disabled", "disabled"); // disable select button
// $("#file-form").trigger("submit"); // start upload
}
}
// Handle Ctrl-V to paste an image directly // Handle Ctrl-V to paste an image directly
function upload_paste_handler(event) export function upload_paste_handler(event) {
{
console.log("paste!"); console.log("paste!");
var items = (event.clipboardData || event.originalEvent.clipboardData).items; var items = (event.clipboardData || event.originalEvent.clipboardData).items;
@ -65,15 +37,13 @@ function upload_paste_handler(event)
// return; // return;
// } // }
for (var i = 0 ; i < items.length ; i++) for (var i = 0; i < items.length; i++) {
{
var item = items[i]; var item = items[i];
console.log(item); console.log(item);
console.log("item size="+item.size); console.log("item size=" + item.size);
if (!item.type.startsWith('image/')) if (!item.type.startsWith("image/")) {
{ console.log("Skipping file with type " + item.type);
console.log("Skipping file with type "+item.type); continue;
continue
} }
console.log(item.type); console.log(item.type);
var file = item.getAsFile(); var file = item.getAsFile();
@ -82,41 +52,68 @@ function upload_paste_handler(event)
} }
} }
function upload_file_with_ajax(file) function upload_file_with_ajax(file) {
{ if (file == null) {
if (file==null)
{
console.log("File was null. Strange."); console.log("File was null. Strange.");
display_error('Maybe the image was too large.'); display_error("Maybe the image was too large.");
return; return;
} }
var formData = new FormData(); var formData = new FormData();
formData.append('file', file); formData.append("file", file);
$.ajax(ajax_upload_url, fetch(ajax_upload_url, {
{ method: "POST",
type: 'POST', body: formData,
contentType: false, headers: {
processData: false, // 'Content-Type' is omitted to let the browser set it automatically
data: formData, // with the proper boundary for FormData
//dataType: 'json',
error: function(xhr, txt, err)
{
console.log("AJAX file upload returned error: "+txt+" / "+err);
response = JSON.parse(xhr.responseText);
display_error(response);
}, },
success: function(res) })
{ .then(async (response) => {
console.log("AJAX file upload was ok"); if (!response.ok) {
// Go back to details page to show the new upload const errorData = await response.json();
window.location.replace(after_upload_url); console.log(`AJAX file upload returned error: ${response.statusText}`);
display_error(errorData);
throw new Error("Upload failed");
}
return response.json();
})
.then((data) => {
console.log("AJAX file upload was ok");
window.location.replace(after_upload_url);
})
.catch((error) => {
if (error.message !== "Upload failed") {
console.log(`AJAX file upload error: ${error}`);
} }
}); });
// $.ajax(ajax_upload_url, {
// type: "POST",
// contentType: false,
// processData: false,
// data: formData,
// //dataType: 'json',
// error: function (xhr, txt, err) {
// console.log("AJAX file upload returned error: " + txt + " / " + err);
// response = JSON.parse(xhr.responseText);
// display_error(response);
// },
// success: function (res) {
// console.log("AJAX file upload was ok");
// // Go back to details page to show the new upload
// window.location.replace(after_upload_url);
// },
// });
} }
function display_error(msg) function display_error(msg) {
{ // $("#messages").html(
$('#messages').html( // '<div class="callout alert alert-callout-subtle radius">Sorry, pasting did not work. ' + msg + "</div>"
'<div class="callout alert alert-callout-subtle radius">Sorry, pasting did not work. ' + msg + '</div>') // );
document.querySelector("#messages").innerHTML = `
<div class="callout alert alert-callout-subtle radius">
Sorry, pasting did not work. ${msg}
</div>
`;
} }

View file

@ -1,8 +1,4 @@
// This file is auto-generated by ./bin/rails stimulus:manifest:update // Import and register all your controllers from the importmap via controllers/**/*_controller
// Run that command whenever you add a new controller or create them with import { application } from "controllers/application"
// ./bin/rails generate stimulus controllerName import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
eagerLoadControllersFrom("controllers", application)
import { application } from "./application"
import HelloController from "./hello_controller"
application.register("hello", HelloController)

View file

@ -1,4 +1,4 @@
require 'open-uri' # allows to load URLs using open() require 'open-uri' # allows to load URLs using open()
require 'json' require 'json'
require 'deb_importer' require 'deb_importer'
@ -8,26 +8,26 @@ class Package < ApplicationRecord
include PgSearch::Model include PgSearch::Model
# TODO: Make search weighted on users' rating # TODO: Make search weighted on users' rating
pg_search_scope :general_search, pg_search_scope :general_search,
# :against => [:name, :description, :long_description], # :against => [:name, :description, :long_description],
:against => [ against: [
[:name, 'A'], [:name, 'A'],
[:description, 'B'], [:description, 'B'],
[:long_description, 'C'] [:long_description, 'C']
], ],
:using => { using: {
:tsearch => {:dictionary => "english"} tsearch: { dictionary: 'english' }
} }
# I am using "destroy_all" here so that when a package gets destroys the # I am using "destroy_all" here so that when a package gets destroys the
# callbacks for all dependent screenshots are executed - thus removing the # callbacks for all dependent screenshots are executed - thus removing the
# screenshot files from disk. # screenshot files from disk.
has_many :screenshots, has_many :screenshots,
-> { order(id: :desc) }, -> { order(id: :desc) },
:inverse_of=>:package, inverse_of: :package,
:dependent => :destroy dependent: :destroy
# default_scope { # default_scope {
# order('name ASC') # order('name ASC')
# } # }
# Define the parameter(s) used for a /package/:name URL to an instance of this model # Define the parameter(s) used for a /package/:name URL to an instance of this model
@ -37,11 +37,7 @@ class Package < ApplicationRecord
# Return the first paragraph of the long description. # Return the first paragraph of the long description.
def long_description_first_paragraph def long_description_first_paragraph
if self.long_description long_description.split(/\n\.\n/).first if long_description
self.long_description.split(/\n\.\n/).first
else
nil
end
end end
# Return a query of all packages that have screenshots # Return a query of all packages that have screenshots
@ -72,7 +68,7 @@ class Package < ApplicationRecord
# Get all screenshots and have them sorted descendingly by their version number (Debian style). # Get all screenshots and have them sorted descendingly by their version number (Debian style).
def screenshots_sorted_by_version def screenshots_sorted_by_version
self.screenshots.approved.to_a.sort { |x,y| version_compare(x.version,y.version) } screenshots.approved.to_a.sort { |x, y| version_compare(x.version, y.version) }
end end
# Return the newest screenshot that is not newer than the given version. # Return the newest screenshot that is not newer than the given version.
@ -83,29 +79,29 @@ class Package < ApplicationRecord
# This way the user does not see a screenshot of version 2.0 because # This way the user does not see a screenshot of version 2.0 because
# 2.0 might contain features that were not there in version 1.5. # 2.0 might contain features that were not there in version 1.5.
def best_screenshot_for_version(version) def best_screenshot_for_version(version)
sorted_screenshots = self.screenshots_sorted_by_version sorted_screenshots = screenshots_sorted_by_version
sorted_screenshots.each do |ss| sorted_screenshots.each do |ss|
logger.debug { "Comparing version #{version} against #{ss.version}" } logger.debug { "Comparing version #{version} against #{ss.version}" }
return ss if version_compare(version, ss.version)<=0 return ss if version_compare(version, ss.version) <= 0
end end
return sorted_screenshots.last sorted_screenshots.last
end end
# Return the part of the version up to the first - or + # Return the part of the version up to the first - or +
def upstream_version def upstream_version
self.version.split(/[\-\+]/).first version.split(/[-+]/).first
end end
private private
def version_compare(x,y) def version_compare(x, y)
x = '0' unless x.present? x = '0' unless x.present?
y = '0' unless y.present? y = '0' unless y.present?
version_x = DebImporter::Version.new(x) version_x = DebImporter::Version.new(x)
version_y = DebImporter::Version.new(y) version_y = DebImporter::Version.new(y)
if version_x<version_y if version_x < version_y
1 1
elsif version_x>version_y elsif version_x > version_y
-1 -1
else else
0 0

View file

@ -9,6 +9,7 @@ class Screenshot < ApplicationRecord
scope :approved, -> { where(approved: true) } scope :approved, -> { where(approved: true) }
scope :visible, -> { where(hidden: false) } scope :visible, -> { where(hidden: false) }
scope :publicly, -> { where(hidden: false, approved: true) }
# Shrine # Shrine
include ImageUploader::Attachment(:simage) # adds an `simage` virtual attribute include ImageUploader::Attachment(:simage) # adds an `simage` virtual attribute
@ -17,10 +18,10 @@ class Screenshot < ApplicationRecord
# Takes the description of a screenshot if available. # Takes the description of a screenshot if available.
# Otherwise it falls back to the general description of its package. # Otherwise it falls back to the general description of its package.
def caption def caption
if self.description.present? if description.present?
"#{self.description}" "#{description}"
else else
"#{self.package.description}" "#{package.description}"
end end
end end
@ -37,25 +38,23 @@ class Screenshot < ApplicationRecord
def status def status
text = 'This image ' text = 'This image '
if self.approved text << if approved
text << 'is public' 'is public'
else else
text << 'has to be moderated before being publicly visible' 'has to be moderated before being publicly visible'
end end
if self.markedfordelete text << ' (and was requested to be removed)' if markedfordelete
text << ' (and was requested to be removed)'
end
return text text
end end
# Brief text describing the status of this screenshots (for admins) # Brief text describing the status of this screenshots (for admins)
def adminstatus def adminstatus
if self.approved if approved
'Public' 'Public'
else else
#fa_icon('hourglass') + 'Waiting for approval' # fa_icon('hourglass') + 'Waiting for approval'
'Unapproved' 'Unapproved'
end end
end end
@ -63,32 +62,33 @@ class Screenshot < ApplicationRecord
# Publish a screenshot from the moderation queue # Publish a screenshot from the moderation queue
def approve! def approve!
self.approved = true self.approved = true
self.save! save!
end end
# Hide a screenshot from the public. Moderator level can do this. # Hide a screenshot from the public. Moderator level can do this.
def hide! def hide!
self.hidden = true self.hidden = true
self.save! save!
end end
def unhide! def unhide!
self.hidden = false self.hidden = false
self.save! save!
end end
# Get the newest screenshots regardless of the package it belongs to # Get the newest screenshots regardless of the package it belongs to
def self.newest def self.newest
self.order(created_at: :desc) order(created_at: :desc)
end end
# Return the part of the version up to the first - or + # Return the part of the version up to the first - or +
def upstream_version def upstream_version
self.version.split(/[\-\+]/).first version.split(/[-+]/).first
end end
# Returns the path to this screenshot's image on disk # Returns the path to this screenshot's image on disk
def disk_path def disk_path
ActiveStorage::Blob.service.send(:path_for, self.image.key) ActiveStorage::Blob.service.send(:path_for, image.key)
end end
# Returns the MD5 hex digest of the current screenshot's data # Returns the MD5 hex digest of the current screenshot's data
@ -98,8 +98,8 @@ class Screenshot < ApplicationRecord
Digest::MD5.hexdigest(disk_path) Digest::MD5.hexdigest(disk_path)
# remote files stored on another person's computer: # remote files stored on another person's computer:
#url = attachment.url # url = attachment.url
#Digest::MD5.base64digest(Net::HTTP.get(URI(url))) # Digest::MD5.base64digest(Net::HTTP.get(URI(url)))
end end
private private
@ -112,11 +112,9 @@ class Screenshot < ApplicationRecord
# for two different packages. Restricting that further may happen later. # for two different packages. Restricting that further may happen later.
def validate_image_is_unique def validate_image_is_unique
# Look for images with the same checksum / image_fingerprint # Look for images with the same checksum / image_fingerprint
if screenshot=Screenshot.find_by(image_fingerprint: image_fingerprint, package_id: self.package.id) if (screenshot = Screenshot.find_by(image_fingerprint: image_fingerprint,
unless screenshot.id == self.id package_id: package.id)) && !(screenshot.id == id)
errors.add(:image, "has already been uploaded for this package") errors.add(:image, 'has already been uploaded for this package')
end
end end
end end
end end

View file

@ -12,14 +12,13 @@ html
/ = stylesheet_link_tag :app, "data-turbo-track": "reload" / = stylesheet_link_tag :app, "data-turbo-track": "reload"
/ = javascript_include_tag "application", "data-turbo-track": "reload", type: "module" / = javascript_include_tag "application", "data-turbo-track": "reload", type: "module"
/ = stylesheet_link_tag "foundation", media: "all"
= stylesheet_link_tag "application", media: "all" = stylesheet_link_tag "application", media: "all"
/ = javascript_include_tag "jquery/dist/jquery.min.js"
/ = javascript_include_tag "foundation-sites/dist/js/foundation.min" / = javascript_include_tag "jquery.js", "data-turbo-track": "reload", type: "module"
= javascript_include_tag "jquery-3.7.1.min.js", "data-turbo-track": "reload", type: "module" / = javascript_include_tag "foundation", "data-turbo-track": "reload", type: "module"
= javascript_include_tag "foundation", "data-turbo-track": "reload", type: "module" / = javascript_include_tag "debshots", "data-turbo-track": "reload", type: "module"
= javascript_include_tag "debshots", "data-turbo-track": "reload", type: "module"
/ = javascript_include_tag "application", "data-turbo-track": "reload", type: "module" = javascript_importmap_tags
= csrf_meta_tags = csrf_meta_tags

View file

@ -23,5 +23,5 @@
/ ' My uploads / ' My uploads
li li
= link_to destroy_user_session_path, method: :delete = link_to destroy_user_session_path, data: { turbo_method: :delete }
= fa_icon 'lock 2x', text: 'Logout' = fa_icon 'lock 2x', text: 'Logout'

View file

@ -66,6 +66,8 @@
= render(partial: 'details_rightbox', locals: {pkg: @package}) = render(partial: 'details_rightbox', locals: {pkg: @package})
javascript: javascript:
import {upload_paste_handler} from 'aplication';
// Handle Ctrl-V to paste an image directly // Handle Ctrl-V to paste an image directly
document.onpaste = upload_paste_handler; document.onpaste = upload_paste_handler;

View file

@ -64,16 +64,18 @@ h1 = "Upload screenshots for #{@package.name}"
' from a shell using after setting "export LANG=C". ' from a shell using after setting "export LANG=C".
li can be pasted here from your clipboard (Ctrl-V) li can be pasted here from your clipboard (Ctrl-V)
/ javascript:
/ // Hide the submit button unless images are selected for upload
/ // $(document).ready(upload_form_init);
/ import upload_form_init from '../../assets/javascripts/upload.js';
/ document.addEventListener('DOMContentLoaded', upload_form_init);
javascript: / // import upload_paste_handler from '../../assets/javascripts/debshots.js';
// Hide the submit button unless images are selected for upload / // Handle Ctrl-V to paste an image directly
$(document).ready(upload_form_init); / document.onpaste = upload_paste_handler;
// Handle Ctrl-V to paste an image directly / // Where to send POST requests for uploads
document.onpaste = upload_paste_handler; / var ajax_upload_url = '#{{upload_receive_json_path}}';
// Where to send POST requests for uploads / // Where to go to after a successful image upload
var ajax_upload_url = '#{{upload_receive_json_path}}'; / var after_upload_url = '#{{package_path(@package)}}';
// Where to go to after a successful image upload
var after_upload_url = '#{{package_path(@package)}}';

View file

@ -44,7 +44,7 @@
.image .image
- if @random_pick - if @random_pick
a href=package_path(@random_pick.name) a href=package_path(@random_pick.name)
= small_img(@random_pick.screenshots.first) = small_img(@random_pick.screenshots.publicly.first)
- else - else
'No uploaded screenshots yet. 'No uploaded screenshots yet.
.text .text

4
bin/importmap Executable file
View file

@ -0,0 +1,4 @@
#!/usr/bin/env ruby
require_relative "../config/application"
require "importmap/commands"

View file

@ -2,12 +2,12 @@
"name": "app", "name": "app",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"esbuild": "^0.25.1", "esbuild": "^0.25.2",
"webpack": "^5.98.0", "webpack": "^5.98.0",
"webpack-cli": "^6.0.1" "webpack-cli": "^6.0.1"
}, },
"scripts": { "scripts": {
"build": "webpack --config webpack.config.js", "build": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets",
"build:css": "sass ./app/assets/stylesheets/application.sass.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules" "build:css": "sass ./app/assets/stylesheets/application.sass.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules"
}, },
"dependencies": { "dependencies": {
@ -17,6 +17,6 @@
"foundation-sites": "^6.9.0", "foundation-sites": "^6.9.0",
"jquery": "^3.7.1", "jquery": "^3.7.1",
"motion-ui": "^2.0.8", "motion-ui": "^2.0.8",
"sass": "^1.85.1" "sass": "^1.86.3"
} }
} }

0
vendor/javascript/.keep vendored Normal file
View file

266
yarn.lock
View file

@ -12,130 +12,130 @@
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz#f13c7c205915eb91ae54c557f5e92bddd8be0e83" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz#f13c7c205915eb91ae54c557f5e92bddd8be0e83"
integrity sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ== integrity sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==
"@esbuild/aix-ppc64@0.25.1": "@esbuild/aix-ppc64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz#c33cf6bbee34975626b01b80451cbb72b4c6c91d" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz#b87036f644f572efb2b3c75746c97d1d2d87ace8"
integrity sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ== integrity sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==
"@esbuild/android-arm64@0.25.1": "@esbuild/android-arm64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz#ea766015c7d2655164f22100d33d7f0308a28d6d" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz#5ca7dc20a18f18960ad8d5e6ef5cf7b0a256e196"
integrity sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA== integrity sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==
"@esbuild/android-arm@0.25.1": "@esbuild/android-arm@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.1.tgz#e84d2bf2fe2e6177a0facda3a575b2139fd3cb9c" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.2.tgz#3c49f607b7082cde70c6ce0c011c362c57a194ee"
integrity sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q== integrity sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==
"@esbuild/android-x64@0.25.1": "@esbuild/android-x64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.1.tgz#58337bee3bc6d78d10425e5500bd11370cfdfbed" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.2.tgz#8a00147780016aff59e04f1036e7cb1b683859e2"
integrity sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw== integrity sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==
"@esbuild/darwin-arm64@0.25.1": "@esbuild/darwin-arm64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz#a46805c1c585d451aa83be72500bd6e8495dd591" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz#486efe7599a8d90a27780f2bb0318d9a85c6c423"
integrity sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ== integrity sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==
"@esbuild/darwin-x64@0.25.1": "@esbuild/darwin-x64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz#0643e003bb238c63fc93ddbee7d26a003be3cd98" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz#95ee222aacf668c7a4f3d7ee87b3240a51baf374"
integrity sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA== integrity sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==
"@esbuild/freebsd-arm64@0.25.1": "@esbuild/freebsd-arm64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz#cff18da5469c09986b93e87979de5d6872fe8f8e" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz#67efceda8554b6fc6a43476feba068fb37fa2ef6"
integrity sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A== integrity sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==
"@esbuild/freebsd-x64@0.25.1": "@esbuild/freebsd-x64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz#362fc09c2de14987621c1878af19203c46365dde" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz#88a9d7ecdd3adadbfe5227c2122d24816959b809"
integrity sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww== integrity sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==
"@esbuild/linux-arm64@0.25.1": "@esbuild/linux-arm64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz#aa90d5b02efc97a271e124e6d1cea490634f7498" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz#87be1099b2bbe61282333b084737d46bc8308058"
integrity sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ== integrity sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==
"@esbuild/linux-arm@0.25.1": "@esbuild/linux-arm@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz#dfcefcbac60a20918b19569b4b657844d39db35a" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz#72a285b0fe64496e191fcad222185d7bf9f816f6"
integrity sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ== integrity sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==
"@esbuild/linux-ia32@0.25.1": "@esbuild/linux-ia32@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz#6f9527077ccb7953ed2af02e013d4bac69f13754" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz#337a87a4c4dd48a832baed5cbb022be20809d737"
integrity sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ== integrity sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==
"@esbuild/linux-loong64@0.25.1": "@esbuild/linux-loong64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz#287d2412a5456e5860c2839d42a4b51284d1697c" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz#1b81aa77103d6b8a8cfa7c094ed3d25c7579ba2a"
integrity sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg== integrity sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==
"@esbuild/linux-mips64el@0.25.1": "@esbuild/linux-mips64el@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz#530574b9e1bc5d20f7a4f44c5f045e26f3783d57" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz#afbe380b6992e7459bf7c2c3b9556633b2e47f30"
integrity sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg== integrity sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==
"@esbuild/linux-ppc64@0.25.1": "@esbuild/linux-ppc64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz#5d7e6b283a0b321ea42c6bc0abeb9eb99c1f5589" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz#6bf8695cab8a2b135cca1aa555226dc932d52067"
integrity sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg== integrity sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==
"@esbuild/linux-riscv64@0.25.1": "@esbuild/linux-riscv64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz#14fa0cd073c26b4ee2465d18cd1e18eea7859fa8" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz#43c2d67a1a39199fb06ba978aebb44992d7becc3"
integrity sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ== integrity sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==
"@esbuild/linux-s390x@0.25.1": "@esbuild/linux-s390x@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz#e677b4b9d1b384098752266ccaa0d52a420dc1aa" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz#419e25737ec815c6dce2cd20d026e347cbb7a602"
integrity sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ== integrity sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==
"@esbuild/linux-x64@0.25.1": "@esbuild/linux-x64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz#f1c796b78fff5ce393658313e8c58613198d9954" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz#22451f6edbba84abe754a8cbd8528ff6e28d9bcb"
integrity sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA== integrity sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==
"@esbuild/netbsd-arm64@0.25.1": "@esbuild/netbsd-arm64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz#0d280b7dfe3973f111b02d5fe9f3063b92796d29" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz#744affd3b8d8236b08c5210d828b0698a62c58ac"
integrity sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g== integrity sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==
"@esbuild/netbsd-x64@0.25.1": "@esbuild/netbsd-x64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz#be663893931a4bb3f3a009c5cc24fa9681cc71c0" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz#dbbe7521fd6d7352f34328d676af923fc0f8a78f"
integrity sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA== integrity sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==
"@esbuild/openbsd-arm64@0.25.1": "@esbuild/openbsd-arm64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz#d9021b884233673a05dc1cc26de0bf325d824217" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz#f9caf987e3e0570500832b487ce3039ca648ce9f"
integrity sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg== integrity sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==
"@esbuild/openbsd-x64@0.25.1": "@esbuild/openbsd-x64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz#9f1dc1786ed2e2938c404b06bcc48be9a13250de" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz#d2bb6a0f8ffea7b394bb43dfccbb07cabd89f768"
integrity sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw== integrity sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==
"@esbuild/sunos-x64@0.25.1": "@esbuild/sunos-x64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz#89aac24a4b4115959b3f790192cf130396696c27" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz#49b437ed63fe333b92137b7a0c65a65852031afb"
integrity sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg== integrity sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==
"@esbuild/win32-arm64@0.25.1": "@esbuild/win32-arm64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz#354358647a6ea98ea6d243bf48bdd7a434999582" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz#081424168463c7d6c7fb78f631aede0c104373cf"
integrity sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ== integrity sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==
"@esbuild/win32-ia32@0.25.1": "@esbuild/win32-ia32@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz#8cea7340f2647eba951a041dc95651e3908cd4cb" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz#3f9e87143ddd003133d21384944a6c6cadf9693f"
integrity sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A== integrity sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==
"@esbuild/win32-x64@0.25.1": "@esbuild/win32-x64@0.25.2":
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz#7d79922cb2d88f9048f06393dbf62d2e4accb584" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz#839f72c2decd378f86b8f525e1979a97b920c67d"
integrity sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg== integrity sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==
"@hotwired/stimulus@^3.2.2": "@hotwired/stimulus@^3.2.2":
version "3.2.2" version "3.2.2"
@ -619,36 +619,36 @@ es-module-lexer@^1.2.1:
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.6.0.tgz#da49f587fd9e68ee2404fe4e256c0c7d3a81be21" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.6.0.tgz#da49f587fd9e68ee2404fe4e256c0c7d3a81be21"
integrity sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ== integrity sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==
esbuild@^0.25.1: esbuild@^0.25.2:
version "0.25.1" version "0.25.2"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.1.tgz#a16b8d070b6ad4871935277bda6ccfe852e3fa2f" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.2.tgz#55a1d9ebcb3aa2f95e8bba9e900c1a5061bc168b"
integrity sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ== integrity sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==
optionalDependencies: optionalDependencies:
"@esbuild/aix-ppc64" "0.25.1" "@esbuild/aix-ppc64" "0.25.2"
"@esbuild/android-arm" "0.25.1" "@esbuild/android-arm" "0.25.2"
"@esbuild/android-arm64" "0.25.1" "@esbuild/android-arm64" "0.25.2"
"@esbuild/android-x64" "0.25.1" "@esbuild/android-x64" "0.25.2"
"@esbuild/darwin-arm64" "0.25.1" "@esbuild/darwin-arm64" "0.25.2"
"@esbuild/darwin-x64" "0.25.1" "@esbuild/darwin-x64" "0.25.2"
"@esbuild/freebsd-arm64" "0.25.1" "@esbuild/freebsd-arm64" "0.25.2"
"@esbuild/freebsd-x64" "0.25.1" "@esbuild/freebsd-x64" "0.25.2"
"@esbuild/linux-arm" "0.25.1" "@esbuild/linux-arm" "0.25.2"
"@esbuild/linux-arm64" "0.25.1" "@esbuild/linux-arm64" "0.25.2"
"@esbuild/linux-ia32" "0.25.1" "@esbuild/linux-ia32" "0.25.2"
"@esbuild/linux-loong64" "0.25.1" "@esbuild/linux-loong64" "0.25.2"
"@esbuild/linux-mips64el" "0.25.1" "@esbuild/linux-mips64el" "0.25.2"
"@esbuild/linux-ppc64" "0.25.1" "@esbuild/linux-ppc64" "0.25.2"
"@esbuild/linux-riscv64" "0.25.1" "@esbuild/linux-riscv64" "0.25.2"
"@esbuild/linux-s390x" "0.25.1" "@esbuild/linux-s390x" "0.25.2"
"@esbuild/linux-x64" "0.25.1" "@esbuild/linux-x64" "0.25.2"
"@esbuild/netbsd-arm64" "0.25.1" "@esbuild/netbsd-arm64" "0.25.2"
"@esbuild/netbsd-x64" "0.25.1" "@esbuild/netbsd-x64" "0.25.2"
"@esbuild/openbsd-arm64" "0.25.1" "@esbuild/openbsd-arm64" "0.25.2"
"@esbuild/openbsd-x64" "0.25.1" "@esbuild/openbsd-x64" "0.25.2"
"@esbuild/sunos-x64" "0.25.1" "@esbuild/sunos-x64" "0.25.2"
"@esbuild/win32-arm64" "0.25.1" "@esbuild/win32-arm64" "0.25.2"
"@esbuild/win32-ia32" "0.25.1" "@esbuild/win32-ia32" "0.25.2"
"@esbuild/win32-x64" "0.25.1" "@esbuild/win32-x64" "0.25.2"
escalade@^3.2.0: escalade@^3.2.0:
version "3.2.0" version "3.2.0"
@ -1157,10 +1157,10 @@ sass-embedded@^1.79.3:
sass-embedded-win32-ia32 "1.85.1" sass-embedded-win32-ia32 "1.85.1"
sass-embedded-win32-x64 "1.85.1" sass-embedded-win32-x64 "1.85.1"
sass@^1.85.1: sass@^1.86.3:
version "1.85.1" version "1.86.3"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.85.1.tgz#18ab0bb48110ae99163778f06445b406148ca0d5" resolved "https://registry.yarnpkg.com/sass/-/sass-1.86.3.tgz#0a0d9ea97cb6665e73f409639f8533ce057464c9"
integrity sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag== integrity sha512-iGtg8kus4GrsGLRDLRBRHY9dNVA78ZaS7xr01cWnS7PEMQyFtTqBiyCrfpTYTZXRWM94akzckYjh8oADfFNTzw==
dependencies: dependencies:
chokidar "^4.0.0" chokidar "^4.0.0"
immutable "^5.0.2" immutable "^5.0.2"