Feat: page Play — backgroundColor, playLink, play-icon + fix slug jouer
All checks were successful
Deploy / Deploy to Production (push) Successful in 5m22s

- Renommage dossier content 3_play → 3_jouer (slug /jouer)
- Champ backgroundColor (code-editor) dans game.yml + exposé en API
- playLinks simplifié en champ url simple → playLink dans l'API
- Variable CSS --background-color sur la section .play
- Bouton "Jouer" avec icône play-icon (SVG data URI dans buttons.css)
- Plugin sylvainjule/code-editor ajouté via composer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
isUnknown 2026-03-09 18:41:05 +01:00
parent 3cafcf3167
commit 5eaf99f7cd
25 changed files with 669 additions and 113 deletions

View file

@ -1,76 +1,81 @@
@font-face { @font-face {
font-family: 'Terminal Grotesque'; font-family: "Terminal Grotesque";
src: url('fonts/terminal-grotesque.ttf') format('truetype'); src: url("fonts/terminal-grotesque.ttf") format("truetype");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Danzza'; font-family: "Danzza";
src: url('fonts/Danzza-Light.woff') format('woff'); src: url("fonts/Danzza-Light.woff") format("woff");
font-weight: 300; font-weight: 300;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Danzza'; font-family: "Danzza";
src: url('fonts/Danzza-Regular.woff') format('woff'); src: url("fonts/Danzza-Regular.woff") format("woff");
font-weight: 400; font-weight: 400;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Danzza'; font-family: "Danzza";
src: url('fonts/Danzza-Medium.woff') format('woff'); src: url("fonts/Danzza-Medium.woff") format("woff");
font-weight: 500; font-weight: 500;
font-style: normal; font-style: normal;
} }
@font-face { @font-face {
font-family: 'Danzza'; font-family: "Danzza";
src: url('fonts/Danzza-Bold.woff') format('woff'); src: url("fonts/Danzza-Bold.woff") format("woff");
font-weight: 700; font-weight: 700;
font-style: normal; font-style: normal;
} }
:root{ :root {
--font-title: 'Terminal Grotesque', sans-serif; --font-title: "Terminal Grotesque", sans-serif;
--font-body: 'Danzza', sans-serif; --font-body: "Danzza", sans-serif;
--font-sans: 'Danzza', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; --font-sans: "Danzza", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
--text-h1: 3em; --text-h1: 3em;
--color-green-perso: #04fea0; --color-green-perso: #04fea0;
--color-black: #0B1632; --color-black: #0b1632;
--color-white: #ffffff; --color-white: #ffffff;
--color-gray-200: #BCCAF0; --color-gray-200: #bccaf0;
--color-gray-100: #BCCAF0; --color-gray-100: #bccaf0;
--color-gray-250: #8BA3E5; --color-gray-250: #8ba3e5;
--color-gray-300: #7A95E1; --color-gray-300: #7a95e1;
--color-gray-400: #597BD9; --color-gray-400: #597bd9;
--color-gray-500: #3761D2; --color-gray-500: #3761d2;
--color-gray-600: #224196; --color-gray-600: #224196;
--color-gray-700: #1A3274; --color-gray-700: #1a3274;
--color-gray-800: #172C64; --color-gray-800: #172c64;
--color-gray-850: #132553; --color-gray-850: #132553;
--color-gray-900: #0e1e43; --color-gray-900: #0e1e43;
--color-gray-950: #0d1a38; --color-gray-950: #0d1a38;
--button-cancel-filled-color-back: light-dark( var(--color-gray-300), var(--color-gray-950) ); --button-cancel-filled-color-back: light-dark(
--color-icon-perso: light-dark( var(--color-gray-700), var(--color-gray-400) ); var(--color-gray-300),
var(--color-gray-950)
);
--color-icon-perso: light-dark(var(--color-gray-700), var(--color-gray-400));
--color-border: light-dark(var(--color-gray-300), var(--color-gray-600)); --color-border: light-dark(var(--color-gray-300), var(--color-gray-600));
--dropdown-color-hr:var(--color-gray-800); --dropdown-color-hr: var(--color-gray-800);
--color-focus: var(--color-green-perso); --color-focus: var(--color-green-perso);
--color-red-h: 355; --color-red-h: 355;
--color-green-h: 152; --color-green-h: 152;
--color-orange-h: 15; --color-orange-h: 15;
--color-blue-h: 220; --color-blue-h: 220;
} }
.k-dialog-button-cancel:where([data-variant="filled"]) { .k-dialog-button-cancel:where([data-variant="filled"]) {
@ -81,25 +86,27 @@
--icon-color: var(--color-icon-perso); --icon-color: var(--color-icon-perso);
} }
.k-panel-menu-button:hover:not(.k-activation-button):not(.k-panel-menu-search){ .k-panel-menu-button:hover:not(.k-activation-button):not(.k-panel-menu-search) {
color: var(--color-green-perso); color: var(--color-green-perso);
} }
.k-header-title {
.k-header-title{ font-family: var(--font-title);
font-family: var(--font-title);
} }
.k-panel[data-template="home"] .k-header-title-text, .k-panel[data-template="expertise"] .k-header-title-text, .k-panel[data-template="home"] .k-header-title-text,
.k-panel[data-template="portfolio"] .k-header-title-text, .k-panel[data-template="jouer"] .k-header-title-text, .k-panel[data-template="expertise"] .k-header-title-text,
.k-panel[data-template="about"] .k-header-title-text, .k-panel[data-template="blog"] .k-header-title-text{ .k-panel[data-template="portfolio"] .k-header-title-text,
text-transform: uppercase; .k-panel[data-template="jouer"] .k-header-title-text,
.k-panel[data-template="about"] .k-header-title-text,
.k-panel[data-template="blog"] .k-header-title-text {
text-transform: uppercase;
} }
.k-header-title .k-icon{ .k-header-title .k-icon {
--icon-size: 28px; --icon-size: 28px;
} }
.k-text a{ .k-text a {
color: var(--color-green-perso); color: var(--color-green-perso);
} }
.k-block-container:not(:last-of-type) { .k-block-container:not(:last-of-type) {
@ -107,35 +114,46 @@
} }
/*modif card pour ressembler au site web*/ /*modif card pour ressembler au site web*/
.k-panel[data-template="blog"] .k-item.k-cards-item[data-template="article"]{ .k-panel[data-template="blog"] .k-item.k-cards-item[data-template="article"] {
display: grid; display: grid;
grid-template-columns: 2fr auto 1fr; grid-template-columns: 2fr auto 1fr;
grid-template-rows: auto; grid-template-rows: auto;
} }
.k-panel[data-template="blog"] .k-item.k-cards-item[data-template="article"] .k-item-image{ .k-panel[data-template="blog"]
grid-column: 3/4; .k-item.k-cards-item[data-template="article"]
grid-row: 1/3; .k-item-image {
grid-column: 3/4;
grid-row: 1/3;
} }
.k-panel[data-template="blog"] .k-item.k-cards-item[data-template="article"] .k-item-content{ .k-panel[data-template="blog"]
grid-column: 1/2; .k-item.k-cards-item[data-template="article"]
grid-row: 1/2; .k-item-content {
grid-column: 1/2;
grid-row: 1/2;
} }
.k-panel[data-template="blog"] .k-item.k-cards-item[data-template="article"] .k-item-options{ .k-panel[data-template="blog"]
grid-column: 2/3; .k-item.k-cards-item[data-template="article"]
grid-row: 1/2; .k-item-options {
align-items: start; grid-column: 2/3;
grid-row: 1/2;
align-items: start;
} }
/* Logo sur la page de login */ /* Logo sur la page de login */
.k-login-view .k-login-form::before { .k-login-view .k-login-form::before {
content: ''; content: "";
display: block; display: block;
width: 150px; width: 150px;
height: 150px; height: 150px;
margin: 0 auto 2rem auto; margin: 0 auto 2rem auto;
background-image: url('logo-panel.png'); background-image: url("logo-panel.png");
background-size: contain; background-size: contain;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
}
/* Code editor style */
.k-code-editor-input[data-size="custom-size"] {
min-height: 2rem;
} }

View file

@ -22,7 +22,8 @@
}, },
"require": { "require": {
"php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
"getkirby/cms": "^5.2" "getkirby/cms": "^5.2",
"sylvainjule/code-editor": "^1.1"
}, },
"config": { "config": {
"allow-plugins": { "allow-plugins": {

40
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "da1c3a8eb3e9e3b252ad405f32a3f585", "content-hash": "07c4d6a85de1d10e6c6fc0e5cec09033",
"packages": [ "packages": [
{ {
"name": "christian-riesen/base32", "name": "christian-riesen/base32",
@ -721,6 +721,44 @@
}, },
"time": "2024-09-11T13:17:53+00:00" "time": "2024-09-11T13:17:53+00:00"
}, },
{
"name": "sylvainjule/code-editor",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/sylvainjule/kirby-code-editor.git",
"reference": "adbc2c8a728994cc57ea72a7f8628f27d202b8df"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sylvainjule/kirby-code-editor/zipball/adbc2c8a728994cc57ea72a7f8628f27d202b8df",
"reference": "adbc2c8a728994cc57ea72a7f8628f27d202b8df",
"shasum": ""
},
"require": {
"getkirby/composer-installer": "^1.2"
},
"type": "kirby-plugin",
"extra": {
"installer-name": "code-editor"
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sylvain Julé",
"email": "contact@sylvain-jule.fr"
}
],
"description": "Code editor field for Kirby 3, 4 and 5",
"support": {
"issues": "https://github.com/sylvainjule/kirby-code-editor/issues",
"source": "https://github.com/sylvainjule/kirby-code-editor/tree/1.1.0"
},
"time": "2025-08-04T17:32:08+00:00"
},
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
"version": "v3.6.0", "version": "v3.6.0",

View file

@ -65,6 +65,13 @@ columns:
previewCol: previewCol:
type: fields type: fields
fields: fields:
backgroundColor:
label: Couleur d'arrière plan
type: code-editor
language: css
size: custom-size
default: radial-gradient(circle at 20% 80%, rgb(240, 154, 110) 0%, rgb(233, 101, 122) 100%)
help: À remplir avec la valeur de la propriété CSS `background-color` souhaitée
preview: preview:
label: Aperçu label: Aperçu
type: files type: files

View file

@ -0,0 +1,12 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
[*.php]
indent_size = 4

6
site/plugins/code-editor/.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
.DS_Store
.cache
node_modules
package-lock.json
yarn.lock
composer.lock

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Sylvain Julé
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,111 @@
# Kirby Code editor
Code editor field for Kirby 3, 4 and 5.
![screenshot-code-editor](https://user-images.githubusercontent.com/14079751/109679014-7b043800-7b7b-11eb-8c4e-2ae25da8288d.png)
<br/>
## Overview
> This plugin is completely free and published under the MIT license. However, if you are using it in a commercial project and want to help me keep up with maintenance, you can consider [making a donation of your choice](https://paypal.me/sylvainjl).
- [1. Installation](#1-installation)
- [2. Setup](#2-setup)
- [3. Options](#3-options)
- [4. Available languages](#4-available-languages)
- [5. License](#5-license)
- [6. Credits](#6-credits)
<br/>
## 1. Installation
Download and copy this repository to ```/site/plugins/code-editor```
Alternatively, you can install it with composer: ```composer require sylvainjule/code-editor```
<br/>
## 2. Setup
This field adds a code editor in the panel:
```yaml
editor:
label: My code editor
type: code-editor
```
<br/>
## 3. Options
| Name | Type | Default | Options | Description |
| -------------------- | ------------------ | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| language | `String` | `'css'` | - | Syntax mode of the editor. See below for available languages |
| size | `String` | `'small'` | - | Min height of the editor. `small / medium / large / huge` |
| lineNumbers | `Boolean` | `true` | - | Whether to show line numbers. |
| tabSize | `number` | `4` | - | The number of characters to insert when pressing tab key. |
| insertSpaces | `boolean` | `true` | - | Whether to use spaces for indentation. If you set it to `false`, you might also want to set `tabSize` to `1` |
| ignoreTabKey | `boolean` | `false` | - | Whether the editor should ignore tab key presses so that keyboard users can tab past the editor. Users can toggle this behaviour using `Ctrl+Shift+M` (Mac) / `Ctrl+M` manually when this is `false`. |
Note that you can make the default height any height you want with some [custom panel CSS](https://getkirby.com/docs/reference/system/options/panel#custom-panel-css). First, set the `size` option to any string you'd like:
```yaml
size: custom-size
```
Then in your `panel.css`:
```css
.k-code-editor-input[data-size="custom-size"] {
min-height: 15rem;
}
```
### 3.1. Default options
You can globally override the default options, instead of setting them on a per-field basis. In your `site/config/config.php`:
```php
return [
'sylvainjule.code-editor.language' => 'css',
'sylvainjule.code-editor.size' => 'small',
'sylvainjule.code-editor.lineNumbers' => true,
'sylvainjule.code-editor.tabSize' => 4,
'sylvainjule.code-editor.insertSpaces' => true,
'sylvainjule.code-editor.ignoreTabKey' => false,
];
```
<br/>
## 4. Available languages
Currently supported languages are:
* `css`
* `javascript`
* `json`
* `less`
* `php`
* `python`
* `ruby`
* `scss`
* `yaml`
<br/>
## 5. License
MIT
<br/>
## 6. Credits
**Code editor:**
- [Vue Prism Editor](https://github.com/koca/vue-prism-editor)

View file

@ -0,0 +1,20 @@
{
"name": "sylvainjule/code-editor",
"description": "Code editor field for Kirby 3, 4 and 5",
"type": "kirby-plugin",
"license": "MIT",
"version": "1.1.0",
"authors": [
{
"name": "Sylvain Julé",
"email": "contact@sylvain-jule.fr"
}
],
"require": {
"getkirby/composer-installer": "^1.2"
},
"extra": {
"installer-name": "code-editor"
},
"minimum-stability": "beta"
}

View file

@ -0,0 +1,28 @@
import js from "@eslint/js";
import prettier from "eslint-config-prettier";
import vue from "eslint-plugin-vue";
export default [
js.configs.recommended,
...vue.configs["flat/vue2-recommended"],
prettier,
{
rules: {
"vue/attributes-order": "error",
"vue/component-definition-name-casing": "off",
"vue/html-closing-bracket-newline": [
"error",
{
singleline: "never",
multiline: "always"
}
],
"vue/multi-word-component-names": "off",
"vue/require-default-prop": "off",
"vue/require-prop-types": "error"
},
languageOptions: {
ecmaVersion: 2022
}
}
];

View file

@ -0,0 +1 @@
.prism-editor-wrapper{width:100%;height:100%;display:flex;align-items:flex-start;overflow:auto;-o-tab-size:1.5em;tab-size:1.5em;-moz-tab-size:1.5em}@media (-ms-high-contrast:active),(-ms-high-contrast:none){.prism-editor-wrapper .prism-editor__textarea{color:transparent!important}.prism-editor-wrapper .prism-editor__textarea::-moz-selection{background-color:#accef7!important;color:transparent!important}.prism-editor-wrapper .prism-editor__textarea::selection{background-color:#accef7!important;color:transparent!important}}.prism-editor-wrapper .prism-editor__container{position:relative;text-align:left;box-sizing:border-box;padding:0;overflow:hidden;width:100%}.prism-editor-wrapper .prism-editor__line-numbers{height:100%;overflow:hidden;flex-shrink:0;padding-top:4px;margin-top:0;margin-right:10px}.prism-editor-wrapper .prism-editor__line-number{text-align:right;white-space:nowrap}.prism-editor-wrapper .prism-editor__textarea{position:absolute;top:0;left:0;height:100%;width:100%;resize:none;color:inherit;overflow:hidden;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;-webkit-text-fill-color:transparent}.prism-editor-wrapper .prism-editor__editor,.prism-editor-wrapper .prism-editor__textarea{margin:0;border:0;background:none;box-sizing:inherit;display:inherit;font-family:inherit;font-size:inherit;font-style:inherit;font-variant-ligatures:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;-moz-tab-size:inherit;-o-tab-size:inherit;tab-size:inherit;text-indent:inherit;text-rendering:inherit;text-transform:inherit;white-space:pre-wrap;word-wrap:keep-all;overflow-wrap:break-word;padding:0}.prism-editor-wrapper .prism-editor__textarea--empty{-webkit-text-fill-color:inherit!important}.prism-editor-wrapper .prism-editor__editor{position:relative;pointer-events:none}code[class*=language-],pre[class*=language-]{color:#ccc;background:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.comment,.token.block-comment,.token.prolog,.token.doctype,.token.cdata{color:#999}.token.punctuation{color:#ccc}.token.tag,.token.attr-name,.token.namespace,.token.deleted{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.number,.token.function{color:#f08d49}.token.property,.token.class-name,.token.constant,.token.symbol{color:#f8c555}.token.selector,.token.important,.token.atrule,.token.keyword,.token.builtin{color:#cc99cd}.token.string,.token.char,.token.attr-value,.token.regex,.token.variable{color:#7ec699}.token.operator,.token.entity,.token.url{color:#67cdcc}.token.important,.token.bold{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}.k-code-editor-input{background:light-dark(var(--color-gray-950),var(--input-color-back));color:var(--color-gray-200);font-family:var(--font-mono);font-size:var(--text-sm);line-height:1.5;padding:var(--spacing-2);border-radius:var(--rounded)}.k-code-editor-input[data-size=small]{min-height:7.5rem}.k-code-editor-input[data-size=medium]{min-height:15rem}.k-code-editor-input[data-size=large]{min-height:30rem}.k-code-editor-input[data-size=huge]{min-height:45rem}.prism-editor__textarea:focus{outline:none}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,15 @@
<?php
Kirby::plugin('sylvainjule/code-editor', [
'options' => array(
'language' => 'css',
'size' => 'small',
'lineNumbers' => true,
'tabSize' => 4,
'insertSpaces' => true,
'ignoreTabKey' => false,
),
'fields' => array(
'code-editor' => require_once __DIR__ . '/lib/fields/code-editor.php',
),
]);

View file

@ -0,0 +1,32 @@
<?php
$options = require kirby()->root('kirby') . '/config/fields/textarea.php';
/* Merge new properties
--------------------------------*/
$options = A::merge($options, [
'props' => [
'size' => function($size = null) {
return $size ?? option('sylvainjule.code-editor.size');
},
'language' => function($language = null) {
return $language ?? option('sylvainjule.code-editor.language');
},
'lineNumbers' => function($lineNumbers = null) {
return $lineNumbers ?? option('sylvainjule.code-editor.lineNumbers');
},
'tabSize' => function($tabSize = null) {
return $tabSize ?? option('sylvainjule.code-editor.tabSize');
},
'insertSpaces' => function($insertSpaces = null) {
return $tabSize ?? option('sylvainjule.code-editor.insertSpaces');
},
'ignoreTabKey' => function($ignoreTabKey = null) {
return $tabSize ?? option('sylvainjule.code-editor.ignoreTabKey');
},
]
]);
// return the updated options
return $options;

View file

@ -0,0 +1,30 @@
{
"name": "kirby-code-editor",
"version": "1.0.3",
"description": "Code editor field for Kirby 3 and 4",
"main": "index.js",
"author": "Kirby Community",
"license": "MIT",
"repository": {
"type": "git",
"url": "git@github.com:sylvainjule/kirby-code-editor.git"
},
"scripts": {
"dev": "kirbyup src/index.js --watch",
"build": "kirbyup src/index.js",
"lint": "eslint \"src/**/*.{js,vue}\"",
"lint:fix": "npm run lint -- --fix",
"format": "prettier --write \"src/**/*.{css,js,vue}\"",
"prepare": "node src/node/patchVuePrismEditor.mjs"
},
"devDependencies": {
"consola": "^3.4.2",
"eslint": "^9.27.0",
"eslint-config-prettier": "^10.1.5",
"eslint-plugin-vue": "^9.33.0",
"kirbyup": "^3.3.0",
"prettier": "^3.5.3",
"prismjs": "^1.30.0",
"vue-prism-editor": "^1.3.0"
}
}

View file

@ -0,0 +1,97 @@
<template>
<k-field :input="uid" v-bind="$props" class="k-code-editor-field">
<prism-editor
v-model="code"
class="k-code-editor-input"
:highlight="highlighter"
:line-numbers="lineNumbers"
:tab-size="tabSize"
:insert-spaces="insertSpaces"
:ignore-tab-key="ignoreTabKey"
:data-size="size"
@input="onCodeInput"
/>
</k-field>
</template>
<script>
import { PrismEditor } from "vue-prism-editor";
import "vue-prism-editor/dist/prismeditor.min.css";
import { highlight, languages } from "prismjs/components/prism-core";
import "prismjs/components/prism-markup-templating";
import "prismjs/components/prism-clike";
import "prismjs/components/prism-css";
import "prismjs/components/prism-javascript";
import "prismjs/components/prism-json";
import "prismjs/components/prism-less";
import "prismjs/components/prism-php";
import "prismjs/components/prism-python";
import "prismjs/components/prism-ruby";
import "prismjs/components/prism-scss";
import "prismjs/components/prism-yaml";
import "prismjs/themes/prism-tomorrow.css";
export default {
components: { PrismEditor },
extends: "k-textarea-field",
props: {
size: String,
language: String,
lineNumbers: Boolean,
tabSize: Number,
insertSpaces: Boolean,
ignoreTabKey: Boolean,
},
data() {
return {
code: "",
};
},
mounted() {
this.code = this.value;
},
methods: {
highlighter() {
return highlight(this.code, languages[this.language]);
},
onCodeInput() {
this.$emit("input", this.code);
},
},
};
</script>
<style>
.k-code-editor-input {
background: light-dark(var(--color-gray-950), var(--input-color-back));
color: var(--color-gray-200);
font-family: var(--font-mono);
font-size: var(--text-sm);
line-height: 1.5;
padding: var(--spacing-2);
border-radius: var(--rounded);
}
.k-code-editor-input[data-size="small"] {
min-height: 7.5rem;
}
.k-code-editor-input[data-size="medium"] {
min-height: 15rem;
}
.k-code-editor-input[data-size="large"] {
min-height: 30rem;
}
.k-code-editor-input[data-size="huge"] {
min-height: 45rem;
}
.prism-editor__textarea:focus {
outline: none;
}
</style>

View file

@ -0,0 +1,7 @@
import CodeEditor from "./components/field/CodeEditor.vue";
window.panel.plugin("sylvainjule/code-editor", {
fields: {
"code-editor": CodeEditor,
},
});

View file

@ -0,0 +1,38 @@
import { existsSync, readFileSync, writeFileSync } from "fs";
import chalk from "chalk";
import consola from "consola";
const srcPath = "node_modules/vue-prism-editor/dist/prismeditor.esm.js";
async function main() {
consola.start("Vue Prism Editor patcher");
if (!existsSync(srcPath)) {
consola.error(
`couldn't find ${chalk.cyan(srcPath)}, did you run ${chalk.green(
"npm install"
)}?`
);
return;
}
const source = readFileSync(srcPath, "utf8");
if (!source.includes("Vue.extend")) {
consola.success("already patched");
return;
}
consola.info("patching the source component...");
let output = source
.replace(/^import Vue from 'vue';/, "")
.replace("/*#__PURE__*/Vue.extend(", "")
.replace(/\}\)(;\s+export)/, "}$1");
writeFileSync(srcPath, output, "utf8");
consola.success("successfully patched");
}
main().catch((err) => consola.error(err));

View file

@ -9,10 +9,8 @@ $specificData = [
'description' => $game->description()->value(), 'description' => $game->description()->value(),
'thumbnail' => $game->thumbnail()->toFile()?->url(), 'thumbnail' => $game->thumbnail()->toFile()?->url(),
'backgroundImage' => $game->backgroundImage()->toFile()?->url(), 'backgroundImage' => $game->backgroundImage()->toFile()?->url(),
'playLinks' => $game->playLinks()->toStructure()->map(fn($l) => [ 'backgroundColor' => $game->backgroundColor()->value() ?: null,
'label' => $l->label()->value(), 'playLink' => $game->playLinks()->value() ?: null,
'url' => $l->url()->value(),
])->values(),
]; ];
})->values() })->values()
]; ];

View file

@ -48,6 +48,16 @@
hue-rotate(91deg) brightness(101%) contrast(97%); hue-rotate(91deg) brightness(101%) contrast(97%);
} }
.button.play-icon::before {
content: "";
background-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15.7598 13.5H14.6348V14.625V15.75H15.7598V14.625H16.8848V13.5V12.375H15.7598V13.5Z' fill='black'/%3E%3Cpath d='M12.3848 15.75V16.875H13.5098H14.6348V15.75H13.5098H12.3848Z' fill='black'/%3E%3Cpath d='M10.1348 16.875H9.00977V18H10.1348H11.2598H12.3848V16.875H11.2598H10.1348Z' fill='black'/%3E%3Cpath d='M1.125 10.125V9V7.875V6.75V5.625H0V6.75V7.875V9V10.125V11.25V12.375H1.125V11.25V10.125Z' fill='black'/%3E%3Cpath d='M3.375 13.5H2.25V12.375H1.125V13.5V14.625H2.25V15.75H3.375V14.625V13.5Z' fill='black'/%3E%3Cpath d='M4.5 15.75H3.375V16.875H4.5H5.625V15.75H4.5Z' fill='black'/%3E%3Cpath d='M6.75 16.875H5.625V18H6.75H7.875H9V16.875H7.875H6.75Z' fill='black'/%3E%3Cpath d='M16.8848 5.625V6.75V7.875V9V10.125V11.25V12.375H18.0098V11.25V10.125V9V7.875V6.75V5.625H16.8848Z' fill='black'/%3E%3Cpath d='M16.8848 3.375H15.7598V2.25H14.6348V3.375V4.5H15.7598V5.625H16.8848V4.5V3.375Z' fill='black'/%3E%3Cpath d='M11.2598 0H10.1348H9.00977V1.125H10.1348H11.2598H12.3848V0H11.2598Z' fill='black'/%3E%3Cpath d='M13.5098 1.125H12.3848V2.25H13.5098H14.6348V1.125H13.5098Z' fill='black'/%3E%3Cpath d='M2.25 4.5H3.375V3.375V2.25H2.25V3.375H1.125V4.5V5.625H2.25V4.5Z' fill='black'/%3E%3Cpath d='M5.625 2.25V1.125H4.5H3.375V2.25H4.5H5.625Z' fill='black'/%3E%3Cpath d='M7.875 1.125H9V0H7.875H6.75H5.625V1.125H6.75H7.875Z' fill='black'/%3E%3Cpath d='M10.1399 10.1825H11.2774V9.6775H12.4149V8.54H11.2774V7.91H10.1399V6.7725H9.00492V5.6375H7.86742V4.5H6.73242V13.5925H7.86742V12.455H9.00492V11.3175H10.1399V10.1825Z' fill='black'/%3E%3C/svg%3E");
background-size: 100%;
width: 1.125rem;
height: 1.125rem;
transform: translateX(-0.5rem);
transition: all 0.5s ease-out;
}
/* Clickable elements */ /* Clickable elements */
.clickable { .clickable {
cursor: pointer; cursor: pointer;

View file

@ -61,7 +61,11 @@
}) })
</script> </script>
<section class="play golden-grid slide" aria-label="Jouer"> <section
class="play golden-grid slide"
aria-label="Jouer"
style={displayedGame?.backgroundColor ? `--background-color: ${displayedGame.backgroundColor}` : ''}
>
<!-- Fond : image + overlay, crossfade au changement de jeu --> <!-- Fond : image + overlay, crossfade au changement de jeu -->
<div class="play-bg" class:is-out={isOut} aria-hidden="true"> <div class="play-bg" class:is-out={isOut} aria-hidden="true">
@ -144,15 +148,13 @@
{/if} {/if}
<div class="play-actions"> <div class="play-actions">
{#if displayedGame.playLinks?.length} {#if displayedGame.playLink}
{#each displayedGame.playLinks as link} <a
<a href={displayedGame.playLink}
href={link.url} target="_blank"
target="_blank" rel="noopener noreferrer"
rel="noopener noreferrer" class="button play-icon"
class="button" >Jouer</a>
>{link.label}</a>
{/each}
{:else} {:else}
<button class="button" disabled>Coming soon</button> <button class="button" disabled>Coming soon</button>
{/if} {/if}
@ -184,7 +186,7 @@
<style> <style>
.play { .play {
background: #000; background: var(--background-color);
} }
/* --- Background --- */ /* --- Background --- */

View file

@ -16,7 +16,7 @@ return array(
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'), 'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
'League\\ColorExtractor\\' => array($vendorDir . '/league/color-extractor/src'), 'League\\ColorExtractor\\' => array($vendorDir . '/league/color-extractor/src'),
'Laminas\\Escaper\\' => array($vendorDir . '/laminas/laminas-escaper/src'), 'Laminas\\Escaper\\' => array($vendorDir . '/laminas/laminas-escaper/src'),
'Kirby\\' => array($vendorDir . '/getkirby/composer-installer/src', $baseDir . '/kirby/src'), 'Kirby\\' => array($baseDir . '/kirby/src', $vendorDir . '/getkirby/composer-installer/src'),
'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'), 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
'Base32\\' => array($vendorDir . '/christian-riesen/base32/src'), 'Base32\\' => array($vendorDir . '/christian-riesen/base32/src'),
); );

View file

@ -96,8 +96,8 @@ class ComposerStaticInitda1c3a8eb3e9e3b252ad405f32a3f585
), ),
'Kirby\\' => 'Kirby\\' =>
array ( array (
0 => __DIR__ . '/..' . '/getkirby/composer-installer/src', 0 => __DIR__ . '/../..' . '/kirby/src',
1 => __DIR__ . '/../..' . '/kirby/src', 1 => __DIR__ . '/..' . '/getkirby/composer-installer/src',
), ),
'Composer\\Semver\\' => 'Composer\\Semver\\' =>
array ( array (

View file

@ -748,6 +748,47 @@
}, },
"install-path": "../psr/log" "install-path": "../psr/log"
}, },
{
"name": "sylvainjule/code-editor",
"version": "1.1.0",
"version_normalized": "1.1.0.0",
"source": {
"type": "git",
"url": "https://github.com/sylvainjule/kirby-code-editor.git",
"reference": "adbc2c8a728994cc57ea72a7f8628f27d202b8df"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sylvainjule/kirby-code-editor/zipball/adbc2c8a728994cc57ea72a7f8628f27d202b8df",
"reference": "adbc2c8a728994cc57ea72a7f8628f27d202b8df",
"shasum": ""
},
"require": {
"getkirby/composer-installer": "^1.2"
},
"time": "2025-08-04T17:32:08+00:00",
"type": "kirby-plugin",
"extra": {
"installer-name": "code-editor"
},
"installation-source": "dist",
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sylvain Julé",
"email": "contact@sylvain-jule.fr"
}
],
"description": "Code editor field for Kirby 3, 4 and 5",
"support": {
"issues": "https://github.com/sylvainjule/kirby-code-editor/issues",
"source": "https://github.com/sylvainjule/kirby-code-editor/tree/1.1.0"
},
"install-path": "../../site/plugins/code-editor"
},
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
"version": "v3.6.0", "version": "v3.6.0",

View file

@ -1,9 +1,9 @@
<?php return array( <?php return array(
'root' => array( 'root' => array(
'name' => 'getkirby/plainkit', 'name' => 'getkirby/plainkit',
'pretty_version' => '5.2.2', 'pretty_version' => 'dev-main',
'version' => '5.2.2.0', 'version' => 'dev-main',
'reference' => null, 'reference' => '3cafcf3167251bbbfd64183de5da67c4a488fa7d',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
@ -65,9 +65,9 @@
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'getkirby/plainkit' => array( 'getkirby/plainkit' => array(
'pretty_version' => '5.2.2', 'pretty_version' => 'dev-main',
'version' => '5.2.2.0', 'version' => 'dev-main',
'reference' => null, 'reference' => '3cafcf3167251bbbfd64183de5da67c4a488fa7d',
'type' => 'project', 'type' => 'project',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
@ -124,6 +124,15 @@
'aliases' => array(), 'aliases' => array(),
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'sylvainjule/code-editor' => array(
'pretty_version' => '1.1.0',
'version' => '1.1.0.0',
'reference' => 'adbc2c8a728994cc57ea72a7f8628f27d202b8df',
'type' => 'kirby-plugin',
'install_path' => __DIR__ . '/../../site/plugins/code-editor',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/deprecation-contracts' => array( 'symfony/deprecation-contracts' => array(
'pretty_version' => 'v3.6.0', 'pretty_version' => 'v3.6.0',
'version' => '3.6.0.0', 'version' => '3.6.0.0',