Init project
This commit is contained in:
17
.editorconfig
Normal file
17
.editorconfig
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# editorconfig.org
|
||||||
|
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[{compose.yaml,compose.*.yaml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
47
.env
Normal file
47
.env
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# In all environments, the following files are loaded if they exist,
|
||||||
|
# the latter taking precedence over the former:
|
||||||
|
#
|
||||||
|
# * .env contains default values for the environment variables needed by the app
|
||||||
|
# * .env.local uncommitted file with local overrides
|
||||||
|
# * .env.$APP_ENV committed environment-specific defaults
|
||||||
|
# * .env.$APP_ENV.local uncommitted environment-specific overrides
|
||||||
|
#
|
||||||
|
# Real environment variables win over .env files.
|
||||||
|
#
|
||||||
|
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
|
||||||
|
# https://symfony.com/doc/current/configuration/secrets.html
|
||||||
|
#
|
||||||
|
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
|
||||||
|
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
|
||||||
|
|
||||||
|
###> symfony/framework-bundle ###
|
||||||
|
APP_ENV=dev
|
||||||
|
APP_SECRET=
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
|
||||||
|
###> symfony/routing ###
|
||||||
|
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
|
||||||
|
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
|
||||||
|
DEFAULT_URI=http://localhost
|
||||||
|
###< symfony/routing ###
|
||||||
|
|
||||||
|
###> doctrine/doctrine-bundle ###
|
||||||
|
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||||
|
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
|
||||||
|
#
|
||||||
|
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data_%kernel.environment%.db"
|
||||||
|
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
|
||||||
|
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
|
||||||
|
DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
|
||||||
|
###< doctrine/doctrine-bundle ###
|
||||||
|
|
||||||
|
###> symfony/messenger ###
|
||||||
|
# Choose one of the transports below
|
||||||
|
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
|
||||||
|
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
|
||||||
|
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
|
||||||
|
###< symfony/messenger ###
|
||||||
|
|
||||||
|
###> symfony/mailer ###
|
||||||
|
MAILER_DSN=null://null
|
||||||
|
###< symfony/mailer ###
|
||||||
4
.env.dev
Normal file
4
.env.dev
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
###> symfony/framework-bundle ###
|
||||||
|
APP_SECRET=a67d1dd72d40ab0515ec1158403570b6
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
3
.env.test
Normal file
3
.env.test
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# define your env variables for the test env here
|
||||||
|
KERNEL_CLASS='App\Kernel'
|
||||||
|
APP_SECRET='$ecretf0rt3st'
|
||||||
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
###> symfony/framework-bundle ###
|
||||||
|
/.env.local
|
||||||
|
/.env.local.php
|
||||||
|
/.env.*.local
|
||||||
|
/config/secrets/prod/prod.decrypt.private.php
|
||||||
|
/public/bundles/
|
||||||
|
/var/
|
||||||
|
/vendor/
|
||||||
|
###< symfony/framework-bundle ###
|
||||||
|
|
||||||
|
###> phpunit/phpunit ###
|
||||||
|
/phpunit.xml
|
||||||
|
/.phpunit.cache/
|
||||||
|
###< phpunit/phpunit ###
|
||||||
|
|
||||||
|
###> symfony/webpack-encore-bundle ###
|
||||||
|
/node_modules/
|
||||||
|
/public/build/
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
###< symfony/webpack-encore-bundle ###
|
||||||
|
|
||||||
|
/.vscode
|
||||||
|
/.zed
|
||||||
14
.prettierrc
Normal file
14
.prettierrc
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["@zackad/prettier-plugin-twig"],
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.jsonc"],
|
||||||
|
"options": {
|
||||||
|
"parser": "json",
|
||||||
|
"trailingComma": "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
12
assets/app.js
Normal file
12
assets/app.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import "./stimulus_bootstrap.js";
|
||||||
|
/*
|
||||||
|
* Welcome to your app's main JavaScript file!
|
||||||
|
*
|
||||||
|
* We recommend including the built version of this JavaScript file
|
||||||
|
* (and its CSS file) in your base layout (base.html.twig).
|
||||||
|
*/
|
||||||
|
|
||||||
|
// any CSS you import will output into a single css file (app.css in this case)
|
||||||
|
import "./styles/app.css";
|
||||||
|
import "./js/ckeditor-init.js";
|
||||||
|
import "./styles/css/ckeditor5.css";
|
||||||
15
assets/controllers.json
Normal file
15
assets/controllers.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"controllers": {
|
||||||
|
"@symfony/ux-turbo": {
|
||||||
|
"turbo-core": {
|
||||||
|
"enabled": true,
|
||||||
|
"fetch": "eager"
|
||||||
|
},
|
||||||
|
"mercure-turbo-stream": {
|
||||||
|
"enabled": false,
|
||||||
|
"fetch": "eager"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"entrypoints": []
|
||||||
|
}
|
||||||
15
assets/controllers/ckeditor5_controller.js
Normal file
15
assets/controllers/ckeditor5_controller.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// assets/controllers/ckeditor5_controller.js
|
||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
import EnhancedEditor from "../js/ckeditor-init.js";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
connect() {
|
||||||
|
this.editor = EnhancedEditor.create(this.element)
|
||||||
|
.then(editor => (this.editor = editor))
|
||||||
|
.catch(error => console.error(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
this.editor.destroy().catch(error => console.error(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = [
|
||||||
|
"loaderWrapper",
|
||||||
|
"loaderProgressBar",
|
||||||
|
"list",
|
||||||
|
"imagesWrapper",
|
||||||
|
];
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
if (!this.hasListTarget || !this.hasImagesWrapperTarget) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const images = Array.from(this.listTarget.querySelectorAll("img"));
|
||||||
|
|
||||||
|
// 1️⃣ avant chargement → tout cacher
|
||||||
|
this.loaderWrapperTarget.classList.add("hidden");
|
||||||
|
this.imagesWrapperTarget.style.opacity = 0;
|
||||||
|
|
||||||
|
if (images.length > 0) {
|
||||||
|
this.trackImages(images);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trackImages(images) {
|
||||||
|
let loadedCount = 0;
|
||||||
|
|
||||||
|
// 2️⃣ début du chargement → afficher le loader
|
||||||
|
this.loaderWrapperTarget.classList.remove("hidden");
|
||||||
|
this.loaderProgressBarTarget.style.width = "0%";
|
||||||
|
|
||||||
|
images.forEach((img) => {
|
||||||
|
if (img.complete) {
|
||||||
|
loadedCount++;
|
||||||
|
this.updateProgress(loadedCount, images.length);
|
||||||
|
} else {
|
||||||
|
img.addEventListener("load", () => {
|
||||||
|
loadedCount++;
|
||||||
|
this.updateProgress(loadedCount, images.length);
|
||||||
|
});
|
||||||
|
img.addEventListener("error", () => {
|
||||||
|
loadedCount++;
|
||||||
|
this.updateProgress(loadedCount, images.length);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProgress(loadedCount, total) {
|
||||||
|
const progress = (loadedCount / total) * 100;
|
||||||
|
this.loaderProgressBarTarget.style.width = `${progress}%`;
|
||||||
|
|
||||||
|
if (loadedCount === total) {
|
||||||
|
// 3️⃣ chargement terminé → masquer le loader + afficher les images
|
||||||
|
setTimeout(() => {
|
||||||
|
this.loaderWrapperTarget.classList.add("hidden");
|
||||||
|
|
||||||
|
this.imagesWrapperTarget.style.transition = "opacity .3s ease";
|
||||||
|
this.imagesWrapperTarget.style.opacity = 1;
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
81
assets/controllers/csrf_protection_controller.js
Normal file
81
assets/controllers/csrf_protection_controller.js
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
const nameCheck = /^[-_a-zA-Z0-9]{4,22}$/;
|
||||||
|
const tokenCheck = /^[-_/+a-zA-Z0-9]{24,}$/;
|
||||||
|
|
||||||
|
// Generate and double-submit a CSRF token in a form field and a cookie, as defined by Symfony's SameOriginCsrfTokenManager
|
||||||
|
// Use `form.requestSubmit()` to ensure that the submit event is triggered. Using `form.submit()` will not trigger the event
|
||||||
|
// and thus this event-listener will not be executed.
|
||||||
|
document.addEventListener('submit', function (event) {
|
||||||
|
generateCsrfToken(event.target);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
// When @hotwired/turbo handles form submissions, send the CSRF token in a header in addition to a cookie
|
||||||
|
// The `framework.csrf_protection.check_header` config option needs to be enabled for the header to be checked
|
||||||
|
document.addEventListener('turbo:submit-start', function (event) {
|
||||||
|
const h = generateCsrfHeaders(event.detail.formSubmission.formElement);
|
||||||
|
Object.keys(h).map(function (k) {
|
||||||
|
event.detail.formSubmission.fetchRequest.headers[k] = h[k];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// When @hotwired/turbo handles form submissions, remove the CSRF cookie once a form has been submitted
|
||||||
|
document.addEventListener('turbo:submit-end', function (event) {
|
||||||
|
removeCsrfToken(event.detail.formSubmission.formElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
export function generateCsrfToken (formElement) {
|
||||||
|
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
|
||||||
|
|
||||||
|
if (!csrfField) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
|
||||||
|
let csrfToken = csrfField.value;
|
||||||
|
|
||||||
|
if (!csrfCookie && nameCheck.test(csrfToken)) {
|
||||||
|
csrfField.setAttribute('data-csrf-protection-cookie-value', csrfCookie = csrfToken);
|
||||||
|
csrfField.defaultValue = csrfToken = btoa(String.fromCharCode.apply(null, (window.crypto || window.msCrypto).getRandomValues(new Uint8Array(18))));
|
||||||
|
}
|
||||||
|
csrfField.dispatchEvent(new Event('change', { bubbles: true }));
|
||||||
|
|
||||||
|
if (csrfCookie && tokenCheck.test(csrfToken)) {
|
||||||
|
const cookie = csrfCookie + '_' + csrfToken + '=' + csrfCookie + '; path=/; samesite=strict';
|
||||||
|
document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateCsrfHeaders (formElement) {
|
||||||
|
const headers = {};
|
||||||
|
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
|
||||||
|
|
||||||
|
if (!csrfField) {
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
|
||||||
|
|
||||||
|
if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) {
|
||||||
|
headers[csrfCookie] = csrfField.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeCsrfToken (formElement) {
|
||||||
|
const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]');
|
||||||
|
|
||||||
|
if (!csrfField) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value');
|
||||||
|
|
||||||
|
if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) {
|
||||||
|
const cookie = csrfCookie + '_' + csrfField.value + '=0; path=/; samesite=strict; max-age=0';
|
||||||
|
|
||||||
|
document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stimulusFetch: 'lazy' */
|
||||||
|
export default 'csrf-protection-controller';
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
connect() {
|
||||||
|
let usersTable = document.getElementById("users-table");
|
||||||
|
if (!usersTable) return;
|
||||||
|
let toggleAllCheckbox = usersTable.querySelector(
|
||||||
|
"thead input[type='checkbox']",
|
||||||
|
);
|
||||||
|
let checkboxes = [
|
||||||
|
...usersTable.querySelectorAll("tbody input[type='checkbox']"),
|
||||||
|
];
|
||||||
|
|
||||||
|
toggleAllCheckbox.addEventListener("change", (event) => {
|
||||||
|
checkboxes.forEach((checkbox) => {
|
||||||
|
checkbox.checked = event.target.checked;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
checkboxes.forEach((checkbox) => {
|
||||||
|
checkbox.addEventListener("change", () => {
|
||||||
|
let allChecked = checkboxes.every((checkbox) => checkbox.checked);
|
||||||
|
let someChecked = checkboxes.some((checkbox) => checkbox.checked);
|
||||||
|
toggleAllCheckbox.checked = someChecked;
|
||||||
|
toggleAllCheckbox.indeterminate = someChecked && !allChecked;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
16
assets/controllers/hello_controller.js
Normal file
16
assets/controllers/hello_controller.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { Controller } from '@hotwired/stimulus';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is an example Stimulus controller!
|
||||||
|
*
|
||||||
|
* Any element with a data-controller="hello" attribute will cause
|
||||||
|
* this controller to be executed. The name "hello" comes from the filename:
|
||||||
|
* hello_controller.js -> "hello"
|
||||||
|
*
|
||||||
|
* Delete this file or adapt it for your use!
|
||||||
|
*/
|
||||||
|
export default class extends Controller {
|
||||||
|
connect() {
|
||||||
|
this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
|
||||||
|
}
|
||||||
|
}
|
||||||
26
assets/controllers/image/delete_img_modal_controller.js
Normal file
26
assets/controllers/image/delete_img_modal_controller.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = ["dialog", "form", "token"];
|
||||||
|
|
||||||
|
open(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const button = event.currentTarget;
|
||||||
|
|
||||||
|
// Récupère l'URL et le token depuis le bouton
|
||||||
|
const url = button.dataset.url;
|
||||||
|
const csrfToken = button.dataset.token;
|
||||||
|
|
||||||
|
// Remplit le formulaire de la modale
|
||||||
|
this.formTarget.action = url;
|
||||||
|
this.tokenTarget.value = csrfToken;
|
||||||
|
|
||||||
|
this.dialogTarget.classList.remove("hidden");
|
||||||
|
this.dialogTarget.classList.add("flex");
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.dialogTarget.classList.add("hidden");
|
||||||
|
this.dialogTarget.classList.remove("flex");
|
||||||
|
}
|
||||||
|
}
|
||||||
66
assets/controllers/image/drop_zone_controller.js
Normal file
66
assets/controllers/image/drop_zone_controller.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = ["input", "preview", "loader"];
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
this.element.addEventListener("dragover", this.dragOver.bind(this));
|
||||||
|
this.element.addEventListener("dragleave", this.dragLeave.bind(this));
|
||||||
|
this.element.addEventListener("drop", this.drop.bind(this));
|
||||||
|
|
||||||
|
this.inputTarget.addEventListener("change", (event) => {
|
||||||
|
this.handleFiles(this.inputTarget.files);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dragOver(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.element.classList.add("border-amber-600");
|
||||||
|
}
|
||||||
|
|
||||||
|
dragLeave(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.element.classList.remove("border-amber-600");
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.element.classList.remove("border-amber-600");
|
||||||
|
this.handleFiles(event.dataTransfer.files);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFiles(files) {
|
||||||
|
const formData = new FormData();
|
||||||
|
this.previewTarget.innerHTML = "";
|
||||||
|
|
||||||
|
Array.from(files).forEach((file) => {
|
||||||
|
formData.append("file-upload[]", file);
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e) => {
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = e.target.result;
|
||||||
|
img.className = "h-24 w-24 object-cover rounded border";
|
||||||
|
this.previewTarget.appendChild(img);
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.uploadFiles(formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
async uploadFiles(formData) {
|
||||||
|
this.loaderTarget.style.display = "block";
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fetch("/admin/image/upload", {
|
||||||
|
method: "POST",
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Upload error:", err);
|
||||||
|
} finally {
|
||||||
|
this.loaderTarget.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
assets/controllers/news/delete_controller.js
Normal file
23
assets/controllers/news/delete_controller.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = ["dialog", "form", "token"];
|
||||||
|
|
||||||
|
open(event) {
|
||||||
|
const button = event.currentTarget;
|
||||||
|
const url = button.dataset.url;
|
||||||
|
const token = button.dataset.token;
|
||||||
|
|
||||||
|
// Remplit le formulaire avec les bonnes données
|
||||||
|
this.formTarget.action = url;
|
||||||
|
this.tokenTarget.value = token;
|
||||||
|
|
||||||
|
this.dialogTarget.classList.remove("hidden");
|
||||||
|
this.dialogTarget.classList.add("flex");
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.dialogTarget.classList.add("hidden");
|
||||||
|
this.dialogTarget.classList.remove("flex");
|
||||||
|
}
|
||||||
|
}
|
||||||
165
assets/controllers/news/edit_image_selector_controller.js
Normal file
165
assets/controllers/news/edit_image_selector_controller.js
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
import Sortable from "sortablejs";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = [
|
||||||
|
"input",
|
||||||
|
"preview",
|
||||||
|
"list",
|
||||||
|
"card",
|
||||||
|
"checkbox",
|
||||||
|
"checkIcon",
|
||||||
|
"overlay",
|
||||||
|
"count",
|
||||||
|
];
|
||||||
|
|
||||||
|
sortable = null;
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
this.restoreInitialSelection();
|
||||||
|
this.enableSortable();
|
||||||
|
this.updateCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// 1) Restaurer auto la sélection existante (images déjà liées)
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
restoreInitialSelection() {
|
||||||
|
this.previewTarget.innerHTML = "";
|
||||||
|
const selectedIds = [
|
||||||
|
...document.querySelectorAll('input[name="selectedImages[]"]'),
|
||||||
|
].map((input) => input.value);
|
||||||
|
|
||||||
|
// coche les bonnes cases dans la modale
|
||||||
|
this.checkboxTargets.forEach((checkbox) => {
|
||||||
|
if (selectedIds.includes(checkbox.value)) {
|
||||||
|
checkbox.checked = true;
|
||||||
|
this.updateCard(checkbox.closest("label"), true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ajoute dans le preview
|
||||||
|
selectedIds.forEach((id) => {
|
||||||
|
const card = this.cardTargets.find((c) => c.dataset.id === id);
|
||||||
|
if (!card) return;
|
||||||
|
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = card.dataset.url;
|
||||||
|
img.dataset.id = id;
|
||||||
|
img.className = "w-20 h-20 rounded object-cover cursor-move";
|
||||||
|
|
||||||
|
this.previewTarget.appendChild(img);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// 2) Sélection dans la modale
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
cardClick(event) {
|
||||||
|
const card = event.currentTarget;
|
||||||
|
const checkbox = card.querySelector("input[type='checkbox']");
|
||||||
|
checkbox.checked = !checkbox.checked;
|
||||||
|
|
||||||
|
this.updateCard(card, checkbox.checked);
|
||||||
|
this.updateCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleCheckbox(event) {
|
||||||
|
const checkbox = event.currentTarget;
|
||||||
|
const card = checkbox.closest("label");
|
||||||
|
|
||||||
|
this.updateCard(card, checkbox.checked);
|
||||||
|
this.updateCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCard(card, checked) {
|
||||||
|
const icon = card.querySelector(
|
||||||
|
"[data-news--edit-image-selector-target='checkIcon']",
|
||||||
|
);
|
||||||
|
const overlay = card.querySelector(
|
||||||
|
"[data-news--edit-image-selector-target='overlay']",
|
||||||
|
);
|
||||||
|
if (icon) icon.classList.toggle("hidden", !checked);
|
||||||
|
if (overlay) overlay.classList.toggle("hidden", !checked);
|
||||||
|
|
||||||
|
card.classList.toggle("ring-4", checked);
|
||||||
|
card.classList.toggle("ring-amber-500", checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCount() {
|
||||||
|
const total = this.checkboxTargets.filter((c) => c.checked).length;
|
||||||
|
|
||||||
|
if (this.hasCountTarget) {
|
||||||
|
this.countTarget.textContent = `${total} sélectionnée(s)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// 3) Validation depuis la modale → update preview + ordre
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
validate() {
|
||||||
|
const selected = this.checkboxTargets
|
||||||
|
.filter((c) => c.checked)
|
||||||
|
.map((c) => c.value);
|
||||||
|
|
||||||
|
// 🔥 RESET COMPLET
|
||||||
|
this.previewTarget.innerHTML = "";
|
||||||
|
|
||||||
|
// 🔁 RECONSTRUCTION PROPRE
|
||||||
|
selected.forEach((id) => {
|
||||||
|
const card = this.cardTargets.find((c) => c.dataset.id === id);
|
||||||
|
if (!card) return;
|
||||||
|
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = card.dataset.url;
|
||||||
|
img.dataset.id = id;
|
||||||
|
img.className = "w-20 h-20 rounded object-cover cursor-move";
|
||||||
|
|
||||||
|
this.previewTarget.appendChild(img);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.enableSortable();
|
||||||
|
this.updateOrder();
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelector("[command='close'][commandfor='edit-news-image-dialog']")
|
||||||
|
.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// 4) Drag & drop
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
enableSortable() {
|
||||||
|
if (this.sortable) this.sortable.destroy();
|
||||||
|
|
||||||
|
this.sortable = Sortable.create(this.previewTarget, {
|
||||||
|
animation: 150,
|
||||||
|
ghostClass: "opacity-40",
|
||||||
|
onSort: () => this.updateOrder(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOrder() {
|
||||||
|
const form = this.previewTarget.closest("form");
|
||||||
|
|
||||||
|
// supprime uniquement les inputs dynamiques
|
||||||
|
form
|
||||||
|
.querySelectorAll(
|
||||||
|
'input[name="selectedImages[]"]:not([data-permanent="true"])',
|
||||||
|
)
|
||||||
|
.forEach((i) => i.remove());
|
||||||
|
|
||||||
|
// recréer les inputs cachés
|
||||||
|
Array.from(this.previewTarget.children).forEach((img) => {
|
||||||
|
const hidden = document.createElement("input");
|
||||||
|
hidden.type = "hidden";
|
||||||
|
hidden.name = "selectedImages[]";
|
||||||
|
hidden.value = img.dataset.id;
|
||||||
|
form.appendChild(hidden);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
126
assets/controllers/news/image_selector_controller.js
Normal file
126
assets/controllers/news/image_selector_controller.js
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
import Sortable from "sortablejs";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = [
|
||||||
|
"container",
|
||||||
|
"input",
|
||||||
|
"preview",
|
||||||
|
"list",
|
||||||
|
"card",
|
||||||
|
"checkbox",
|
||||||
|
"checkIcon",
|
||||||
|
"count",
|
||||||
|
];
|
||||||
|
|
||||||
|
sortable = null;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// Sélection normale
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
cardClick(event) {
|
||||||
|
const card = event.currentTarget;
|
||||||
|
const checkbox = card.querySelector("input[type='checkbox']");
|
||||||
|
checkbox.checked = !checkbox.checked;
|
||||||
|
this.updateCard(card, checkbox.checked);
|
||||||
|
this.updateCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleCheckbox(event) {
|
||||||
|
const checkbox = event.currentTarget;
|
||||||
|
const card = checkbox.closest("label");
|
||||||
|
this.updateCard(card, checkbox.checked);
|
||||||
|
this.updateCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCard(card, checked) {
|
||||||
|
const icon = card.querySelector(
|
||||||
|
"[data-news--image-selector-target='checkIcon']",
|
||||||
|
);
|
||||||
|
|
||||||
|
const overlay = card.querySelector(
|
||||||
|
"[data-news--image-selector-target='overlay']",
|
||||||
|
);
|
||||||
|
|
||||||
|
icon.classList.toggle("hidden", !checked);
|
||||||
|
overlay.classList.toggle("hidden", !checked);
|
||||||
|
|
||||||
|
card.classList.toggle("ring-4", checked);
|
||||||
|
card.classList.toggle("ring-amber-500", checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCount() {
|
||||||
|
const total = this.checkboxTargets.filter((c) => c.checked).length;
|
||||||
|
if (this.hasCountTarget) {
|
||||||
|
this.countTarget.textContent = `${total} sélectionnée(s)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// Validation → création du preview + activation du drag&drop
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
validate() {
|
||||||
|
const selected = this.checkboxTargets
|
||||||
|
.filter((c) => c.checked)
|
||||||
|
.map((c) => c.value);
|
||||||
|
|
||||||
|
// 🔥 RESET TOTAL DU PREVIEW
|
||||||
|
this.previewTarget.innerHTML = "";
|
||||||
|
|
||||||
|
// 🔁 RECONSTRUCTION À PARTIR DE LA SOURCE DE VÉRITÉ
|
||||||
|
selected.forEach((id) => {
|
||||||
|
const card = this.cardTargets.find((c) => c.dataset.id === id);
|
||||||
|
if (!card) return;
|
||||||
|
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = card.dataset.url;
|
||||||
|
img.dataset.id = id;
|
||||||
|
img.className = "w-20 h-20 rounded object-cover cursor-move";
|
||||||
|
|
||||||
|
this.previewTarget.appendChild(img);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.enableSortable();
|
||||||
|
this.updateOrder();
|
||||||
|
|
||||||
|
// ferme la modale
|
||||||
|
document.querySelector("[command='close'][commandfor='dialog']").click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
// SortableJS (drag & drop)
|
||||||
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
|
enableSortable() {
|
||||||
|
if (this.sortable) {
|
||||||
|
this.sortable.destroy(); // reset si déjà actif
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sortable = Sortable.create(this.previewTarget, {
|
||||||
|
animation: 150,
|
||||||
|
ghostClass: "opacity-40",
|
||||||
|
onSort: () => {
|
||||||
|
this.updateOrder();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOrder() {
|
||||||
|
// Supprime les anciennes valeurs
|
||||||
|
const container = this.previewTarget.closest("form");
|
||||||
|
container
|
||||||
|
.querySelectorAll('input[name="selectedImages[]"]')
|
||||||
|
.forEach((i) => i.remove());
|
||||||
|
|
||||||
|
// Crée un input caché par image dans l'ordre
|
||||||
|
Array.from(this.previewTarget.children).forEach((img) => {
|
||||||
|
const hidden = document.createElement("input");
|
||||||
|
hidden.type = "hidden";
|
||||||
|
hidden.name = "selectedImages[]";
|
||||||
|
hidden.value = img.dataset.id;
|
||||||
|
container.appendChild(hidden);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
33
assets/controllers/news/sortable_controller.js
Normal file
33
assets/controllers/news/sortable_controller.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import Sortable from "sortablejs";
|
||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
static values = {
|
||||||
|
url: String,
|
||||||
|
};
|
||||||
|
|
||||||
|
static targets = ["item"];
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
this.sortable = new Sortable(this.element, {
|
||||||
|
animation: 150,
|
||||||
|
handle: '[data-news--sortable-target="handle"]',
|
||||||
|
onEnd: this.reorder.bind(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
reorder() {
|
||||||
|
const order = this.itemTargets.map((el, index) => ({
|
||||||
|
id: el.dataset.id,
|
||||||
|
position: index + 1,
|
||||||
|
}));
|
||||||
|
|
||||||
|
fetch(this.urlValue, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ order }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// assets/controllers/news_carroussel_controller.js
|
||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
import Swiper from "swiper";
|
||||||
|
import { Navigation, Pagination } from "swiper/modules";
|
||||||
|
|
||||||
|
import "swiper/css";
|
||||||
|
import "swiper/css/navigation";
|
||||||
|
import "swiper/css/pagination";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
connect() {
|
||||||
|
this.swiper = new Swiper(this.element, {
|
||||||
|
modules: [Navigation, Pagination],
|
||||||
|
slidesPerView: 1,
|
||||||
|
spaceBetween: 24,
|
||||||
|
loop: true,
|
||||||
|
|
||||||
|
pagination: {
|
||||||
|
el: ".swiper-pagination",
|
||||||
|
clickable: true,
|
||||||
|
dynamicBullets: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
navigation: {
|
||||||
|
nextEl: ".swiper-button-next",
|
||||||
|
prevEl: ".swiper-button-prev",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
if (this.swiper) {
|
||||||
|
this.swiper.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
assets/controllers/year_controller.js
Normal file
8
assets/controllers/year_controller.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { Controller } from "@hotwired/stimulus";
|
||||||
|
|
||||||
|
export default class extends Controller {
|
||||||
|
connect() {
|
||||||
|
const year = new Date().getFullYear();
|
||||||
|
this.element.innerHTML = `© ${year} Arts-ticule, Tous droits réservés.`;
|
||||||
|
}
|
||||||
|
}
|
||||||
55
assets/js/CKEditor/LICENSE-ckeditor5.md
Normal file
55
assets/js/CKEditor/LICENSE-ckeditor5.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
Software License Agreement
|
||||||
|
==========================
|
||||||
|
|
||||||
|
**CKEditor 5** (https://github.com/ckeditor/ckeditor5)<br>
|
||||||
|
Copyright (c) 2003–2025, [CKSource Holding sp. z o.o.](https://cksource.com) All rights reserved.
|
||||||
|
|
||||||
|
Licensed under a dual-license model, this software is available under:
|
||||||
|
|
||||||
|
* the [GNU General Public License Version 2 or later](https://www.gnu.org/licenses/gpl.html) (see COPYING.GPL),
|
||||||
|
* or commercial license terms from CKSource Holding sp. z o.o.
|
||||||
|
|
||||||
|
For more information, see: [https://ckeditor.com/legal/ckeditor-licensing-options](https://ckeditor.com/legal/ckeditor-licensing-options).
|
||||||
|
|
||||||
|
If you are using CKEditor under commercial terms, you are free to remove the COPYING.GPL file with the full copy of a GPL license.
|
||||||
|
|
||||||
|
Sources of Intellectual Property Included in CKEditor 5
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
Where not otherwise indicated, all CKEditor 5 content is authored by CKSource engineers and consists of CKSource-owned intellectual property. In some specific instances, CKEditor 5 will incorporate work done by developers outside of CKSource with their express permission.
|
||||||
|
|
||||||
|
The following libraries are included in CKEditor 5 under the [ISC license](https://opensource.org/licenses/ISC):
|
||||||
|
|
||||||
|
* hast-util-from-dom - Copyright (c) Keith McKnight <keith@mcknig.ht>.
|
||||||
|
* rehype-dom-parse - Copyright (c) 2018 Keith McKnight <keith@mcknig.ht>.
|
||||||
|
* rehype-dom-stringify - Copyright (c) 2018 Keith McKnight <keith@mcknig.ht>.
|
||||||
|
|
||||||
|
The following libraries are included in CKEditor 5 under the [MIT license](https://opensource.org/licenses/MIT):
|
||||||
|
|
||||||
|
* @types/color-convert - Copyright (c) Microsoft Corporation.
|
||||||
|
* @types/hast - Copyright (c) Microsoft Corporation.
|
||||||
|
* blurhash - Copyright (c) 2018 Wolt Enterprises.
|
||||||
|
* color-convert - Copyright (c) 2011-2016 Heather Arthur <fayearthur@gmail.com> and Copyright (c) 2016-2021 Josh Junon <josh@junon.me>.
|
||||||
|
* color-parse - Copyright (c) 2015 Dmitry Ivanov.
|
||||||
|
* emojibase-data - Copyright (c) 2017-2019 Miles Johnson.
|
||||||
|
* es-toolkit - Copyright (c) 2024 Viva Republica, Inc.
|
||||||
|
* fuzzysort - Copyright (c) 2018 Stephen Kamenar.
|
||||||
|
* hast-util-to-html - Copyright (c) Titus Wormer <tituswormer@gmail.com>.
|
||||||
|
* hast-util-to-mdast - Copyright (c) Titus Wormer <tituswormer@gmail.com> and Copyright (c) Seth Vincent <sethvincent@gmail.com>.
|
||||||
|
* hastscript - Copyright (c) Titus Wormer <tituswormer@gmail.com>.
|
||||||
|
* is-emoji-supported - Copyright (c) 2016-2020 Koala Interactive, Inc.
|
||||||
|
* Regular expression for URL validation - Copyright (c) 2010-2018 Diego Perini.
|
||||||
|
* rehype-remark - Copyright (c) Titus Wormer <tituswormer@gmail.com>.
|
||||||
|
* remark-breaks - Copyright (c) 2017 Titus Wormer <tituswormer@gmail.com>.
|
||||||
|
* remark-gfm - Copyright (c) Titus Wormer <tituswormer@gmail.com>.
|
||||||
|
* remark-parse - Copyright (c) 2014 Titus Wormer <tituswormer@gmail.com>.
|
||||||
|
* remark-rehype - Copyright (c) Titus Wormer <tituswormer@gmail.com>.
|
||||||
|
* remark-stringify - Copyright (c) 2014 Titus Wormer <tituswormer@gmail.com>.
|
||||||
|
* unified - Copyright (c) 2015 Titus Wormer <tituswormer@gmail.com>.
|
||||||
|
* unist-util-visit - Copyright (c) 2015 Titus Wormer <tituswormer@gmail.com>.
|
||||||
|
* vanilla-colorful - Copyright (c) 2020 Serhii Kulykov <iamkulykov@gmail.com>.
|
||||||
|
|
||||||
|
Trademarks
|
||||||
|
----------
|
||||||
|
|
||||||
|
**CKEditor** is a trademark of [CKSource Holding sp. z o.o.](https://cksource.com) All other brand and product names are trademarks, registered trademarks or service marks of their respective holders.
|
||||||
6
assets/js/CKEditor/ckeditor5.js
Normal file
6
assets/js/CKEditor/ckeditor5.js
Normal file
File diff suppressed because one or more lines are too long
1
assets/js/CKEditor/ckeditor5.js.map
Normal file
1
assets/js/CKEditor/ckeditor5.js.map
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/af.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/af.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/af.js
Normal file
5
assets/js/CKEditor/translations/af.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/af.umd.js
Normal file
11
assets/js/CKEditor/translations/af.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/ar.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/ar.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/ar.js
Normal file
5
assets/js/CKEditor/translations/ar.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/ar.umd.js
Normal file
11
assets/js/CKEditor/translations/ar.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/ast.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/ast.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/ast.js
Normal file
5
assets/js/CKEditor/translations/ast.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/ast.umd.js
Normal file
11
assets/js/CKEditor/translations/ast.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/az.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/az.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/az.js
Normal file
5
assets/js/CKEditor/translations/az.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/az.umd.js
Normal file
11
assets/js/CKEditor/translations/az.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/be.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/be.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/be.js
Normal file
5
assets/js/CKEditor/translations/be.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/be.umd.js
Normal file
11
assets/js/CKEditor/translations/be.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/bg.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/bg.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/bg.js
Normal file
5
assets/js/CKEditor/translations/bg.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/bg.umd.js
Normal file
11
assets/js/CKEditor/translations/bg.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/bn.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/bn.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/bn.js
Normal file
5
assets/js/CKEditor/translations/bn.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/bn.umd.js
Normal file
11
assets/js/CKEditor/translations/bn.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/bs.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/bs.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/bs.js
Normal file
5
assets/js/CKEditor/translations/bs.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/bs.umd.js
Normal file
11
assets/js/CKEditor/translations/bs.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/ca.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/ca.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/ca.js
Normal file
5
assets/js/CKEditor/translations/ca.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/ca.umd.js
Normal file
11
assets/js/CKEditor/translations/ca.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/cs.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/cs.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/cs.js
Normal file
5
assets/js/CKEditor/translations/cs.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/cs.umd.js
Normal file
11
assets/js/CKEditor/translations/cs.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/da.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/da.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/da.js
Normal file
5
assets/js/CKEditor/translations/da.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/da.umd.js
Normal file
11
assets/js/CKEditor/translations/da.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/de-ch.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/de-ch.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/de-ch.js
Normal file
5
assets/js/CKEditor/translations/de-ch.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/de-ch.umd.js
Normal file
11
assets/js/CKEditor/translations/de-ch.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/de.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/de.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/de.js
Normal file
5
assets/js/CKEditor/translations/de.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/de.umd.js
Normal file
11
assets/js/CKEditor/translations/de.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/el.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/el.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/el.js
Normal file
5
assets/js/CKEditor/translations/el.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/el.umd.js
Normal file
11
assets/js/CKEditor/translations/el.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/en-au.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/en-au.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/en-au.js
Normal file
5
assets/js/CKEditor/translations/en-au.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/en-au.umd.js
Normal file
11
assets/js/CKEditor/translations/en-au.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/en-gb.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/en-gb.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/en-gb.js
Normal file
5
assets/js/CKEditor/translations/en-gb.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/en-gb.umd.js
Normal file
11
assets/js/CKEditor/translations/en-gb.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/en.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/en.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/en.js
Normal file
5
assets/js/CKEditor/translations/en.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/en.umd.js
Normal file
11
assets/js/CKEditor/translations/en.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/eo.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/eo.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/eo.js
Normal file
5
assets/js/CKEditor/translations/eo.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/eo.umd.js
Normal file
11
assets/js/CKEditor/translations/eo.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/es-co.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/es-co.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/es-co.js
Normal file
5
assets/js/CKEditor/translations/es-co.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/es-co.umd.js
Normal file
11
assets/js/CKEditor/translations/es-co.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/es.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/es.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/es.js
Normal file
5
assets/js/CKEditor/translations/es.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/es.umd.js
Normal file
11
assets/js/CKEditor/translations/es.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/et.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/et.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/et.js
Normal file
5
assets/js/CKEditor/translations/et.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/et.umd.js
Normal file
11
assets/js/CKEditor/translations/et.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/eu.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/eu.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/eu.js
Normal file
5
assets/js/CKEditor/translations/eu.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/eu.umd.js
Normal file
11
assets/js/CKEditor/translations/eu.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/fa.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/fa.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/fa.js
Normal file
5
assets/js/CKEditor/translations/fa.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/fa.umd.js
Normal file
11
assets/js/CKEditor/translations/fa.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/fi.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/fi.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/fi.js
Normal file
5
assets/js/CKEditor/translations/fi.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/fi.umd.js
Normal file
11
assets/js/CKEditor/translations/fi.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/fr.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/fr.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
5
assets/js/CKEditor/translations/fr.js
Normal file
5
assets/js/CKEditor/translations/fr.js
Normal file
File diff suppressed because one or more lines are too long
11
assets/js/CKEditor/translations/fr.umd.js
Normal file
11
assets/js/CKEditor/translations/fr.umd.js
Normal file
File diff suppressed because one or more lines are too long
8
assets/js/CKEditor/translations/gl.d.ts
vendored
Normal file
8
assets/js/CKEditor/translations/gl.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Translations } from '@ckeditor/ckeditor5-utils';
|
||||||
|
declare const translations: Translations;
|
||||||
|
export default translations;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user