Compare commits
90 Commits
v0.1.2
...
18306c28b9
| Author | SHA1 | Date | |
|---|---|---|---|
| 18306c28b9 | |||
| 36e7d8ad8b | |||
| fdf32bbc78 | |||
| 2c44d8137c | |||
| db831700f0 | |||
| 9bb09b89d9 | |||
| 58dbcdd25a | |||
| 8ae6dafb62 | |||
| faf39ca182 | |||
| 8d350bb092 | |||
| 4338028c60 | |||
| ab563a7b37 | |||
| 2cfc1a0047 | |||
| 98e8d971e8 | |||
| 87be06ecea | |||
| 28f6e1ae7c | |||
| 27380290e1 | |||
| 7e44554767 | |||
| 9c3dceef84 | |||
| ba8d8e00a8 | |||
| 8f037b5950 | |||
| 291fa6eaa4 | |||
| 4079e4ecfb | |||
| eea020b136 | |||
| 5161bff624 | |||
| 3199835e83 | |||
| 6dd13ead91 | |||
| 980c5271ac | |||
| 115a5d2d38 | |||
| 6b17201f60 | |||
| ad3c53c5dd | |||
| fefa98021b | |||
| 1e58b1f1e7 | |||
| 0bafc3a9dd | |||
| 8bd544b5c3 | |||
| 4918c638ab | |||
| bff7bce1f1 | |||
| 0fbd2bf7ac | |||
| 238aa29bd4 | |||
| f268bdc3c3 | |||
| 11641a00d1 | |||
| 6a5d60e34c | |||
| 80e6555c88 | |||
| ff866e2078 | |||
| 5e39b53a44 | |||
| 2d93d44a93 | |||
| ec64a42c2e | |||
| 5f9c29c39a | |||
| 27f4f73148 | |||
| 21a7036ef5 | |||
| b1b1aa47c9 | |||
| 54fea5f64a | |||
| a27e6af5db | |||
| 2c86905c91 | |||
| 065b729a2f | |||
| c82bf47e98 | |||
| 51f594baa5 | |||
| 3e56ba7eb3 | |||
| aaea0b062a | |||
| b886585be1 | |||
| c6dfbeb247 | |||
| a1a8114f49 | |||
| 63f8e443cf | |||
| 5b8c50c758 | |||
| c5ce607fae | |||
| 9cd99c36db | |||
| 108269e3fe | |||
| 4492d760bb | |||
| 489ac82faa | |||
| d7cf08db00 | |||
| 4ae9b67b9c | |||
| 3b706c0092 | |||
| baa3061685 | |||
| fd61895bbd | |||
| cdcb09e24b | |||
| 341b0d6e9d | |||
| 58d1dc0045 | |||
| 5e0df227f3 | |||
| 2d0b176ab8 | |||
| bfb5ae3a70 | |||
| 9d99770b38 | |||
| e383255e73 | |||
| 684e2fa1e9 | |||
| 8e26f19f66 | |||
| 40becf1135 | |||
| 764bc6aeea | |||
| 12048ffdd3 | |||
| c7f6cca663 | |||
| 2b9a87511b | |||
| 688c4e36b3 |
56
.gitea/workflows/deploy.yaml
Normal file
56
.gitea/workflows/deploy.yaml
Normal file
@@ -0,0 +1,56 @@
|
||||
name: Deployment
|
||||
run-name: ${{ gitea.actor }} deploying ${{ gitea.repository.name }}
|
||||
on: [push]
|
||||
|
||||
env:
|
||||
NUXT_PROJECT_PATH: wp-content/themes/moonshine
|
||||
PNPM_STORE_DIR: /cache/wp-scripts/pnpm
|
||||
|
||||
jobs:
|
||||
|
||||
wordpress:
|
||||
runs-on: ubuntu-websimple
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install WordPress scripts
|
||||
env:
|
||||
TEMPLATES_REPO_TOKEN: ${{ secrets.TEMPLATES_REPO_TOKEN }}
|
||||
run: |
|
||||
git clone https://$TEMPLATES_REPO_TOKEN@gitea.websimple.com/templates/wp-scripts.git /tmp/wp-scripts
|
||||
|
||||
- name: Run deployment script
|
||||
env:
|
||||
REMOTE_HOST: ${{ vars.REMOTE_HOST }}
|
||||
REMOTE_PORT: ${{ vars.REMOTE_PORT }}
|
||||
REMOTE_USER: ${{ vars.REMOTE_USER }}
|
||||
REMOTE_PATH: ${{ vars.REMOTE_PATH }}
|
||||
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
run: /tmp/wp-scripts/wp-deploy.sh --skip-node
|
||||
|
||||
nuxt:
|
||||
runs-on: ubuntu-websimple
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ env.NUXT_PROJECT_PATH }}
|
||||
env:
|
||||
NUXT_SITE_ENV: ${{ vars.NUXT_SITE_ENV }}
|
||||
NUXT_SITE_URL: ${{ vars.NUXT_SITE_URL }}
|
||||
NUXT_WP_URL: ${{ vars.NUXT_WP_URL }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Node.js dependencies
|
||||
run: pnpm install --frozen-lockfile --store-dir $PNPM_STORE_DIR
|
||||
|
||||
- name: Build Nuxt project
|
||||
run: pnpm build
|
||||
|
||||
- name: Deploy to Cloudflare Workers
|
||||
run: pnpm wrangler deploy
|
||||
env:
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
3
.vscode/extensions.json
vendored
Normal file
3
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["oxc.oxc-vscode"]
|
||||
}
|
||||
27
.vscode/launch.json
vendored
Normal file
27
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Nuxt server",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/wp-content/themes/moonshine/node_modules/nuxt/bin/nuxt.mjs",
|
||||
"runtimeArgs": ["--inspect"],
|
||||
"args": ["dev"],
|
||||
"cwd": "${workspaceFolder}/wp-content/themes/moonshine",
|
||||
"autoAttachChildProcesses": true,
|
||||
"console": "integratedTerminal",
|
||||
"skipFiles": ["<node_internals>/**"]
|
||||
},
|
||||
{
|
||||
"name": "Nuxt client",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"sourceMaps": true,
|
||||
"trace": false,
|
||||
"url": "http://localhost:3000",
|
||||
"userDataDir": "${env:HOME}/.vscode/chromium-profile",
|
||||
"webRoot": "${workspaceFolder}/wp-content/themes/moonshine"
|
||||
}
|
||||
]
|
||||
}
|
||||
46
.vscode/settings.json
vendored
46
.vscode/settings.json
vendored
@@ -1,4 +1,34 @@
|
||||
{
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[postcss]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[scss]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.oxc": "always"
|
||||
},
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSaveMode": "file",
|
||||
"editor.quickSuggestions": {
|
||||
"strings": "on"
|
||||
},
|
||||
@@ -6,15 +36,11 @@
|
||||
"*.css": "tailwindcss"
|
||||
},
|
||||
"graphql-config.load.rootDir": "wp-content/themes/moonshine",
|
||||
"tailwindCSS.classAttributes": [
|
||||
"class",
|
||||
"ui"
|
||||
],
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
[
|
||||
"ui:\\s*{([^)]*)\\s*}",
|
||||
"(?:'|\"|`)([^']*)(?:'|\"|`)"
|
||||
]
|
||||
],
|
||||
"oxc.fmt.configPath": "wp-content/themes/moonshine/.oxfmtrc.json",
|
||||
"oxc.path.oxfmt": "wp-content/themes/moonshine/node_modules/.bin/oxfmt",
|
||||
"oxc.path.oxlint": "wp-content/themes/moonshine/node_modules/.bin/oxlint",
|
||||
"oxc.tsConfigPath": "wp-content/themes/moonshine/tsconfig.json",
|
||||
"tailwindCSS.classAttributes": ["class", "ui"],
|
||||
"tailwindCSS.experimental.classRegex": [["ui:\\s*{([^)]*)\\s*}", "(?:'|\"|`)([^']*)(?:'|\"|`)"]],
|
||||
"typescript.tsdk": "wp-content/themes/moonshine/node_modules/typescript/lib"
|
||||
}
|
||||
@@ -3,4 +3,3 @@
|
||||
Headless WordPress project boilerplate using Nuxt.
|
||||
|
||||
[✨ Release notes](/wp-content/themes/moonshine/CHANGELOG.md)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lewebsimple/wp-headless",
|
||||
"description": "WordPress project",
|
||||
"description": "WP Headless",
|
||||
"version": "0.4.25",
|
||||
"type": "project",
|
||||
"license": "MIT",
|
||||
@@ -32,12 +32,16 @@
|
||||
"lintfix": "vendor/bin/phpcbf"
|
||||
},
|
||||
"require": {
|
||||
"axepress/wp-graphql-rank-math": "*",
|
||||
"lewebsimple/acf-phone": "*",
|
||||
"lewebsimple/advanced-custom-fields-pro": "*",
|
||||
"lewebsimple/kaliroots": "*",
|
||||
"lewebsimple/wp-graphql-headless-login": "*",
|
||||
"wpackagist-plugin/acf-extended": "*",
|
||||
"wpackagist-plugin/clean-image-filenames": "*",
|
||||
"wpackagist-plugin/disable-comments": "*",
|
||||
"wpackagist-plugin/media-focus-point": "*",
|
||||
"wpackagist-plugin/seo-by-rank-math": "*",
|
||||
"wpackagist-plugin/wp-graphql": "*",
|
||||
"wpackagist-plugin/wpgraphql-acf": "*"
|
||||
},
|
||||
|
||||
258
composer.lock
generated
258
composer.lock
generated
@@ -4,8 +4,169 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "aec2b0e396a71ea02fe95432358ca91e",
|
||||
"content-hash": "e3ce417e8c09ed84502559af141f6530",
|
||||
"packages": [
|
||||
{
|
||||
"name": "axepress/wp-graphql-plugin-boilerplate",
|
||||
"version": "0.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/AxeWP/wp-graphql-plugin-boilerplate.git",
|
||||
"reference": "09495b61346453baabdf4c71a38ada3cfc91c3a7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/AxeWP/wp-graphql-plugin-boilerplate/zipball/09495b61346453baabdf4c71a38ada3cfc91c3a7",
|
||||
"reference": "09495b61346453baabdf4c71a38ada3cfc91c3a7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"axepress/wp-graphql-cs": "^2.0.0",
|
||||
"axepress/wp-graphql-stubs": "^2.3.0",
|
||||
"phpcompatibility/php-compatibility": "dev-develop as 9.9.9",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpstan/phpstan-deprecation-rules": "^2.0.1",
|
||||
"szepeviktor/phpstan-wordpress": "^2.0",
|
||||
"wp-cli/wp-cli-bundle": "^2.8.1"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"AxeWP\\GraphQL\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-3.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "AxePress Development",
|
||||
"homepage": "https://axepress.dev"
|
||||
},
|
||||
{
|
||||
"name": "David Levine",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Boilerplate for creating WPGraphQL extensions",
|
||||
"support": {
|
||||
"issues": "https://github.com/AxeWP/wp-graphql-plugin-boilerplate/issues",
|
||||
"source": "https://github.com/AxeWP/wp-graphql-plugin-boilerplate/tree/0.1.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/AxeWp",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-06-07T02:03:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "axepress/wp-graphql-rank-math",
|
||||
"version": "0.3.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/AxeWP/wp-graphql-rank-math.git",
|
||||
"reference": "167bdd4a5350717ed34069c304e0ffc3fe02bc7d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/AxeWP/wp-graphql-rank-math/zipball/167bdd4a5350717ed34069c304e0ffc3fe02bc7d",
|
||||
"reference": "167bdd4a5350717ed34069c304e0ffc3fe02bc7d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"axepress/wp-graphql-plugin-boilerplate": "^0.1.1",
|
||||
"php": ">=7.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"axepress/wp-graphql-cs": "^2.0.0",
|
||||
"axepress/wp-graphql-stubs": "^2.0.0",
|
||||
"codeception/lib-innerbrowser": "^1.0",
|
||||
"codeception/module-asserts": "^1.0",
|
||||
"codeception/module-cli": "^1.0",
|
||||
"codeception/module-db": "^1.0",
|
||||
"codeception/module-filesystem": "^1.0",
|
||||
"codeception/module-phpbrowser": "^1.0",
|
||||
"codeception/module-rest": "^2.0",
|
||||
"codeception/module-webdriver": "^1.0",
|
||||
"codeception/phpunit-wrapper": "^9.0",
|
||||
"codeception/util-universalframework": "^1.0",
|
||||
"lucatume/wp-browser": "<3.5",
|
||||
"php-coveralls/php-coveralls": "^2.5",
|
||||
"phpcompatibility/php-compatibility": "dev-develop as 9.9.9",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^2.1.5",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"szepeviktor/phpstan-wordpress": "^2.0.1",
|
||||
"wp-cli/wp-cli-bundle": "^2.8.1",
|
||||
"wp-graphql/wp-graphql-testcase": "~3.4.0"
|
||||
},
|
||||
"type": "wordpress-plugin",
|
||||
"extra": {
|
||||
"strauss": {
|
||||
"packages": [
|
||||
"axepress/wp-graphql-plugin-boilerplate"
|
||||
],
|
||||
"classmap_prefix": "WPGraphQL_RankMath_",
|
||||
"constant_prefix": "WPGRAPHQL_SEO_",
|
||||
"namespace_prefix": "WPGraphQL\\RankMath\\Vendor\\",
|
||||
"target_directory": "vendor-prefixed",
|
||||
"update_call_sites": false,
|
||||
"exclude_from_prefix": {
|
||||
"namespaces": [],
|
||||
"file_patterns": []
|
||||
},
|
||||
"include_modified_date": false,
|
||||
"delete_vendor_packages": true
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"access-functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"WPGraphQL\\RankMath\\": "src/"
|
||||
},
|
||||
"classmap": [
|
||||
"vendor-prefixed/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-3.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "AxePress Development",
|
||||
"email": "support@axepress.dev",
|
||||
"homepage": "https://axepress.dev"
|
||||
},
|
||||
{
|
||||
"name": "David Levine",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Adds WPGraphQL support for RankMath SEO",
|
||||
"support": {
|
||||
"email": "support@axepress.dev",
|
||||
"forum": "https://github.com/AxeWP/wp-graphql-rank-math/discussions",
|
||||
"issues": "https://github.com/AxeWP/wp-graphql-rank-math/issues",
|
||||
"source": "https://github.com/AxeWP/wp-graphql-rank-math/tree/0.3.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sponsors/AxeWP",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-06-07T12:05:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/installers",
|
||||
"version": "v2.3.0",
|
||||
@@ -152,6 +313,43 @@
|
||||
],
|
||||
"time": "2024-06-24T20:46:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lewebsimple/acf-phone",
|
||||
"version": "v3.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/lewebsimple/acf-phone.git",
|
||||
"reference": "cf4c6440e0c2cdf7e422423bb629014204e721bf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://satis.ledevsimple.ca/dist/lewebsimple/acf-phone/lewebsimple-acf-phone-cf4c6440e0c2cdf7e422423bb629014204e721bf-zip-439080.zip",
|
||||
"reference": "cf4c6440e0c2cdf7e422423bb629014204e721bf",
|
||||
"shasum": "f9d7cbcf27985656245285e5bc035578621f1a69"
|
||||
},
|
||||
"require-dev": {
|
||||
"lewebsimple/wp-phpcs-ruleset": "*",
|
||||
"php-stubs/acf-pro-stubs": "*",
|
||||
"squizlabs/php_codesniffer": "*"
|
||||
},
|
||||
"type": "wordpress-plugin",
|
||||
"scripts": {
|
||||
"post-create-project-cmd": [
|
||||
"./scripts/post-create.sh"
|
||||
],
|
||||
"lint": [
|
||||
"vendor/bin/phpcs"
|
||||
],
|
||||
"lintfix": [
|
||||
"vendor/bin/phpcbf"
|
||||
]
|
||||
},
|
||||
"support": {
|
||||
"source": "https://github.com/lewebsimple/acf-phone/tree/v3.1.0",
|
||||
"issues": "https://github.com/lewebsimple/acf-phone/issues"
|
||||
},
|
||||
"time": "2026-01-30T15:01:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "lewebsimple/advanced-custom-fields-pro",
|
||||
"version": "v6.7.0.2",
|
||||
@@ -205,15 +403,15 @@
|
||||
},
|
||||
{
|
||||
"name": "wpackagist-plugin/acf-extended",
|
||||
"version": "0.9.2.2",
|
||||
"version": "0.9.2.3",
|
||||
"source": {
|
||||
"type": "svn",
|
||||
"url": "https://plugins.svn.wordpress.org/acf-extended/",
|
||||
"reference": "tags/0.9.2.2"
|
||||
"reference": "tags/0.9.2.3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://downloads.wordpress.org/plugin/acf-extended.0.9.2.2.zip"
|
||||
"url": "https://downloads.wordpress.org/plugin/acf-extended.0.9.2.3.zip"
|
||||
},
|
||||
"require": {
|
||||
"composer/installers": "^1.0 || ^2.0"
|
||||
@@ -241,15 +439,15 @@
|
||||
},
|
||||
{
|
||||
"name": "wpackagist-plugin/disable-comments",
|
||||
"version": "2.6.1",
|
||||
"version": "2.6.2",
|
||||
"source": {
|
||||
"type": "svn",
|
||||
"url": "https://plugins.svn.wordpress.org/disable-comments/",
|
||||
"reference": "tags/2.6.1"
|
||||
"reference": "tags/2.6.2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://downloads.wordpress.org/plugin/disable-comments.2.6.1.zip"
|
||||
"url": "https://downloads.wordpress.org/plugin/disable-comments.2.6.2.zip"
|
||||
},
|
||||
"require": {
|
||||
"composer/installers": "^1.0 || ^2.0"
|
||||
@@ -258,16 +456,52 @@
|
||||
"homepage": "https://wordpress.org/plugins/disable-comments/"
|
||||
},
|
||||
{
|
||||
"name": "wpackagist-plugin/wp-graphql",
|
||||
"version": "2.6.0",
|
||||
"name": "wpackagist-plugin/media-focus-point",
|
||||
"version": "2.0.4",
|
||||
"source": {
|
||||
"type": "svn",
|
||||
"url": "https://plugins.svn.wordpress.org/wp-graphql/",
|
||||
"reference": "tags/2.6.0"
|
||||
"url": "https://plugins.svn.wordpress.org/media-focus-point/",
|
||||
"reference": "tags/2.0.4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://downloads.wordpress.org/plugin/wp-graphql.2.6.0.zip"
|
||||
"url": "https://downloads.wordpress.org/plugin/media-focus-point.2.0.4.zip"
|
||||
},
|
||||
"require": {
|
||||
"composer/installers": "^1.0 || ^2.0"
|
||||
},
|
||||
"type": "wordpress-plugin",
|
||||
"homepage": "https://wordpress.org/plugins/media-focus-point/"
|
||||
},
|
||||
{
|
||||
"name": "wpackagist-plugin/seo-by-rank-math",
|
||||
"version": "1.0.263",
|
||||
"source": {
|
||||
"type": "svn",
|
||||
"url": "https://plugins.svn.wordpress.org/seo-by-rank-math/",
|
||||
"reference": "tags/1.0.263"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://downloads.wordpress.org/plugin/seo-by-rank-math.1.0.263.zip"
|
||||
},
|
||||
"require": {
|
||||
"composer/installers": "^1.0 || ^2.0"
|
||||
},
|
||||
"type": "wordpress-plugin",
|
||||
"homepage": "https://wordpress.org/plugins/seo-by-rank-math/"
|
||||
},
|
||||
{
|
||||
"name": "wpackagist-plugin/wp-graphql",
|
||||
"version": "2.8.0",
|
||||
"source": {
|
||||
"type": "svn",
|
||||
"url": "https://plugins.svn.wordpress.org/wp-graphql/",
|
||||
"reference": "tags/2.8.0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://downloads.wordpress.org/plugin/wp-graphql.2.8.0.zip"
|
||||
},
|
||||
"require": {
|
||||
"composer/installers": "^1.0 || ^2.0"
|
||||
|
||||
20
wp-content/mu-plugins/headless-home-url.php
Normal file
20
wp-content/mu-plugins/headless-home-url.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
// Customize home URL for headless WordPress
|
||||
add_filter( 'home_url', 'headless_home_url', 10, 4 );
|
||||
function headless_home_url( $url, $path, $orig_scheme, $blog_id ) {
|
||||
// Exclude specific patterns from rewriting
|
||||
$excluded_patterns = array(
|
||||
'#/wp-json(/|$)#i', // WP REST API
|
||||
'#\.(xsl|xml)$#i', // Sitemap and XSLT files
|
||||
);
|
||||
foreach ( $excluded_patterns as $pattern ) {
|
||||
if ( preg_match( $pattern, $url ) ) {
|
||||
return get_site_url( $blog_id, $path, $orig_scheme );
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite URL protocol to match original home scheme
|
||||
$scheme = wp_parse_url( get_option( 'home' ) )['scheme'] ?? 'https';
|
||||
return preg_replace( '#^https:#i', "$scheme:", $url );
|
||||
}
|
||||
4
wp-content/themes/moonshine/.gitignore
vendored
4
wp-content/themes/moonshine/.gitignore
vendored
@@ -22,3 +22,7 @@ logs
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Wrangler files
|
||||
.wrangler
|
||||
server/types/cloudflare.d.ts
|
||||
|
||||
20
wp-content/themes/moonshine/.oxfmtrc.json
Normal file
20
wp-content/themes/moonshine/.oxfmtrc.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
||||
"experimentalSortImports": {
|
||||
"groups": [
|
||||
["side-effect"],
|
||||
["builtin"],
|
||||
["external", "type-external"],
|
||||
["internal", "type-internal"],
|
||||
["parent", "type-parent"],
|
||||
["sibling", "type-sibling"],
|
||||
["index", "type-index"]
|
||||
]
|
||||
},
|
||||
"experimentalTailwindcss": {
|
||||
"attributes": ["class"],
|
||||
"functions": ["tv"],
|
||||
"preserveWhitespace": true,
|
||||
"stylesheet": "./app/assets/css/_main.css"
|
||||
}
|
||||
}
|
||||
22
wp-content/themes/moonshine/.oxlintrc.json
Normal file
22
wp-content/themes/moonshine/.oxlintrc.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||
"categories": {},
|
||||
"env": {
|
||||
"builtin": true,
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
"globals": {},
|
||||
"ignorePatterns": [],
|
||||
"plugins": ["import", "vue"],
|
||||
"rules": {
|
||||
"vue/define-emits-declaration": ["error", "type-based"],
|
||||
"vue/define-props-declaration": ["error", "type-based"],
|
||||
"vue/require-typed-ref": "error"
|
||||
},
|
||||
"settings": {
|
||||
"vitest": {
|
||||
"typecheck": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,178 @@
|
||||
# Changelog
|
||||
|
||||
## v0.1.13
|
||||
|
||||
[compare changes](https://gitea.websimple.com/wp-sites/wp-headless/compare/v0.1.12...v0.1.13)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- TinyMCE list style (8ae6daf)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Wrangler.json needed for wrangler types before build (faf39ca)
|
||||
|
||||
## v0.1.12
|
||||
|
||||
[compare changes](https://gitea.websimple.com/wp-sites/wp-headless/compare/v0.1.11...v0.1.12)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- ConnexionButton (87be06e)
|
||||
- ShowLabel (98e8d97)
|
||||
- ParseAcfLink (2cfc1a0)
|
||||
- ParseAcfMedia (ab563a7)
|
||||
- Event context type for Cloudflare environment (4338028)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- UApp in app.vue (28f6e1a)
|
||||
|
||||
## v0.1.11
|
||||
|
||||
[compare changes](https://gitea.websimple.com/wp-sites/wp-headless/compare/v0.1.10...v0.1.11)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- MapSocialIcon (6dd13ea)
|
||||
- AcfSocial / parseAcfSocial (3199835)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Remove unneeded wrangler main / assets (eea020b)
|
||||
- Cloudflare image provider only in production (291fa6e)
|
||||
- Wrangler project name (8f037b5)
|
||||
- ENABLE_CLOUDFLARE_IMAGE (9c3dcee)
|
||||
|
||||
## v0.1.10
|
||||
|
||||
[compare changes](https://gitea.websimple.com/templates/wp-headless/compare/v0.1.9...v0.1.10)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- GroupSiteOptions.phoneNumber (ad3c53c)
|
||||
- AcfPhone component (6b17201)
|
||||
- AcfLink / AcfLinkButton components (115a5d2)
|
||||
|
||||
### 💅 Refactors
|
||||
|
||||
- OptionsSite => SiteOptions for clearer naming (fefa980)
|
||||
|
||||
## v0.1.9
|
||||
|
||||
[compare changes](https://gitea.websimple.com/templates/wp-headless/compare/v0.1.8...v0.1.9)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Enhance refreshAuthToken to prevent duplicate requests (5e39b53)
|
||||
- Default site-logo.svg (238aa29)
|
||||
- Initial Media / HeroSplit acf groups (0fbd2bf)
|
||||
- Media Focus Point plugin integration (bff7bce)
|
||||
- AcfImage component based on @nuxt/image (4918c63)
|
||||
- AcfMedia component (image + aspect + object-fit) (8bd544b)
|
||||
- HeroSplit section (0bafc3a)
|
||||
|
||||
## v0.1.8
|
||||
|
||||
[compare changes](https://gitea.websimple.com/templates/wp-headless/compare/v0.1.7...v0.1.8)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- UseResponsive with device detection on SSR (c82bf47)
|
||||
- Graphql cache keyPrefix from package.json version (b1b1aa4)
|
||||
- All of wrangler config in nuxt.config.ts (21a7036)
|
||||
- Configure nuxt-svgo module (5f9c29c)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Headless_home_url needs to be in mu-plugins (51f594b)
|
||||
- Use public wpUrl runtime config for auth refresh token mutation (2c86905)
|
||||
- Term_order and default WPGraphQL settings (a27e6af)
|
||||
- Update nuxt-graphql and extractNodes typing (maybe => undefined instead of null) (27f4f73)
|
||||
|
||||
## v0.1.7
|
||||
|
||||
[compare changes](https://gitea.websimple.com/templates/wp-headless/compare/v0.1.6...v0.1.7)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Configure sitemap URL in robots.txt (63f8e44)
|
||||
- Deploy to Cloudflare workers (c6dfbeb)
|
||||
- Display theme version in admin footer (b886585)
|
||||
|
||||
## v0.1.6
|
||||
|
||||
[compare changes](https://gitea.websimple.com/templates/wp-headless/compare/v0.1.5...v0.1.6)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Site options page & field group (489ac82)
|
||||
- Initial SEO integration (c5ce607)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Bypass headless home URL for specific cases (108269e)
|
||||
|
||||
## v0.1.5
|
||||
|
||||
[compare changes](https://gitea.websimple.com/templates/wp-headless/compare/v0.1.4...v0.1.5)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Auth server utils upgrade to latest nuxt-graphql (fd61895)
|
||||
- Immutable extractNodes (baa3061)
|
||||
- Type issue with NodePage (3b706c0)
|
||||
|
||||
## v0.1.4
|
||||
|
||||
[compare changes](https://gitea.websimple.com/templates/wp-headless/compare/v0.1.2...v0.1.4)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Initial NodeByUri logic and frontend (688c4e3)
|
||||
- BuilderSections component (2b9a875)
|
||||
- LaoutContained (c7f6cca)
|
||||
- LayoutContained section wrapper (12048ff)
|
||||
- Initial typography / prose styles (764bc6a)
|
||||
- UiProse prose component with link highjacking (40becf1)
|
||||
- TinyMCE WYSIWYG editor styles (8e26f19)
|
||||
- Login / logout toast (2d0b176)
|
||||
- Hide title on front page (5e0df22)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Fatal 404 (bfb5ae3)
|
||||
|
||||
### 💅 Refactors
|
||||
|
||||
- Update to nuxt-graphql 0.5.x (e383255)
|
||||
- /api/login route (9d99770)
|
||||
|
||||
## v0.1.3
|
||||
|
||||
[compare changes](https://gitea.websimple.com/templates/wp-headless/compare/v0.1.2...v0.1.3)
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Initial NodeByUri logic and frontend (688c4e3)
|
||||
- BuilderSections component (2b9a875)
|
||||
- LaoutContained (c7f6cca)
|
||||
- LayoutContained section wrapper (12048ff)
|
||||
- Initial typography / prose styles (764bc6a)
|
||||
- UiProse prose component with link highjacking (40becf1)
|
||||
- TinyMCE WYSIWYG editor styles (8e26f19)
|
||||
- Login / logout toast (2d0b176)
|
||||
- Hide title on front page (5e0df22)
|
||||
|
||||
### 🩹 Fixes
|
||||
|
||||
- Fatal 404 (bfb5ae3)
|
||||
|
||||
### 💅 Refactors
|
||||
|
||||
- Update to nuxt-graphql 0.5.x (e383255)
|
||||
- /api/login route (9d99770)
|
||||
|
||||
## v0.1.2
|
||||
|
||||
[compare changes](https://gitea.websimple.com/templates/wp-headless/compare/v0.1.1...v0.1.2)
|
||||
@@ -17,7 +190,6 @@
|
||||
|
||||
## v0.1.1
|
||||
|
||||
|
||||
### 🚀 Enhancements
|
||||
|
||||
- Initial Moonshine theme - Headless WordPress theme based on Nuxt (b3134fe)
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
# Moonshine
|
||||
|
||||
Headless WordPress theme based on Nuxt.
|
||||
Thème WordPress en headless basé sur Nuxt.
|
||||
|
||||
## Variables d'environnement
|
||||
|
||||
| Nom | Description | Exemple | Requise |
|
||||
| --------------- | ------------------------ | ----------------------- | ------- |
|
||||
| `NUXT_SITE_ENV` | Environnement | staging \| production | ➖ |
|
||||
| `NUXT_SITE_URL` | URL du frontend Nuxt | https://www.example.com | ➖ |
|
||||
| `NUXT_WP_URL` | URL du backend WordPress | https://wp.exemple.com | ✅ |
|
||||
|
||||
## Secrets
|
||||
|
||||
Configurer les secrets nécessaires au projet:
|
||||
|
||||
```sh
|
||||
pnpm wrangler secret put NUXT_SESSION_PASSWORD
|
||||
```
|
||||
|
||||
240
wp-content/themes/moonshine/acf-json/group_abstract_builder.json
Normal file
240
wp-content/themes/moonshine/acf-json/group_abstract_builder.json
Normal file
@@ -0,0 +1,240 @@
|
||||
{
|
||||
"key": "group_abstract_builder",
|
||||
"title": "Abstract - Builder",
|
||||
"fields": [
|
||||
{
|
||||
"key": "field_builder_sections",
|
||||
"label": "Section(s)",
|
||||
"name": "sections",
|
||||
"aria-label": "",
|
||||
"type": "flexible_content",
|
||||
"instructions": "",
|
||||
"required": 0,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"acfe_flexible_advanced": 1,
|
||||
"acfe_flexible_stylised_button": 0,
|
||||
"acfe_flexible_hide_empty_message": 0,
|
||||
"acfe_flexible_empty_message": "",
|
||||
"acfe_flexible_layouts_templates": 0,
|
||||
"acfe_flexible_layouts_placeholder": 0,
|
||||
"acfe_flexible_layouts_thumbnails": 0,
|
||||
"acfe_flexible_async": [],
|
||||
"acfe_flexible_add_actions": ["copy", "title", "toggle"],
|
||||
"acfe_flexible_remove_button": [],
|
||||
"acfe_flexible_remove_top_actions": [],
|
||||
"acfe_flexible_modal_edit": {
|
||||
"acfe_flexible_modal_edit_enabled": "1",
|
||||
"acfe_flexible_modal_edit_size": "xlarge"
|
||||
},
|
||||
"acfe_flexible_modal": {
|
||||
"acfe_flexible_modal_enabled": "0",
|
||||
"acfe_flexible_modal_title": false,
|
||||
"acfe_flexible_modal_size": "xlarge",
|
||||
"acfe_flexible_modal_col": "4",
|
||||
"acfe_flexible_modal_categories": false
|
||||
},
|
||||
"acfe_flexible_modal_settings": {
|
||||
"acfe_flexible_modal_settings_enabled": "1",
|
||||
"acfe_flexible_modal_settings_size": "large",
|
||||
"acfe_flexible_modal_settings_close": "1",
|
||||
"acfe_flexible_modal_settings_close_label": ""
|
||||
},
|
||||
"layouts": {
|
||||
"layout_6852f761e95b0": {
|
||||
"key": "layout_6852f761e95b0",
|
||||
"name": "text_block",
|
||||
"label": "Bloc de texte",
|
||||
"display": "block",
|
||||
"sub_fields": [
|
||||
{
|
||||
"key": "field_68eeceb62b8a6",
|
||||
"label": "Contenu",
|
||||
"name": "content",
|
||||
"aria-label": "",
|
||||
"type": "wysiwyg",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"default_value": "",
|
||||
"acfe_wysiwyg_height": 300,
|
||||
"acfe_wysiwyg_max_height": "",
|
||||
"acfe_wysiwyg_valid_elements": "",
|
||||
"acfe_wysiwyg_custom_style": "",
|
||||
"acfe_wysiwyg_disable_wp_style": 0,
|
||||
"acfe_wysiwyg_autoresize": 0,
|
||||
"acfe_wysiwyg_disable_resize": 0,
|
||||
"acfe_wysiwyg_remove_path": 0,
|
||||
"acfe_wysiwyg_menubar": 0,
|
||||
"acfe_wysiwyg_transparent": 0,
|
||||
"acfe_wysiwyg_merge_toolbar": 0,
|
||||
"acfe_wysiwyg_custom_toolbar": 0,
|
||||
"required_message": "",
|
||||
"allow_in_bindings": 0,
|
||||
"tabs": "all",
|
||||
"toolbar": "full",
|
||||
"media_upload": 1,
|
||||
"delay": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "content",
|
||||
"graphql_non_null": 1,
|
||||
"acfe_wysiwyg_auto_init": 0,
|
||||
"acfe_wysiwyg_min_height": 300,
|
||||
"acfe_wysiwyg_toolbar_buttons": []
|
||||
}
|
||||
],
|
||||
"min": "",
|
||||
"max": "",
|
||||
"acfe_flexible_modal_edit_size": "",
|
||||
"acfe_flexible_settings": ["group_layout_contained"],
|
||||
"acfe_flexible_settings_size": "large",
|
||||
"acfe_flexible_render_template": false,
|
||||
"acfe_flexible_render_style": false,
|
||||
"acfe_flexible_render_script": false,
|
||||
"acfe_flexible_thumbnail": false,
|
||||
"acfe_flexible_category": false
|
||||
},
|
||||
"layout_697caf9a3e05b": {
|
||||
"key": "layout_697caf9a3e05b",
|
||||
"name": "hero_split",
|
||||
"label": "Héro en moitié",
|
||||
"display": "block",
|
||||
"sub_fields": [
|
||||
{
|
||||
"key": "field_697cafb13e05d",
|
||||
"label": "Content",
|
||||
"name": "content",
|
||||
"aria-label": "",
|
||||
"type": "wysiwyg",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"default_value": "",
|
||||
"allow_in_bindings": 0,
|
||||
"tabs": "all",
|
||||
"toolbar": "full",
|
||||
"media_upload": 0,
|
||||
"delay": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "content",
|
||||
"graphql_non_null": 1
|
||||
},
|
||||
{
|
||||
"key": "field_697cafc43e05e",
|
||||
"label": "Media",
|
||||
"name": "media",
|
||||
"aria-label": "",
|
||||
"type": "clone",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"graphql_field_name": "media",
|
||||
"clone": ["group_abstract_media"],
|
||||
"display": "seamless",
|
||||
"layout": "block",
|
||||
"prefix_label": 0,
|
||||
"prefix_name": 0,
|
||||
"acfe_seamless_style": 0,
|
||||
"acfe_clone_modal": 0,
|
||||
"acfe_clone_modal_close": 0,
|
||||
"acfe_clone_modal_button": "",
|
||||
"acfe_clone_modal_size": "large"
|
||||
},
|
||||
{
|
||||
"key": "field_697cafdc3e05f",
|
||||
"label": "Position de l'image",
|
||||
"name": "reverse",
|
||||
"aria-label": "",
|
||||
"type": "true_false",
|
||||
"instructions": "",
|
||||
"required": 0,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"message": "",
|
||||
"default_value": 0,
|
||||
"allow_in_bindings": 0,
|
||||
"ui_on_text": "Gauche",
|
||||
"ui_off_text": "Droite",
|
||||
"ui": 1,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "reverse",
|
||||
"graphql_non_null": 1
|
||||
}
|
||||
],
|
||||
"min": "",
|
||||
"max": "",
|
||||
"acfe_flexible_modal_edit_size": "",
|
||||
"acfe_flexible_settings": "",
|
||||
"acfe_flexible_settings_size": "large",
|
||||
"acfe_flexible_render_template": false,
|
||||
"acfe_flexible_render_style": false,
|
||||
"acfe_flexible_render_script": false,
|
||||
"acfe_flexible_thumbnail": false,
|
||||
"acfe_flexible_category": false
|
||||
}
|
||||
},
|
||||
"min": "",
|
||||
"max": "",
|
||||
"button_label": "Ajouter un élément",
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "sections",
|
||||
"graphql_non_null": 0,
|
||||
"acfe_flexible_layouts_previews": false,
|
||||
"acfe_flexible_close_button_label": "",
|
||||
"acfe_flexible_layouts_state": false
|
||||
}
|
||||
],
|
||||
"location": [
|
||||
[
|
||||
{
|
||||
"param": "abstract"
|
||||
}
|
||||
]
|
||||
],
|
||||
"menu_order": 0,
|
||||
"position": "acf_after_title",
|
||||
"style": "seamless",
|
||||
"label_placement": "top",
|
||||
"instruction_placement": "label",
|
||||
"hide_on_screen": ["the_content"],
|
||||
"active": true,
|
||||
"description": "",
|
||||
"show_in_rest": 0,
|
||||
"display_title": "",
|
||||
"acfe_autosync": ["json"],
|
||||
"acfe_form": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_field_name": "GroupAbstractBuilder",
|
||||
"map_graphql_types_from_location_rules": 0,
|
||||
"graphql_types": "",
|
||||
"acfe_meta": "",
|
||||
"acfe_note": "",
|
||||
"modified": 1769779666
|
||||
}
|
||||
121
wp-content/themes/moonshine/acf-json/group_abstract_media.json
Normal file
121
wp-content/themes/moonshine/acf-json/group_abstract_media.json
Normal file
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"key": "group_abstract_media",
|
||||
"title": "Abstract - Media",
|
||||
"fields": [
|
||||
{
|
||||
"key": "field_697caec68536d",
|
||||
"label": "Image",
|
||||
"name": "image",
|
||||
"aria-label": "",
|
||||
"type": "image",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "33",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"uploader": "",
|
||||
"return_format": "array",
|
||||
"library": "all",
|
||||
"acfe_thumbnail": 0,
|
||||
"min_width": "",
|
||||
"min_height": "",
|
||||
"min_size": "",
|
||||
"max_width": "",
|
||||
"max_height": "",
|
||||
"max_size": "",
|
||||
"mime_types": "",
|
||||
"allow_in_bindings": 0,
|
||||
"preview_size": "medium",
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "image"
|
||||
},
|
||||
{
|
||||
"key": "field_697caf018536e",
|
||||
"label": "Ratio d'aspect",
|
||||
"name": "aspect_ratio",
|
||||
"aria-label": "",
|
||||
"type": "button_group",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "33",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"choices": {
|
||||
"square": "Carré (1:1)",
|
||||
"video": "Vidéo (16:9)",
|
||||
"portrait": "Portrait (2:3)",
|
||||
"auto": "Aspect d'origine"
|
||||
},
|
||||
"default_value": "auto",
|
||||
"return_format": "value",
|
||||
"allow_null": 0,
|
||||
"allow_in_bindings": 0,
|
||||
"layout": "horizontal",
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "aspectRatio",
|
||||
"graphql_non_null": 1
|
||||
},
|
||||
{
|
||||
"key": "field_697caf378536f",
|
||||
"label": "Ajustement de l'image",
|
||||
"name": "object_fit",
|
||||
"aria-label": "",
|
||||
"type": "button_group",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "33",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"choices": {
|
||||
"cover": "Recadrer si nécessaire",
|
||||
"contain": "Contenir sans recadrage"
|
||||
},
|
||||
"default_value": "cover",
|
||||
"return_format": "value",
|
||||
"allow_null": 0,
|
||||
"allow_in_bindings": 0,
|
||||
"layout": "horizontal",
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "objectFit",
|
||||
"graphql_non_null": 1
|
||||
}
|
||||
],
|
||||
"location": [
|
||||
[
|
||||
{
|
||||
"param": "abstract"
|
||||
}
|
||||
]
|
||||
],
|
||||
"menu_order": 0,
|
||||
"position": "normal",
|
||||
"style": "seamless",
|
||||
"label_placement": "top",
|
||||
"instruction_placement": "label",
|
||||
"hide_on_screen": "",
|
||||
"active": true,
|
||||
"description": "",
|
||||
"show_in_rest": 0,
|
||||
"display_title": "",
|
||||
"acfe_autosync": ["json"],
|
||||
"acfe_form": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_field_name": "GroupAbstractMedia",
|
||||
"map_graphql_types_from_location_rules": 0,
|
||||
"graphql_types": "",
|
||||
"acfe_meta": "",
|
||||
"acfe_note": "",
|
||||
"modified": 1769779078
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"key": "group_abstract_social",
|
||||
"title": "Abstract - Social",
|
||||
"fields": [
|
||||
{
|
||||
"key": "field_6855a1d643408",
|
||||
"label": "Médias sociaux",
|
||||
"name": "profiles",
|
||||
"aria-label": "",
|
||||
"type": "repeater",
|
||||
"instructions": "",
|
||||
"required": 0,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"acfe_repeater_stylised_button": 0,
|
||||
"layout": "table",
|
||||
"pagination": 0,
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"collapsed": "",
|
||||
"button_label": "Ajouter un élément",
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "profiles",
|
||||
"graphql_non_null": 1,
|
||||
"rows_per_page": 20,
|
||||
"sub_fields": [
|
||||
{
|
||||
"key": "field_6855a7e143409",
|
||||
"label": "URL",
|
||||
"name": "url",
|
||||
"aria-label": "",
|
||||
"type": "url",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"default_value": "",
|
||||
"allow_in_bindings": 0,
|
||||
"placeholder": "",
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "url",
|
||||
"graphql_non_null": 1,
|
||||
"parent_repeater": "field_6855a1d643408"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"location": [
|
||||
[
|
||||
{
|
||||
"param": "abstract"
|
||||
}
|
||||
]
|
||||
],
|
||||
"menu_order": 0,
|
||||
"position": "normal",
|
||||
"style": "seamless",
|
||||
"label_placement": "top",
|
||||
"instruction_placement": "label",
|
||||
"hide_on_screen": "",
|
||||
"active": true,
|
||||
"description": "",
|
||||
"show_in_rest": 0,
|
||||
"display_title": "",
|
||||
"acfe_autosync": ["json"],
|
||||
"acfe_form": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_field_name": "GroupAbstractSocial",
|
||||
"map_graphql_types_from_location_rules": 0,
|
||||
"graphql_types": "",
|
||||
"acfe_meta": "",
|
||||
"acfe_note": "",
|
||||
"modified": 1769788591
|
||||
}
|
||||
147
wp-content/themes/moonshine/acf-json/group_layout_contained.json
Normal file
147
wp-content/themes/moonshine/acf-json/group_layout_contained.json
Normal file
@@ -0,0 +1,147 @@
|
||||
{
|
||||
"key": "group_layout_contained",
|
||||
"title": "Layout - Contained",
|
||||
"fields": [
|
||||
{
|
||||
"key": "field_68dc29d78941c",
|
||||
"label": "Conteneur",
|
||||
"name": "container",
|
||||
"aria-label": "",
|
||||
"type": "select",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"choices": {
|
||||
"default": "1536px",
|
||||
"xl": "1280px",
|
||||
"lg": "1024px",
|
||||
"fluid": "Largeur fluide",
|
||||
"none": "Pleine largeur"
|
||||
},
|
||||
"default_value": "default",
|
||||
"return_format": "value",
|
||||
"multiple": 0,
|
||||
"max": "",
|
||||
"prepend": "",
|
||||
"append": "",
|
||||
"required_message": "",
|
||||
"allow_null": 0,
|
||||
"allow_in_bindings": 0,
|
||||
"ui": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "container",
|
||||
"graphql_non_null": 1,
|
||||
"ajax": 0,
|
||||
"placeholder": "",
|
||||
"create_options": 0,
|
||||
"save_options": 0,
|
||||
"allow_custom": 0,
|
||||
"search_placeholder": "",
|
||||
"min": ""
|
||||
},
|
||||
{
|
||||
"key": "field_693c8c3b5ce50",
|
||||
"label": "Espacement vertical",
|
||||
"name": "vertical_padding",
|
||||
"aria-label": "",
|
||||
"type": "select",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"choices": {
|
||||
"sm": "Petit (12px)",
|
||||
"md": "Medium (24px)",
|
||||
"lg": "Grand (48px)"
|
||||
},
|
||||
"default_value": "md",
|
||||
"return_format": "value",
|
||||
"multiple": 0,
|
||||
"allow_null": 0,
|
||||
"allow_in_bindings": 0,
|
||||
"ui": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "verticalPadding",
|
||||
"graphql_non_null": 1,
|
||||
"ajax": 0,
|
||||
"placeholder": "",
|
||||
"create_options": 0,
|
||||
"save_options": 0,
|
||||
"allow_custom": 0,
|
||||
"search_placeholder": ""
|
||||
},
|
||||
{
|
||||
"key": "field_693c8c945ce51",
|
||||
"label": "Couleur d'arrière-plan",
|
||||
"name": "bg_color",
|
||||
"aria-label": "",
|
||||
"type": "select",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"choices": {
|
||||
"default": "Par défaut",
|
||||
"muted": "Atténué",
|
||||
"inverted": "Inversé"
|
||||
},
|
||||
"default_value": "default",
|
||||
"return_format": "value",
|
||||
"multiple": 0,
|
||||
"allow_null": 0,
|
||||
"allow_in_bindings": 0,
|
||||
"ui": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "bgColor",
|
||||
"graphql_non_null": 1,
|
||||
"ajax": 0,
|
||||
"placeholder": "",
|
||||
"create_options": 0,
|
||||
"save_options": 0,
|
||||
"allow_custom": 0,
|
||||
"search_placeholder": ""
|
||||
}
|
||||
],
|
||||
"location": [
|
||||
[
|
||||
{
|
||||
"param": "abstract"
|
||||
}
|
||||
]
|
||||
],
|
||||
"menu_order": 0,
|
||||
"position": "normal",
|
||||
"style": "default",
|
||||
"label_placement": "top",
|
||||
"instruction_placement": "label",
|
||||
"hide_on_screen": "",
|
||||
"active": true,
|
||||
"description": "",
|
||||
"show_in_rest": 0,
|
||||
"display_title": "",
|
||||
"acfe_autosync": ["json"],
|
||||
"acfe_form": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_field_name": "GroupLayoutContained",
|
||||
"map_graphql_types_from_location_rules": 0,
|
||||
"graphql_types": "",
|
||||
"acfe_meta": "",
|
||||
"acfe_note": "",
|
||||
"modified": 1768358794
|
||||
}
|
||||
154
wp-content/themes/moonshine/acf-json/group_options_site.json
Normal file
154
wp-content/themes/moonshine/acf-json/group_options_site.json
Normal file
@@ -0,0 +1,154 @@
|
||||
{
|
||||
"key": "group_options_site",
|
||||
"title": "Options - Site",
|
||||
"fields": [
|
||||
{
|
||||
"key": "field_697220310aaaf",
|
||||
"label": "Email",
|
||||
"name": "email",
|
||||
"aria-label": "",
|
||||
"type": "email",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"default_value": "",
|
||||
"allow_in_bindings": 0,
|
||||
"placeholder": "",
|
||||
"prepend": "",
|
||||
"append": "",
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "email",
|
||||
"graphql_non_null": 1
|
||||
},
|
||||
{
|
||||
"key": "field_697cbf414fdd5",
|
||||
"label": "Phone number",
|
||||
"name": "phone_number",
|
||||
"aria-label": "",
|
||||
"type": "phone",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"initial_country": "CA",
|
||||
"return_format": "national",
|
||||
"allow_in_bindings": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "phoneNumber",
|
||||
"graphql_non_null": 1
|
||||
},
|
||||
{
|
||||
"key": "field_697cd4c5fc56a",
|
||||
"label": "Médias sociaux",
|
||||
"name": "social",
|
||||
"aria-label": "",
|
||||
"type": "clone",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"graphql_field_name": "social",
|
||||
"clone": ["group_abstract_social"],
|
||||
"display": "seamless",
|
||||
"layout": "block",
|
||||
"prefix_label": 0,
|
||||
"prefix_name": 0,
|
||||
"acfe_seamless_style": 0,
|
||||
"acfe_clone_modal": 0,
|
||||
"acfe_clone_modal_close": 0,
|
||||
"acfe_clone_modal_button": "",
|
||||
"acfe_clone_modal_size": "large"
|
||||
},
|
||||
{
|
||||
"key": "field_697cc921234cc",
|
||||
"label": "Liens globaux",
|
||||
"name": "links",
|
||||
"aria-label": "",
|
||||
"type": "group",
|
||||
"instructions": "",
|
||||
"required": 0,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"layout": "row",
|
||||
"acfe_seamless_style": 0,
|
||||
"acfe_group_modal": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "links",
|
||||
"graphql_non_null": 0,
|
||||
"sub_fields": [
|
||||
{
|
||||
"key": "field_697cc93e234cd",
|
||||
"label": "Contact",
|
||||
"name": "contact",
|
||||
"aria-label": "",
|
||||
"type": "link",
|
||||
"instructions": "",
|
||||
"required": 1,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"return_format": "array",
|
||||
"allow_in_bindings": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_description": "",
|
||||
"graphql_field_name": "contact",
|
||||
"graphql_non_null": 1
|
||||
}
|
||||
],
|
||||
"acfe_group_modal_close": 0,
|
||||
"acfe_group_modal_button": "",
|
||||
"acfe_group_modal_size": "large"
|
||||
}
|
||||
],
|
||||
"location": [
|
||||
[
|
||||
{
|
||||
"param": "options_page",
|
||||
"operator": "==",
|
||||
"value": "site-options"
|
||||
}
|
||||
]
|
||||
],
|
||||
"menu_order": 0,
|
||||
"position": "normal",
|
||||
"style": "seamless",
|
||||
"label_placement": "top",
|
||||
"instruction_placement": "label",
|
||||
"hide_on_screen": "",
|
||||
"active": true,
|
||||
"description": "",
|
||||
"show_in_rest": 0,
|
||||
"display_title": "",
|
||||
"acfe_autosync": ["json"],
|
||||
"acfe_form": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_field_name": "GroupSiteOptions",
|
||||
"map_graphql_types_from_location_rules": 0,
|
||||
"graphql_types": "",
|
||||
"acfe_meta": "",
|
||||
"acfe_note": "",
|
||||
"modified": 1769788698
|
||||
}
|
||||
60
wp-content/themes/moonshine/acf-json/group_post_page.json
Normal file
60
wp-content/themes/moonshine/acf-json/group_post_page.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"key": "group_post_page",
|
||||
"title": "Post - Page",
|
||||
"fields": [
|
||||
{
|
||||
"key": "field_690cbda0abcbb",
|
||||
"label": "Constructeur de page",
|
||||
"name": "builder",
|
||||
"aria-label": "",
|
||||
"type": "clone",
|
||||
"instructions": "",
|
||||
"required": 0,
|
||||
"conditional_logic": 0,
|
||||
"wrapper": {
|
||||
"width": "",
|
||||
"class": "",
|
||||
"id": ""
|
||||
},
|
||||
"graphql_field_name": "builder",
|
||||
"clone": ["group_abstract_builder"],
|
||||
"display": "seamless",
|
||||
"layout": "block",
|
||||
"prefix_label": 0,
|
||||
"prefix_name": 0,
|
||||
"acfe_seamless_style": 0,
|
||||
"acfe_clone_modal": 0,
|
||||
"acfe_clone_modal_close": 0,
|
||||
"acfe_clone_modal_button": "",
|
||||
"acfe_clone_modal_size": "large"
|
||||
}
|
||||
],
|
||||
"location": [
|
||||
[
|
||||
{
|
||||
"param": "post_type",
|
||||
"operator": "==",
|
||||
"value": "page"
|
||||
}
|
||||
]
|
||||
],
|
||||
"menu_order": 0,
|
||||
"position": "normal",
|
||||
"style": "seamless",
|
||||
"label_placement": "top",
|
||||
"instruction_placement": "label",
|
||||
"hide_on_screen": ["the_content"],
|
||||
"active": true,
|
||||
"description": "",
|
||||
"show_in_rest": 0,
|
||||
"display_title": "",
|
||||
"acfe_autosync": ["json"],
|
||||
"acfe_form": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_field_name": "GroupPostPage",
|
||||
"map_graphql_types_from_location_rules": 0,
|
||||
"graphql_types": "",
|
||||
"acfe_meta": "",
|
||||
"acfe_note": "",
|
||||
"modified": 1768336934
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"key": "ui_options_page_site",
|
||||
"title": "Options du site",
|
||||
"active": true,
|
||||
"menu_order": 0,
|
||||
"page_title": "Options du site",
|
||||
"menu_slug": "site-options",
|
||||
"parent_slug": "options-general.php",
|
||||
"advanced_configuration": 1,
|
||||
"icon_url": "",
|
||||
"menu_title": "",
|
||||
"position": "",
|
||||
"redirect": false,
|
||||
"description": "",
|
||||
"menu_icon": [],
|
||||
"update_button": "Mise à jour",
|
||||
"updated_message": "Options mises à jours",
|
||||
"capability": "edit_posts",
|
||||
"data_storage": "options",
|
||||
"post_id": "",
|
||||
"autoload": 0,
|
||||
"show_in_graphql": 1,
|
||||
"graphql_type_name": "SiteOptions",
|
||||
"modified": 1769693948
|
||||
}
|
||||
@@ -1,9 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { fr } from "@nuxt/ui/locale";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UApp :locale="fr">
|
||||
<NuxtRouteAnnouncer />
|
||||
<NuxtLoadingIndicator />
|
||||
<NuxtLayout>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
</div>
|
||||
</UApp>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
@import "tailwindcss";
|
||||
@import "tailwindcss" theme(static) source("../../..");
|
||||
@import "@nuxt/ui";
|
||||
|
||||
@import "./a11y.css";
|
||||
@import "./containers.css";
|
||||
@import "./links.css";
|
||||
@import "./lists.css";
|
||||
@import "./prose.css";
|
||||
@import "./typography.css";
|
||||
|
||||
@import "./vendors/tinymce.css";
|
||||
|
||||
7
wp-content/themes/moonshine/app/assets/css/a11y.css
Normal file
7
wp-content/themes/moonshine/app/assets/css/a11y.css
Normal file
@@ -0,0 +1,7 @@
|
||||
@utility disabled-default {
|
||||
@apply disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75;
|
||||
}
|
||||
|
||||
@utility focus-default {
|
||||
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2;
|
||||
}
|
||||
@@ -8,13 +8,27 @@
|
||||
}
|
||||
|
||||
/* Container sizes */
|
||||
@utility container { @apply mx-auto px-container max-w-(--breakpoint-2xl); }
|
||||
@utility container-xl { @apply container max-w-(--breakpoint-xl); }
|
||||
@utility container-lg { @apply container max-w-(--breakpoint-lg); }
|
||||
@utility container-md { @apply container max-w-(--breakpoint-md); }
|
||||
@utility container-sm { @apply container max-w-(--breakpoint-sm); }
|
||||
@utility container-fluid { @apply container max-w-screen; }
|
||||
@utility container-none { @apply w-full max-w-screen; }
|
||||
@utility container {
|
||||
@apply mx-auto px-container max-w-(--breakpoint-2xl);
|
||||
}
|
||||
@utility container-xl {
|
||||
@apply container max-w-(--breakpoint-xl);
|
||||
}
|
||||
@utility container-lg {
|
||||
@apply container max-w-(--breakpoint-lg);
|
||||
}
|
||||
@utility container-md {
|
||||
@apply container max-w-(--breakpoint-md);
|
||||
}
|
||||
@utility container-sm {
|
||||
@apply container max-w-(--breakpoint-sm);
|
||||
}
|
||||
@utility container-fluid {
|
||||
@apply container max-w-screen;
|
||||
}
|
||||
@utility container-none {
|
||||
@apply w-full max-w-screen;
|
||||
}
|
||||
|
||||
/* Split containers */
|
||||
:root {
|
||||
@@ -42,6 +56,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
@utility container-left { @apply ml-(--container-outside-margin) px-container;}
|
||||
@utility container-right { @apply mr-(--container-outside-margin) px-container;}
|
||||
@utility container-half { width: calc(var(--container-width) / 2);}
|
||||
@utility container-left {
|
||||
@apply ml-(--container-outside-margin) px-container;
|
||||
}
|
||||
@utility container-right {
|
||||
@apply mr-(--container-outside-margin) px-container;
|
||||
}
|
||||
@utility container-half {
|
||||
width: calc(var(--container-width) / 2);
|
||||
}
|
||||
|
||||
13
wp-content/themes/moonshine/app/assets/css/links.css
Normal file
13
wp-content/themes/moonshine/app/assets/css/links.css
Normal file
@@ -0,0 +1,13 @@
|
||||
/* Variant to target all children links without specific link or button classes */
|
||||
@custom-variant links (& a:not([class*='link-']):not([class*='button-']));
|
||||
|
||||
/* Link styles */
|
||||
@utility link-base {
|
||||
@apply cursor-pointer disabled-default transition;
|
||||
}
|
||||
@utility link-underline {
|
||||
@apply link-base underline hover:decoration-primary;
|
||||
}
|
||||
@utility link-opacity {
|
||||
@apply link-base hover:opacity-80;
|
||||
}
|
||||
3
wp-content/themes/moonshine/app/assets/css/lists.css
Normal file
3
wp-content/themes/moonshine/app/assets/css/lists.css
Normal file
@@ -0,0 +1,3 @@
|
||||
@utility list-horizontal {
|
||||
@apply list-none flex flex-wrap items-center gap-3;
|
||||
}
|
||||
26
wp-content/themes/moonshine/app/assets/css/prose.css
Normal file
26
wp-content/themes/moonshine/app/assets/css/prose.css
Normal file
@@ -0,0 +1,26 @@
|
||||
@utility prose {
|
||||
/* Headings (allow class overrides) */
|
||||
h1:not([class*="heading-"]) {
|
||||
@apply heading-1;
|
||||
}
|
||||
h2:not([class*="heading-"]) {
|
||||
@apply heading-2;
|
||||
}
|
||||
h3:not([class*="heading-"]) {
|
||||
@apply heading-3;
|
||||
}
|
||||
h4:not([class*="heading-"]) {
|
||||
@apply heading-4;
|
||||
}
|
||||
|
||||
/* Links */
|
||||
@apply links:link-underline;
|
||||
|
||||
/* Paragraphs */
|
||||
p:not([class*="paragraph-"]) {
|
||||
@apply paragraph-base;
|
||||
}
|
||||
|
||||
/* Spacing */
|
||||
@apply space-y-2;
|
||||
}
|
||||
24
wp-content/themes/moonshine/app/assets/css/typography.css
Normal file
24
wp-content/themes/moonshine/app/assets/css/typography.css
Normal file
@@ -0,0 +1,24 @@
|
||||
/* Heading styles */
|
||||
@utility heading-base {
|
||||
@apply font-bold tracking-tight;
|
||||
}
|
||||
@utility heading-1 {
|
||||
@apply heading-base text-4xl;
|
||||
}
|
||||
@utility heading-2 {
|
||||
@apply heading-base text-3xl;
|
||||
}
|
||||
@utility heading-3 {
|
||||
@apply heading-base text-2xl;
|
||||
}
|
||||
@utility heading-4 {
|
||||
@apply heading-base text-xl;
|
||||
}
|
||||
|
||||
/* Paragraph styles */
|
||||
@utility paragraph-base {
|
||||
@apply font-sans;
|
||||
}
|
||||
@utility paragraph-lead {
|
||||
@apply paragraph-base text-2xl;
|
||||
}
|
||||
3
wp-content/themes/moonshine/app/assets/css/vendors/tinymce.css
vendored
Normal file
3
wp-content/themes/moonshine/app/assets/css/vendors/tinymce.css
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
body#tinymce {
|
||||
@apply prose;
|
||||
}
|
||||
4
wp-content/themes/moonshine/app/assets/svg/site-logo.svg
Normal file
4
wp-content/themes/moonshine/app/assets/svg/site-logo.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg version="1.1" viewBox="0 0 490.3 86.763" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m10.344 1.5312a10.208 10.208 0 0 0-9.0195 15.207l36.1 64.801a10.2 10.2 0 0 0 13.9 3.9004 10.415 10.415 0 0 0 4-14l-36.201-64.701a10.208 10.208 0 0 0-8.7793-5.207zm221.33 12.51v51.84h11.52v-2.8789a16.277 16.277 0 0 0 11.232 3.959c9.576 0 17.641-7.7004 17.641-19.152 0-11.376-8.0656-19.152-17.641-19.152a16.277 16.277 0 0 0-11.232 3.9609v-18.576h-11.52zm206 0v51.84h11.52v-51.84h-11.52zm-127.3 0.070312v11.145h11.521v-11.145h-11.521zm-21.229 14.535c-8.6942-0.004836-14.866 4.5403-15.109 11.721-0.193 5.685 3.5014 9.4123 10.15 10.863l7.291 1.6875c2.645 0.594 3.5488 1.5612 3.5078 2.7852-0.054 1.583-1.7534 2.8227-4.7754 2.7207-3.094-0.105-5.8618-1.3519-6.2598-4.4629l-11.305 1.9199c0.972 7.453 8.133 10.795 16.625 11.084 9.5 0.322 16.549-3.6186 16.82-11.602 0.181-5.325-2.8478-9.5341-9.6348-11.205l-8.4316-2.0137c-2.286-0.582-2.6824-1.6003-2.6484-2.6113 0.044-1.295 1.0992-2.773 4.1992-2.668 3.526 0.12 5.6164 2.2082 5.9004 4.4512l10.574-1.7363c-1.227-6.309-7.0597-10.613-16.055-10.918-0.28559-0.009687-0.56915-0.015469-0.84961-0.015625zm-79.43 0.009766c-10.512 0-19.152 7.7764-19.152 19.152 0 11.448 8.6401 19.152 19.08 19.152 8.28 0 14.832-3.6728 17.928-11.301l-10.225-2.0879c-1.944 3.528-5.0392 4.1758-7.6992 4.1758-3.888 0-6.8414-2.6624-7.7774-6.9824h26.5v-2.957h-0.00781c-0.216-11.808-8.4225-19.152-18.646-19.152zm140.62 0a13.682 13.682 0 0 0-10.656 4.3926v-3.3125h-11.52v36.145h11.52v-17.711c0-6.048 2.7361-9.1445 6.9121-9.1445 3.456 0 6.1191 2.5912 6.1191 6.6992v20.156h11.521v-17.711c0-6.048 2.8067-9.1445 7.0547-9.1445 3.384 0 6.0488 2.5912 6.0488 6.6992v20.156h11.447v-22.607c0-8.784-6.1202-14.617-13.824-14.617a15.58 15.58 0 0 0-12.814 6.1211c-2.448-3.96-6.7686-6.1211-11.809-6.1211zm66.391 0a16.277 16.277 0 0 0-11.232 3.9609v-2.8809h-11.52v48.385h11.52v-15.119a16.277 16.277 0 0 0 11.232 3.959c9.576 0 17.639-7.7004 17.639-19.152 0-11.376-8.0627-19.152-17.639-19.152zm54.936 0c-10.512 0-19.15 7.7764-19.15 19.152 0 11.448 8.6381 19.152 19.078 19.152 8.28 0 14.834-3.6728 17.93-11.301l-10.225-2.0879c-1.944 3.528-5.0392 4.1758-7.6992 4.1758-3.888 0-6.8414-2.6624-7.7774-6.9824h26.5v-2.957h-0.00781c-0.216-11.808-8.4244-19.152-18.648-19.152zm-336.16 1.0801 11.592 36.217h10.008l6.5527-19.584 6.4805 19.584h10.008l11.576-36.217h-11.301l-5.9004 19.512-6.8398-19.512h-8.1367l-6.8398 19.441-5.8984-19.441h-11.301zm174.88 0v36.145h11.521v-36.145h-11.521zm-100.66 8.2812a7.221 7.221 0 0 1 7.2715 5.6875h-14.9a7.918 7.918 0 0 1 7.6289-5.6875zm261.94 0a7.221 7.221 0 0 1 7.2715 5.6875h-14.9a7.918 7.918 0 0 1 7.6289-5.6875zm-219.6 0.43164c5.04 0 8.7109 3.8154 8.7109 9.3594 0 5.616-3.6709 9.3613-8.7109 9.3613a8.972 8.972 0 0 1-8.8574-9.3613 9.016 9.016 0 0 1 8.8574-9.3594zm162.29 0c5.04 0 8.7129 3.8154 8.7129 9.3594 0 5.616-3.6729 9.3613-8.7129 9.3613a8.972 8.972 0 0 1-8.8555-9.3613 9.016 9.016 0 0 1 8.8555-9.3594z" fill="#212121"/>
|
||||
<path d="m123.02 1.939-.7-.5a9.735 9.735 0 0 0-13.4 3.2l-29.1 47.3a2.253 2.253 0 0 1-3.9-.1l-11.3-20.3a9.82 9.82 0 0 0-13.3-3.8l-.8.4a9.82 9.82 0 0 0-3.8 13.3l21.8 39a9.983 9.983 0 0 0 8.3 5 9.83 9.83 0 0 0 9.1-4.6l40.4-65.6a9.668 9.668 0 0 0-3.3-13.3" fill="#0ad2b7" data-name="Tracé 22516"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,9 @@
|
||||
fragment AcfImage on MediaItem {
|
||||
src: sourceUrl
|
||||
alt: altText
|
||||
mediaDetails {
|
||||
width
|
||||
height
|
||||
}
|
||||
objectPosition
|
||||
}
|
||||
17
wp-content/themes/moonshine/app/components/acf/AcfImage.vue
Normal file
17
wp-content/themes/moonshine/app/components/acf/AcfImage.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
import type { AcfImageFragment } from "#graphql/operations";
|
||||
|
||||
defineProps<{ image?: AcfImageFragment }>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NuxtImg
|
||||
v-if="image"
|
||||
:src="image.src"
|
||||
:alt="image.alt"
|
||||
:width="image.mediaDetails?.width"
|
||||
:height="image.mediaDetails?.height"
|
||||
:style="{ objectPosition: image.objectPosition || 'center' }"
|
||||
placeholder
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,5 @@
|
||||
fragment AcfLink on AcfLink {
|
||||
title
|
||||
url
|
||||
target
|
||||
}
|
||||
23
wp-content/themes/moonshine/app/components/acf/AcfLink.vue
Normal file
23
wp-content/themes/moonshine/app/components/acf/AcfLink.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<script setup lang="ts">
|
||||
import type { AcfLinkFragment } from "#graphql/operations";
|
||||
import type { LinkProps } from "@nuxt/ui";
|
||||
|
||||
type AcfLinkProps = Omit<LinkProps, "to" | "target" | "href"> & {
|
||||
link?: AcfLinkFragment;
|
||||
};
|
||||
|
||||
const { link, ...linkProps } = defineProps<AcfLinkProps>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ULink
|
||||
v-if="link?.url && link?.title"
|
||||
v-bind="linkProps"
|
||||
:to="link.url"
|
||||
:target="link.target"
|
||||
:external="link.target === '_blank'"
|
||||
:rel="link.target === '_blank' ? 'noopener noreferrer' : undefined"
|
||||
>
|
||||
<slot>{{ link.title }}</slot>
|
||||
</ULink>
|
||||
</template>
|
||||
@@ -0,0 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
import type { AcfLinkFragment } from "#graphql/operations";
|
||||
import type { ButtonProps } from "@nuxt/ui";
|
||||
|
||||
type AcfLinkButtonProps = Omit<ButtonProps, "to" | "target" | "href"> & {
|
||||
link?: AcfLinkFragment;
|
||||
showLabel?: boolean;
|
||||
};
|
||||
|
||||
const { link, showLabel, ...buttonProps } = defineProps<AcfLinkButtonProps>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UButton
|
||||
v-if="link?.url && link?.title"
|
||||
v-bind="buttonProps"
|
||||
:to="link.url"
|
||||
:target="link.target"
|
||||
:external="link.target === '_blank'"
|
||||
:rel="link.target === '_blank' ? 'noopener noreferrer' : undefined"
|
||||
>
|
||||
<slot>{{ showLabel ? link.title : "" }}</slot>
|
||||
</UButton>
|
||||
</template>
|
||||
@@ -0,0 +1,9 @@
|
||||
fragment AcfMedia on GroupAbstractMedia_Fields {
|
||||
image {
|
||||
node {
|
||||
...AcfImage
|
||||
}
|
||||
}
|
||||
aspectRatio
|
||||
objectFit
|
||||
}
|
||||
36
wp-content/themes/moonshine/app/components/acf/AcfMedia.vue
Normal file
36
wp-content/themes/moonshine/app/components/acf/AcfMedia.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
import { tv, type VariantProps } from "tailwind-variants";
|
||||
import type { AcfMediaFragment } from "#graphql/operations";
|
||||
|
||||
const tvAcfMedia = tv({
|
||||
slots: {
|
||||
image: "w-full",
|
||||
},
|
||||
variants: {
|
||||
aspectRatio: {
|
||||
square: { image: "aspect-[1/1]" },
|
||||
video: { image: "aspect-video" },
|
||||
portrait: { image: "aspect-[2/3]" },
|
||||
auto: { image: "aspect-auto" },
|
||||
},
|
||||
objectFit: {
|
||||
cover: { image: "object-cover" },
|
||||
contain: { image: "object-contain" },
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
aspectRatio: "auto",
|
||||
objectFit: "cover",
|
||||
},
|
||||
});
|
||||
|
||||
const props = defineProps<{ media?: AcfMediaFragment }>();
|
||||
const classes = tvAcfMedia({
|
||||
aspectRatio: props.media?.aspectRatio,
|
||||
objectFit: props.media?.objectFit,
|
||||
} as VariantProps<typeof tvAcfMedia>);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AcfImage v-if="media?.image?.node" :image="media.image.node" :class="classes.image()" />
|
||||
</template>
|
||||
@@ -0,0 +1,5 @@
|
||||
fragment AcfPhone on AcfPhone {
|
||||
national
|
||||
e164
|
||||
extension
|
||||
}
|
||||
14
wp-content/themes/moonshine/app/components/acf/AcfPhone.vue
Normal file
14
wp-content/themes/moonshine/app/components/acf/AcfPhone.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import type { AcfPhoneFragment } from "#graphql/operations";
|
||||
|
||||
defineProps<{
|
||||
phone?: AcfPhoneFragment;
|
||||
link?: boolean;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Component :is="link ? 'a' : 'span'" v-if="phone" :href="link ? `tel:${phone.e164}` : undefined">
|
||||
{{ phone.national }}{{ phone.extension ? ` ext. ${phone.extension}` : "" }}
|
||||
</Component>
|
||||
</template>
|
||||
@@ -0,0 +1,5 @@
|
||||
fragment AcfSocial on GroupAbstractSocial_Fields {
|
||||
profiles {
|
||||
url
|
||||
}
|
||||
}
|
||||
18
wp-content/themes/moonshine/app/components/acf/AcfSocial.vue
Normal file
18
wp-content/themes/moonshine/app/components/acf/AcfSocial.vue
Normal file
@@ -0,0 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{ social?: AcfSocialOutput }>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="social?.profiles" class="flex gap-1.5">
|
||||
<a
|
||||
v-for="({ url, icon }, key) in social.profiles"
|
||||
:key="key"
|
||||
:href="url"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="flex"
|
||||
>
|
||||
<UIcon :name="icon" />
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,20 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
const { isLoggedIn } = useAuth();
|
||||
const attrs = computed(() => {
|
||||
return isLoggedIn.value
|
||||
? {
|
||||
label: "Déconnexion",
|
||||
icon: "i-lucide-log-out",
|
||||
}
|
||||
: {
|
||||
label: "Connexion",
|
||||
icon: "i-lucide-log-in",
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthState>
|
||||
<UButton to="/connexion" v-bind="attrs" color="neutral" />
|
||||
</AuthState>
|
||||
</template>
|
||||
@@ -7,7 +7,8 @@ const fields = [
|
||||
label: "Courriel",
|
||||
placeholder: "Entrez votre courriel",
|
||||
required: true,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: "password",
|
||||
label: "Mot de passe",
|
||||
type: "password" as const,
|
||||
|
||||
@@ -5,12 +5,8 @@ const { logout } = useAuthConnexion();
|
||||
<template>
|
||||
<div class="w-full space-y-6">
|
||||
<div class="flex flex-col text-center">
|
||||
<div class="text-xl text-pretty font-semibold text-highlighted">
|
||||
Déconnexion
|
||||
</div>
|
||||
<div class="mt-1 text-base text-pretty text-muted">
|
||||
Veuillez confirmer la déconnexion.
|
||||
</div>
|
||||
<div class="text-xl font-semibold text-pretty text-highlighted">Déconnexion</div>
|
||||
<div class="mt-1 text-base text-pretty text-muted">Veuillez confirmer la déconnexion.</div>
|
||||
</div>
|
||||
<UButton
|
||||
icon="i-lucide-log-out"
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
<template>
|
||||
<div class="w-full space-y-6">
|
||||
<div class="flex flex-col text-center">
|
||||
<div class="text-xl text-pretty font-semibold text-highlighted">
|
||||
Redirection en cours
|
||||
</div>
|
||||
<div class="mt-1 text-base text-pretty text-muted">
|
||||
Veuillez patienter...
|
||||
</div>
|
||||
<div class="text-xl font-semibold text-pretty text-highlighted">Redirection en cours</div>
|
||||
<div class="mt-1 text-base text-pretty text-muted">Veuillez patienter...</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fragment BuilderSections on GroupAbstractBuilder_Fields {
|
||||
sections {
|
||||
__typename
|
||||
... on GroupAbstractBuilderSectionsHeroSplitLayout {
|
||||
...SectionHeroSplit
|
||||
}
|
||||
... on GroupAbstractBuilderSectionsTextBlockLayout {
|
||||
...SectionTextBlock
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
import type { BuilderSectionsFragment } from "#graphql/operations";
|
||||
|
||||
const props = defineProps<BuilderSectionsFragment>();
|
||||
const sections = computed(() => {
|
||||
return (props.sections || [])
|
||||
.filter((section) => !!section)
|
||||
.map(({ __typename, ...attrs }) => ({
|
||||
componentName: __typename.replace(/^GroupAbstractBuilderSections(.+?)Layout$/, "Section$1"),
|
||||
attrs,
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="builder-sections">
|
||||
<Component
|
||||
:is="componentName"
|
||||
v-for="({ componentName, attrs }, index) in sections"
|
||||
:key="index"
|
||||
v-bind="attrs"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,5 @@
|
||||
fragment LayoutContained on GroupLayoutContained_Fields {
|
||||
container
|
||||
verticalPadding
|
||||
bgColor
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<script setup lang="ts">
|
||||
import type { LayoutContainedFragment } from "#graphql/operations";
|
||||
import { tv, type VariantProps } from "tailwind-variants";
|
||||
|
||||
const props = defineProps<LayoutContainedFragment>();
|
||||
|
||||
const layoutWrapperVariants = tv({
|
||||
slots: {
|
||||
base: "",
|
||||
inner: "",
|
||||
},
|
||||
variants: {
|
||||
container: {
|
||||
default: { inner: "container" },
|
||||
lg: { inner: "container-lg" },
|
||||
xl: { inner: "container-xl" },
|
||||
fluid: { inner: "container-fluid" },
|
||||
none: { inner: "container-none" },
|
||||
},
|
||||
verticalPadding: {
|
||||
sm: { base: "py-3" },
|
||||
md: { base: "py-6" },
|
||||
lg: { base: "py-12" },
|
||||
},
|
||||
bgColor: {
|
||||
default: { base: "bg-default" },
|
||||
muted: { base: "bg-muted" },
|
||||
inverted: { base: "bg-inverted text-inverted" },
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
container: "default",
|
||||
verticalPadding: "md",
|
||||
bgColor: "default",
|
||||
},
|
||||
});
|
||||
const { base, inner } = layoutWrapperVariants({
|
||||
container: props.container[0],
|
||||
verticalPadding: props.verticalPadding[0],
|
||||
bgColor: props.bgColor[0],
|
||||
} as VariantProps<typeof layoutWrapperVariants>);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section :class="base()">
|
||||
<div :class="inner()">
|
||||
<slot />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -0,0 +1,7 @@
|
||||
fragment NodePage on Page {
|
||||
title
|
||||
isFrontPage
|
||||
groupPostPage {
|
||||
...BuilderSections
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import type { NodePageFragment } from "#graphql/operations";
|
||||
|
||||
defineProps<NodePageFragment>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="node-page">
|
||||
<h1 v-if="!isFrontPage" class="text-4xl font-bold">
|
||||
{{ title }}
|
||||
</h1>
|
||||
<BuilderSections :sections="groupPostPage?.sections || []" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,5 @@
|
||||
fragment SectionHeroSplit on GroupAbstractBuilderSectionsHeroSplitLayout {
|
||||
content
|
||||
reverse
|
||||
...AcfMedia
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<script setup lang="ts">
|
||||
import { tv, type VariantProps } from "tailwind-variants";
|
||||
import type { SectionHeroSplitFragment } from "#graphql/operations";
|
||||
|
||||
const tvSectionHeroSplit = tv({
|
||||
slots: {
|
||||
base: "py-6",
|
||||
container: "container flex flex-col items-center gap-6",
|
||||
content: "flex-1",
|
||||
media: "w-full basis-1/2",
|
||||
},
|
||||
variants: {
|
||||
reverse: {
|
||||
false: {
|
||||
container: "lg:flex-row",
|
||||
},
|
||||
true: {
|
||||
container: "lg:flex-row-reverse",
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
reverse: false,
|
||||
},
|
||||
});
|
||||
|
||||
const props = defineProps<SectionHeroSplitFragment>();
|
||||
const classes = tvSectionHeroSplit({
|
||||
reverse: props.reverse,
|
||||
} as VariantProps<typeof tvSectionHeroSplit>);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section :class="classes.base()">
|
||||
<div :class="classes.container()">
|
||||
<UiProse :content="content" :class="classes.content()" />
|
||||
<AcfMedia :media="parseAcfMedia(props)" :class="classes.media()" />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -0,0 +1,6 @@
|
||||
fragment SectionTextBlock on GroupAbstractBuilderSectionsTextBlockLayout {
|
||||
content
|
||||
layoutSettings {
|
||||
...LayoutContained
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import type { SectionTextBlockFragment } from "#graphql/operations";
|
||||
|
||||
defineProps<SectionTextBlockFragment>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<LayoutContained data-section-type="text-block" v-bind="layoutSettings!">
|
||||
<UiProse :content="content" />
|
||||
</LayoutContained>
|
||||
</template>
|
||||
@@ -1,13 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
const { data: siteOptions } = await useSiteOptions();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UFooter id="site-footer">
|
||||
<template #left>
|
||||
<SiteFooterCopyright />
|
||||
</template>
|
||||
<template #right>
|
||||
<SiteFooterCredits />
|
||||
</template>
|
||||
</UFooter>
|
||||
<footer class="links:link-prose bg-accented">
|
||||
<div class="container py-6">
|
||||
<AcfSocial :social="parseAcfSocial(siteOptions)" />
|
||||
</div>
|
||||
<SiteFooterBottom />
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
const { connexionButton } = useAuthConnexion();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-inverted py-1.5 text-inverted">
|
||||
<div class="container flex flex-col items-center gap-3 sm:flex-row">
|
||||
<SiteFooterCopyright class="sm:mr-auto" />
|
||||
<UButton v-bind="connexionButton" color="neutral" variant="link" />
|
||||
<SiteFooterCredits />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,10 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
const { data } = await useGraphQLQuery("GeneralSettings", undefined, { cache: { ttl: 0 } });
|
||||
const { data: generalSettings } = await useGeneralSettings();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
© {{ new Date().getFullYear() }}
|
||||
<span v-if="data.generalSettings?.title">{{ data.generalSettings.title }}</span>
|
||||
<span v-if="generalSettings?.title">{{ generalSettings.title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
<template>
|
||||
<div class="flex items-center gap-1">
|
||||
Fait avec <UIcon name="i-lucide-heart" /> par
|
||||
<ULink href="https://websimple.com" target="_blank" external title="Site web développé par Websimple">Websimple</ULink>
|
||||
<ULink
|
||||
href="https://websimple.com"
|
||||
target="_blank"
|
||||
external
|
||||
title="Site web développé par Websimple"
|
||||
>Websimple</ULink
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
const title = "Moonshine";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UHeader :title="title">
|
||||
<template #right>
|
||||
<AuthConnexionButton />
|
||||
<UHeader mode="slideover">
|
||||
<template #left>
|
||||
<NuxtLink to="/">
|
||||
<SvgSiteLogo class="h-12 w-auto" />
|
||||
</NuxtLink>
|
||||
</template>
|
||||
</UHeader>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{ content: string }>();
|
||||
const refContent = useTemplateRef("refContent");
|
||||
useProseLinks(refContent);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="refContent" class="prose" v-html="content" />
|
||||
</template>
|
||||
@@ -2,5 +2,6 @@ export function useAuth() {
|
||||
const { loggedIn: isLoggedIn, session } = useUserSession();
|
||||
const hasRole = (role: string) => session.value?.user?.roles?.includes(role) || false;
|
||||
const isAdmin = computed(() => hasRole("administrator"));
|
||||
|
||||
return { isLoggedIn, hasRole, isAdmin };
|
||||
}
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
import z from "zod";
|
||||
import type { FormSubmitEvent } from "@nuxt/ui";
|
||||
|
||||
export const authLoginFormSchema = z.object({
|
||||
username: z.email("Courriel invalide"),
|
||||
password: z.string("Veuillez saisir votre mot de passe"),
|
||||
});
|
||||
|
||||
export type AuthLoginForm = z.infer<typeof authLoginFormSchema>;
|
||||
|
||||
const isRedirecting = ref(false);
|
||||
|
||||
export function useAuthConnexion() {
|
||||
const { isLoggedIn } = useAuth();
|
||||
const toast = useToast();
|
||||
const { fetch: refreshUserSession } = useUserSession();
|
||||
const routeRedirect = useRoute().query.redirect as string || undefined;
|
||||
const routeRedirect = (useRoute().query.redirect as string) || undefined;
|
||||
|
||||
// Helper: Redirect after login / logout
|
||||
async function redirectTo(to: string | undefined) {
|
||||
@@ -20,21 +14,31 @@ export function useAuthConnexion() {
|
||||
await delay(1000);
|
||||
await refreshUserSession();
|
||||
await navigateTo(to || routeRedirect || "/");
|
||||
isRedirecting.value = false;
|
||||
}
|
||||
|
||||
// Login
|
||||
const { mutate: loginMutate } = useGraphQLMutation("AuthLogin");
|
||||
async function login({ data: variables }: FormSubmitEvent<AuthLoginForm>, redirect?: string) {
|
||||
async function login({ data: body }: FormSubmitEvent<AuthLoginForm>, redirect?: string) {
|
||||
try {
|
||||
const { data } = await loginMutate(variables);
|
||||
if (!data.login) {
|
||||
throw new Error(`Échec de la connexion par mot de passe.`);
|
||||
const { success, message } = await $fetch("/api/login", { method: "POST", body });
|
||||
if (!success) {
|
||||
throw new Error(message);
|
||||
}
|
||||
toast.add({
|
||||
title: "Connexion réussie",
|
||||
color: "success",
|
||||
description: message,
|
||||
duration: 3000,
|
||||
});
|
||||
await redirectTo(redirect);
|
||||
}
|
||||
catch (error) {
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.add({
|
||||
title: "Erreur de connexion",
|
||||
color: "error",
|
||||
description:
|
||||
error instanceof Error ? error.message : "Une erreur est survenue lors de la connexion.",
|
||||
duration: 5000,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,12 +49,33 @@ export function useAuthConnexion() {
|
||||
if (!result.success) {
|
||||
throw new Error("Échec de la déconnexion.");
|
||||
}
|
||||
toast.add({
|
||||
title: "Déconnexion réussie",
|
||||
color: "success",
|
||||
description: "Vous avez été déconnecté avec succès.",
|
||||
duration: 3000,
|
||||
});
|
||||
await redirectTo(redirect);
|
||||
}
|
||||
catch (error) {
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
toast.add({
|
||||
title: "Erreur de déconnexion",
|
||||
color: "error",
|
||||
description:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Une erreur est survenue lors de la déconnexion.",
|
||||
duration: 5000,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { isRedirecting, login, logout };
|
||||
// Dynamic connexion link
|
||||
const connexionButton = computed(() => ({
|
||||
label: isLoggedIn.value ? "Déconnexion" : "Connexion",
|
||||
icon: isLoggedIn.value ? "i-lucide-log-out" : "i-lucide-log-in",
|
||||
to: "/connexion",
|
||||
}));
|
||||
|
||||
return { isRedirecting, login, logout, connexionButton };
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export const useGeneralSettings = () =>
|
||||
useAsyncGraphQLQuery(
|
||||
"GeneralSettings",
|
||||
{},
|
||||
{
|
||||
transform: ({ generalSettings }) => generalSettings,
|
||||
},
|
||||
);
|
||||
20
wp-content/themes/moonshine/app/composables/useNodeSeo.ts
Normal file
20
wp-content/themes/moonshine/app/composables/useNodeSeo.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { NodeByUriQueryResult, NodeSeoFragment } from "#graphql/operations";
|
||||
|
||||
export function useNodeSeo(node: NodeByUriQueryResult["nodeByUri"]) {
|
||||
// Check if node has SEO data
|
||||
if (!node || !("seo" in node) || !node.seo) {
|
||||
return;
|
||||
}
|
||||
const { seo } = node as NodeSeoFragment;
|
||||
|
||||
useSeoMeta({
|
||||
title: seo?.title || undefined,
|
||||
description: seo?.description || undefined,
|
||||
robots: (seo?.robots || []).join(", "),
|
||||
ogTitle: seo?.openGraph?.title || undefined,
|
||||
ogDescription: seo?.openGraph?.description || undefined,
|
||||
ogImage: seo?.openGraph?.image?.url || undefined,
|
||||
ogUrl: seo?.canonicalUrl || undefined,
|
||||
twitterCard: "summary_large_image",
|
||||
});
|
||||
}
|
||||
70
wp-content/themes/moonshine/app/composables/useProseLinks.ts
Normal file
70
wp-content/themes/moonshine/app/composables/useProseLinks.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
export function useProseLinks(refContent: Ref<HTMLElement | null>) {
|
||||
const router = useRouter();
|
||||
const { url } = useSiteConfig();
|
||||
const siteUrl = new URL(url);
|
||||
|
||||
// Determine if the href is internal
|
||||
const isInternal = (href: string) => {
|
||||
if (!href) return false;
|
||||
if (href.startsWith("/")) return true;
|
||||
if (href.startsWith("#")) return false;
|
||||
try {
|
||||
const hrefUrl = new URL(href);
|
||||
return hrefUrl.hostname === siteUrl.hostname;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Convert href to relative path
|
||||
const convertToRelative = (href: string) => {
|
||||
if (href.startsWith("/")) return href;
|
||||
try {
|
||||
const hrefUrl = new URL(href);
|
||||
if (hrefUrl.hostname === siteUrl.hostname) {
|
||||
return hrefUrl.pathname + hrefUrl.search + hrefUrl.hash;
|
||||
}
|
||||
} catch {
|
||||
// Invalid URL
|
||||
}
|
||||
return href;
|
||||
};
|
||||
|
||||
// Highjack click events to use router for internal links
|
||||
const handleClick = (e: MouseEvent) => {
|
||||
const target = e.target as HTMLElement;
|
||||
const link = target.closest("a");
|
||||
if (!link) return;
|
||||
const href = link.getAttribute("href");
|
||||
if (!href) return;
|
||||
if (
|
||||
e.metaKey ||
|
||||
e.ctrlKey ||
|
||||
e.shiftKey ||
|
||||
e.altKey ||
|
||||
link.target === "_blank" ||
|
||||
link.hasAttribute("download")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (isInternal(href)) {
|
||||
e.preventDefault();
|
||||
const path = convertToRelative(href);
|
||||
router.push(path);
|
||||
}
|
||||
};
|
||||
|
||||
// Attach and detach event listeners
|
||||
onMounted(() => {
|
||||
const element = unref(refContent);
|
||||
if (element) {
|
||||
element.addEventListener("click", handleClick);
|
||||
}
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
const element = unref(refContent);
|
||||
if (element) {
|
||||
element.removeEventListener("click", handleClick);
|
||||
}
|
||||
});
|
||||
}
|
||||
11
wp-content/themes/moonshine/app/composables/useReponsive.ts
Normal file
11
wp-content/themes/moonshine/app/composables/useReponsive.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { breakpointsTailwind, useBreakpoints } from "@vueuse/core";
|
||||
|
||||
export function useResponsive() {
|
||||
const { isMobileOrTablet } = useDevice();
|
||||
const breakpoints = useBreakpoints(breakpointsTailwind, {
|
||||
ssrWidth: isMobileOrTablet ? 375 : 1024,
|
||||
});
|
||||
const isDesktop = breakpoints.greaterOrEqual("lg");
|
||||
|
||||
return { breakpoints, isDesktop };
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export const useSiteOptions = () =>
|
||||
useAsyncGraphQLQuery(
|
||||
"SiteOptions",
|
||||
{},
|
||||
{
|
||||
transform: ({ siteOptions }) => siteOptions?.groupSiteOptions,
|
||||
},
|
||||
);
|
||||
@@ -1,6 +1,10 @@
|
||||
query GeneralSettings {
|
||||
generalSettings {
|
||||
fragment GeneralSettings on GeneralSettings {
|
||||
title
|
||||
description
|
||||
}
|
||||
|
||||
query GeneralSettings {
|
||||
generalSettings {
|
||||
...GeneralSettings
|
||||
}
|
||||
}
|
||||
|
||||
27
wp-content/themes/moonshine/app/graphql/NodebyUri.query.gql
Normal file
27
wp-content/themes/moonshine/app/graphql/NodebyUri.query.gql
Normal file
@@ -0,0 +1,27 @@
|
||||
fragment NodeSeo on NodeWithRankMathSeo {
|
||||
seo {
|
||||
title
|
||||
description
|
||||
robots
|
||||
canonicalUrl
|
||||
openGraph {
|
||||
title
|
||||
description
|
||||
image {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query NodeByUri($uri: String!) {
|
||||
nodeByUri(uri: $uri) {
|
||||
__typename
|
||||
... on Page {
|
||||
...NodePage
|
||||
}
|
||||
... on NodeWithRankMathSeo {
|
||||
...NodeSeo
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fragment SiteOptions on GroupSiteOptions {
|
||||
email
|
||||
phoneNumber {
|
||||
...AcfPhone
|
||||
}
|
||||
...AcfSocial
|
||||
links {
|
||||
contact {
|
||||
...AcfLink
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query SiteOptions {
|
||||
siteOptions {
|
||||
groupSiteOptions {
|
||||
...SiteOptions
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { fr } from "@nuxt/ui/locale";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UApp id="layout-default" :locale="fr">
|
||||
<div id="layout-default">
|
||||
<SiteHeader />
|
||||
<UMain>
|
||||
<slot />
|
||||
</UMain>
|
||||
<SiteFooter />
|
||||
</UApp>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
// Fetch node by URI and handle query errors
|
||||
const { path: uri } = useRoute();
|
||||
const { data, error } = await useAsyncGraphQLQuery("NodeByUri", { uri });
|
||||
if (!data.value?.nodeByUri) {
|
||||
console.error("NodeByUri query error:", error.value);
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
message: `La page demandée est introuvable: ${uri}`,
|
||||
fatal: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Dynamically resolve component based on node type
|
||||
const componentName = `Node${data.value.nodeByUri.__typename}`;
|
||||
if (!useNuxtApp().vueApp.component(componentName)) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
message: `La page demandée ne peut pas être affichée correctement: ${componentName}`,
|
||||
fatal: true,
|
||||
});
|
||||
}
|
||||
|
||||
useNodeSeo(data.value.nodeByUri);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="page-node-from-uri" />
|
||||
<div v-if="data?.nodeByUri" id="page-node-from-uri">
|
||||
<Component :is="componentName" v-bind="data.nodeByUri" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
const { isRedirecting } = useAuthConnexion();
|
||||
onBeforeMount(() => {
|
||||
isRedirecting.value = false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
17
wp-content/themes/moonshine/app/utils/acf-link.ts
Normal file
17
wp-content/themes/moonshine/app/utils/acf-link.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { AcfLinkFragment } from "#graphql/operations";
|
||||
import * as z from "zod";
|
||||
|
||||
const acfLinkSchema = z.object({
|
||||
title: z.string(),
|
||||
url: z.string(),
|
||||
target: z.string().optional().default(""),
|
||||
});
|
||||
export type AcfLinkOutput = z.infer<typeof acfLinkSchema>;
|
||||
|
||||
export function parseAcfLink(data?: Partial<AcfLinkFragment>) {
|
||||
try {
|
||||
return acfLinkSchema.parse(data);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
28
wp-content/themes/moonshine/app/utils/acf-media.ts
Normal file
28
wp-content/themes/moonshine/app/utils/acf-media.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import type { AcfMediaFragment } from "#graphql/operations";
|
||||
import * as z from "zod";
|
||||
|
||||
export const acfImageSchema = z.object({
|
||||
src: z.url(),
|
||||
alt: z.string(),
|
||||
mediaDetails: z.object({
|
||||
width: z.number(),
|
||||
height: z.number(),
|
||||
}),
|
||||
objectPosition: z.string().optional().default("center"),
|
||||
});
|
||||
|
||||
export const acfMediaSchema = z.object({
|
||||
image: z.object({
|
||||
node: acfImageSchema,
|
||||
}),
|
||||
aspectRatio: z.enum(["square", "video", "portrait", "auto"]).optional().default("auto"),
|
||||
objectFit: z.enum(["cover", "contain"]).optional().default("cover"),
|
||||
});
|
||||
|
||||
export function parseAcfMedia(data?: Partial<AcfMediaFragment>) {
|
||||
try {
|
||||
return acfMediaSchema.parse(data);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
33
wp-content/themes/moonshine/app/utils/acf-social.ts
Normal file
33
wp-content/themes/moonshine/app/utils/acf-social.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { AcfSocialFragment } from "#graphql/operations";
|
||||
import * as z from "zod";
|
||||
|
||||
const socialProfile = z
|
||||
.object({ url: z.url() })
|
||||
.transform(({ url }) => ({ url, icon: getSocialIcon(url) }));
|
||||
const acfSocialSchema = z.object({
|
||||
profiles: z.array(socialProfile),
|
||||
});
|
||||
export type AcfSocialOutput = z.infer<typeof acfSocialSchema>;
|
||||
|
||||
export function parseAcfSocial(data?: AcfSocialFragment) {
|
||||
try {
|
||||
return acfSocialSchema.parse(data);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const socialIconMap = {
|
||||
"facebook.com": "i-cib-facebook-f",
|
||||
"twitter.com": "i-cib-twitter",
|
||||
"x.com": "i-cib-twitter",
|
||||
"instagram.com": "i-cib-instagram",
|
||||
"youtube.com": "i-cib-youtube",
|
||||
"linkedin.com": "i-cib-linkedin",
|
||||
"tiktok.com": "i-cib-tiktok",
|
||||
};
|
||||
|
||||
function getSocialIcon(url: string): string {
|
||||
const domain = new URL(url).hostname.toLowerCase().replace(/^www\./, "");
|
||||
return socialIconMap[domain as keyof typeof socialIconMap] ?? "i-lucide-globe";
|
||||
}
|
||||
2150
wp-content/themes/moonshine/editor-style.css
Normal file
2150
wp-content/themes/moonshine/editor-style.css
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,8 +0,0 @@
|
||||
// @ts-check
|
||||
import withNuxt from "./.nuxt/eslint.config.mjs";
|
||||
|
||||
export default withNuxt({ rules: {
|
||||
"vue/max-attributes-per-line": "off",
|
||||
"vue/no-v-html": "off",
|
||||
} },
|
||||
);
|
||||
@@ -2,3 +2,13 @@
|
||||
|
||||
// Core
|
||||
require_once __DIR__ . '/includes/core/theme-setup.php';
|
||||
|
||||
// Vendors
|
||||
require_once __DIR__ . '/includes/vendors/acf.php';
|
||||
require_once __DIR__ . '/includes/vendors/rankmath.php';
|
||||
require_once __DIR__ . '/includes/vendors/tinymce.php';
|
||||
require_once __DIR__ . '/includes/vendors/wpgraphql.php';
|
||||
|
||||
// WPGraphQL
|
||||
require_once __DIR__ . '/includes/wpgraphql/media-focus-point.php';
|
||||
require_once __DIR__ . '/includes/wpgraphql/term-connection.php';
|
||||
|
||||
@@ -16,3 +16,12 @@ function moonshine_after_setup_theme() {
|
||||
|
||||
// Register sidebars
|
||||
}
|
||||
|
||||
// Display theme version in admin footer
|
||||
add_filter( 'update_footer', 'moonshine_update_footer', 100 );
|
||||
function moonshine_update_footer() {
|
||||
$package_json = json_decode( file_get_contents( get_theme_file_path( 'package.json' ) ), true );
|
||||
$name = $package_json['name'] ?? 'moonshine';
|
||||
$version = $package_json['version'] ?? '(unknown)';
|
||||
return sprintf( '%s v%s', esc_html( $name ), esc_html( $version ) );
|
||||
}
|
||||
|
||||
15
wp-content/themes/moonshine/includes/vendors/acf.php
vendored
Normal file
15
wp-content/themes/moonshine/includes/vendors/acf.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
// Disable ACF / ACFE modules
|
||||
add_filter( 'acf/settings/enable_post_types', '__return_false' );
|
||||
add_action( 'acf/init', 'moonshine_acf_init' );
|
||||
function moonshine_acf_init() {
|
||||
acf_update_setting( 'acfe/modules/block_types', false );
|
||||
acf_update_setting( 'acfe/modules/categories', false );
|
||||
acf_update_setting( 'acfe/modules/forms', false );
|
||||
acf_update_setting( 'acfe/modules/options', false );
|
||||
acf_update_setting( 'acfe/modules/options_pages', false );
|
||||
acf_update_setting( 'acfe/modules/post_types', false );
|
||||
acf_update_setting( 'acfe/modules/taxonomies', false );
|
||||
acf_update_setting( 'acfe/modules/templates', false );
|
||||
}
|
||||
1
wp-content/themes/moonshine/includes/vendors/rankmath.php
vendored
Normal file
1
wp-content/themes/moonshine/includes/vendors/rankmath.php
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<?php
|
||||
139
wp-content/themes/moonshine/includes/vendors/tinymce.php
vendored
Normal file
139
wp-content/themes/moonshine/includes/vendors/tinymce.php
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
// Enable formats (styleselect) in TinyMCE
|
||||
add_filter( 'mce_buttons', 'moonshine_tinymce_styleselect' );
|
||||
function moonshine_tinymce_styleselect( $buttons ) {
|
||||
array_unshift( $buttons, 'styleselect' );
|
||||
return $buttons;
|
||||
}
|
||||
|
||||
// Configure TinyMCE
|
||||
add_filter( 'tiny_mce_before_init', 'moonshine_tiny_mce_before_init' );
|
||||
function moonshine_tiny_mce_before_init( $settings ) {
|
||||
// Reset TinyMCE editor CSS
|
||||
if ( isset( $settings['content_css'] ) ) {
|
||||
$content_css = explode( ',', $settings['content_css'] );
|
||||
unset( $content_css[1] ); // wp-content.min.css
|
||||
$settings['content_css'] = implode( ',', $content_css );
|
||||
}
|
||||
|
||||
// Format styles
|
||||
$settings['style_formats'] = wp_json_encode(
|
||||
array(
|
||||
array(
|
||||
'title' => __( "Link styles", 'moonshine' ),
|
||||
'items' => array(// Link styles
|
||||
array(
|
||||
'title' => "Lien (opacité)",
|
||||
'selector' => 'a',
|
||||
'classes' => 'link-opacity',
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'title' => __( "Inline styles", 'moonshine' ),
|
||||
'items' => array(// Inline styles
|
||||
array(
|
||||
'title' => __( "Semi-bold", 'moonshine' ),
|
||||
'inline' => 'span',
|
||||
'classes' => 'font-semibold',
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'title' => __( "Paragraph styles", 'moonshine' ),
|
||||
'items' => array(// Paragraph styles
|
||||
array(
|
||||
'title' => "Paragraphe vedette",
|
||||
'block' => 'p',
|
||||
'classes' => 'paragraph-lead',
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'title' => __( "List styles", 'moonshine' ),
|
||||
'items' => array(// List styles
|
||||
array(
|
||||
'title' => "Liste horizontale",
|
||||
'selector' => 'ul,ol',
|
||||
'classes' => 'list-horizontal',
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'title' => __( "Heading styles", 'moonshine' ),
|
||||
'items' => array(// Heading styles
|
||||
array(
|
||||
'title' => "Titre 1",
|
||||
'selector' => 'h1,h2,h3,h4',
|
||||
'classes' => 'heading-1',
|
||||
),
|
||||
array(
|
||||
'title' => "Titre 2",
|
||||
'selector' => 'h1,h2,h3,h4',
|
||||
'classes' => 'heading-2',
|
||||
),
|
||||
array(
|
||||
'title' => "Titre 3",
|
||||
'selector' => 'h1,h2,h3,h4',
|
||||
'classes' => 'heading-3',
|
||||
),
|
||||
array(
|
||||
'title' => "Titre 4",
|
||||
'selector' => 'h1,h2,h3,h4',
|
||||
'classes' => 'heading-4',
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// Block styles
|
||||
$settings['block_formats'] = implode(
|
||||
';',
|
||||
array(
|
||||
'Paragraph=p',
|
||||
'Heading 1=h1',
|
||||
'Heading 2=h2',
|
||||
'Heading 3=h3',
|
||||
'Heading 4=h4',
|
||||
)
|
||||
);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
// Override TinyMCE editor styles
|
||||
add_filter( 'mce_css', 'moonshine_override_editor_styles' );
|
||||
function moonshine_override_editor_styles() {
|
||||
return get_stylesheet_directory_uri() . '/editor-style.css';
|
||||
}
|
||||
|
||||
// Remove default TinyMCE styles for all editors (WordPress & ACF)
|
||||
add_action( 'admin_print_footer_scripts', 'moonshine_remove_tinymce_default_styles', 99 );
|
||||
function moonshine_remove_tinymce_default_styles() {
|
||||
?>
|
||||
<script>
|
||||
(function($) {
|
||||
if (typeof tinymce !== 'undefined') {
|
||||
tinymce.on('AddEditor', function({editor}) {
|
||||
editor.on('init', function() {
|
||||
$(editor.iframeElement).contents().find("link[href*='content.min.css']").remove();
|
||||
});
|
||||
});
|
||||
}
|
||||
})(jQuery);
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
// Convert absolute URLs to relative in link query
|
||||
add_filter( 'wp_link_query', 'moonshine_tinymce_relative_urls' );
|
||||
function moonshine_tinymce_relative_urls( $results ) {
|
||||
foreach ( $results as &$result ) {
|
||||
if ( empty( $result['permalink'] ) ) {
|
||||
continue;
|
||||
}
|
||||
$result['permalink'] = str_replace( get_home_url(), '', $result['permalink'] );
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
17
wp-content/themes/moonshine/includes/vendors/wpgraphql.php
vendored
Normal file
17
wp-content/themes/moonshine/includes/vendors/wpgraphql.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
// Default WPGraphQL settings
|
||||
add_filter( 'graphql_get_setting_section_field_value', 'moonshine_wpgraphql_settings', 10, 5 );
|
||||
function moonshine_wpgraphql_settings( $value, $default_value, $option_name, $section_fields, $section_name ) {
|
||||
if ( $section_name === 'graphql_general_settings' ) {
|
||||
switch ( $option_name ) {
|
||||
case 'graphql_endpoint':
|
||||
$value = 'graphql';
|
||||
break;
|
||||
case "public_introspection_enabled":
|
||||
$value = "on";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
// Expose 'bg_pos_desktop' post meta on MediaItem type in WPGraphQL
|
||||
add_action( 'graphql_register_types', 'leblanc_graphql_register_media_focus_point' );
|
||||
function leblanc_graphql_register_media_focus_point() {
|
||||
register_graphql_field(
|
||||
'MediaItem',
|
||||
'objectPosition',
|
||||
array(
|
||||
'type' => 'String',
|
||||
'description' => 'CSS object-position value from Media Focus Point plugin',
|
||||
'resolve' => static function ( $media_item ) {
|
||||
return get_post_meta( $media_item->databaseId, 'bg_pos_desktop', true );
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
// Override term connection query args
|
||||
add_filter( 'graphql_term_object_connection_query_args', 'moonshine_graphql_term_object_connection_query_args', 10, 3 );
|
||||
function moonshine_graphql_term_object_connection_query_args( $query_args, $source, $args ) {
|
||||
// Sort by 'order' meta value instead of legacy 'term_order' field
|
||||
if ( 'term_order' === $args['where']['orderby'] ?? false ) {
|
||||
$query_args['meta_key'] = 'order';
|
||||
$query_args['orderby'] = 'meta_value_num';
|
||||
}
|
||||
|
||||
return $query_args;
|
||||
}
|
||||
@@ -3,7 +3,7 @@ return array(
|
||||
'project-id-version' => 'Moonshine',
|
||||
'report-msgid-bugs-to' => '',
|
||||
'pot-creation-date' => '2026-01-13 15:52+0000',
|
||||
'po-revision-date' => '2026-01-13 15:53+0000',
|
||||
'po-revision-date' => '2026-01-29 02:55+0000',
|
||||
'last-translator' => '',
|
||||
'language-team' => 'Français du Canada',
|
||||
'language' => 'fr_CA',
|
||||
@@ -15,10 +15,15 @@ return array(
|
||||
'x-loco-version' => '2.8.1; wp-6.9; php-8.3.27',
|
||||
'x-domain' => 'moonshine',
|
||||
'messages' => array(
|
||||
'Heading styles' => 'Styles de titres',
|
||||
'Headless WordPress theme based on Nuxt.' => 'Thème Wordpress headless basé sur Nuxt.',
|
||||
'https://websimple.com/' => 'https://websimple.com/',
|
||||
'Inline styles' => 'Styles de caractères',
|
||||
'Link styles' => 'Styles de liens',
|
||||
'Main menu' => 'Menu principal',
|
||||
'Moonshine' => 'Moonshine',
|
||||
'Paragraph styles' => 'Styles de paragraphes',
|
||||
'Pascal Martineau ' => 'Pascal Martineau ',
|
||||
'Semi-bold' => 'Semi-gras',
|
||||
),
|
||||
);
|
||||
|
||||
Binary file not shown.
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: Moonshine\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-13 15:52+0000\n"
|
||||
"PO-Revision-Date: 2026-01-13 15:53+0000\n"
|
||||
"PO-Revision-Date: 2026-01-29 02:55+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Français du Canada\n"
|
||||
"Language: fr_CA\n"
|
||||
@@ -15,6 +15,10 @@ msgstr ""
|
||||
"X-Loco-Version: 2.8.1; wp-6.9; php-8.3.27\n"
|
||||
"X-Domain: moonshine"
|
||||
|
||||
#: includes/vendors/tinymce.php:54
|
||||
msgid "Heading styles"
|
||||
msgstr "Styles de titres"
|
||||
|
||||
#. Description of the theme
|
||||
msgid "Headless WordPress theme based on Nuxt."
|
||||
msgstr "Thème Wordpress headless basé sur Nuxt."
|
||||
@@ -23,6 +27,14 @@ msgstr "Thème Wordpress headless basé sur Nuxt."
|
||||
msgid "https://websimple.com/"
|
||||
msgstr "https://websimple.com/"
|
||||
|
||||
#: includes/vendors/tinymce.php:34
|
||||
msgid "Inline styles"
|
||||
msgstr "Styles de caractères"
|
||||
|
||||
#: includes/vendors/tinymce.php:24
|
||||
msgid "Link styles"
|
||||
msgstr "Styles de liens"
|
||||
|
||||
#: includes/core/theme-setup.php:15
|
||||
msgid "Main menu"
|
||||
msgstr "Menu principal"
|
||||
@@ -31,6 +43,14 @@ msgstr "Menu principal"
|
||||
msgid "Moonshine"
|
||||
msgstr "Moonshine"
|
||||
|
||||
#: includes/vendors/tinymce.php:44
|
||||
msgid "Paragraph styles"
|
||||
msgstr "Styles de paragraphes"
|
||||
|
||||
#. Author of the theme
|
||||
msgid "Pascal Martineau "
|
||||
msgstr "Pascal Martineau "
|
||||
|
||||
#: includes/vendors/tinymce.php:37
|
||||
msgid "Semi-bold"
|
||||
msgstr "Semi-gras"
|
||||
|
||||
@@ -3,7 +3,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Moonshine\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-13 15:52+0000\n"
|
||||
"POT-Creation-Date: 2026-01-29 02:55+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: \n"
|
||||
@@ -16,6 +16,10 @@ msgstr ""
|
||||
"X-Loco-Version: 2.8.1; wp-6.9; php-8.3.27\n"
|
||||
"X-Domain: moonshine"
|
||||
|
||||
#: includes/vendors/tinymce.php:54
|
||||
msgid "Heading styles"
|
||||
msgstr ""
|
||||
|
||||
#. Description of the theme
|
||||
msgid "Headless WordPress theme based on Nuxt."
|
||||
msgstr ""
|
||||
@@ -24,6 +28,14 @@ msgstr ""
|
||||
msgid "https://websimple.com/"
|
||||
msgstr ""
|
||||
|
||||
#: includes/vendors/tinymce.php:34
|
||||
msgid "Inline styles"
|
||||
msgstr ""
|
||||
|
||||
#: includes/vendors/tinymce.php:24
|
||||
msgid "Link styles"
|
||||
msgstr ""
|
||||
|
||||
#: includes/core/theme-setup.php:15
|
||||
msgid "Main menu"
|
||||
msgstr ""
|
||||
@@ -32,6 +44,14 @@ msgstr ""
|
||||
msgid "Moonshine"
|
||||
msgstr ""
|
||||
|
||||
#: includes/vendors/tinymce.php:44
|
||||
msgid "Paragraph styles"
|
||||
msgstr ""
|
||||
|
||||
#. Author of the theme
|
||||
msgid "Pascal Martineau "
|
||||
msgstr ""
|
||||
|
||||
#: includes/vendors/tinymce.php:37
|
||||
msgid "Semi-bold"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,50 +1,101 @@
|
||||
import { version } from "./package.json";
|
||||
|
||||
const siteUrl = process.env.NUXT_SITE_URL;
|
||||
if (!siteUrl) {
|
||||
throw new Error(
|
||||
`NUXT_SITE_URL is not defined. Make sure to set it in your build environment variables.`,
|
||||
);
|
||||
}
|
||||
|
||||
const wpUrl = process.env.NUXT_WP_URL;
|
||||
if (!wpUrl) {
|
||||
throw new Error(
|
||||
`NUXT_WP_URL is not defined. Make sure to set it in your build environment variables.`,
|
||||
);
|
||||
}
|
||||
const wpDomain = new URL(wpUrl).hostname;
|
||||
|
||||
const enableCloudflareImages = Boolean(process.env.ENABLE_CLOUDFLARE_IMAGES);
|
||||
|
||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
|
||||
modules: [
|
||||
"@lewebsimple/nuxt-graphql",
|
||||
"@nuxt/eslint",
|
||||
"@nuxt/image",
|
||||
"@nuxt/ui",
|
||||
"@nuxtjs/device",
|
||||
"@nuxtjs/seo",
|
||||
"nuxt-auth-utils",
|
||||
"nuxt-svgo",
|
||||
],
|
||||
|
||||
components: {
|
||||
dirs: [
|
||||
{ path: "~/components", pathPrefix: false },
|
||||
],
|
||||
dirs: [{ path: "~/components", pathPrefix: false }],
|
||||
},
|
||||
|
||||
devtools: { enabled: true },
|
||||
|
||||
css: ["~/assets/css/_main.css"],
|
||||
|
||||
site: {
|
||||
url: siteUrl,
|
||||
name: "WP Headless",
|
||||
defaultLocale: "fr",
|
||||
},
|
||||
|
||||
ui: {
|
||||
colorMode: false,
|
||||
},
|
||||
|
||||
runtimeConfig: {
|
||||
wpUrl,
|
||||
},
|
||||
|
||||
compatibilityDate: "2026-01-01",
|
||||
|
||||
eslint: {
|
||||
config: {
|
||||
stylistic: {
|
||||
arrowParens: true,
|
||||
commaDangle: "always-multiline",
|
||||
indent: 2,
|
||||
quotes: "double",
|
||||
semi: true,
|
||||
nitro: {
|
||||
preset: "cloudflare_module",
|
||||
cloudflare: {
|
||||
wrangler: {
|
||||
vars: {
|
||||
NODE_ENV: "staging",
|
||||
NUXT_SITE_URL: siteUrl,
|
||||
NUXT_WP_URL: wpUrl,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
graphql: {
|
||||
context: "server/graphql/context.ts",
|
||||
schemas: {
|
||||
wp: {
|
||||
type: "remote",
|
||||
url: `${process.env.NUXT_WP_URL || "https://wp-headless.ledevsimple.ca"}/graphql`,
|
||||
middleware: "server/graphql/wp-middleware.ts",
|
||||
client: {
|
||||
cache: {
|
||||
keyVersion: version,
|
||||
},
|
||||
},
|
||||
saveSdl: "server/graphql/schema.graphql",
|
||||
server: {
|
||||
context: ["server/graphql/context"],
|
||||
schema: {
|
||||
wp: { type: "remote", endpoint: `${wpUrl}/graphql`, hooks: ["server/graphql/wp-hooks"] },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
image: {
|
||||
provider: enableCloudflareImages ? "cloudflare" : "none",
|
||||
cloudflare: { baseURL: `${siteUrl}/` },
|
||||
domains: [wpDomain],
|
||||
format: ["avif", "webp"],
|
||||
},
|
||||
|
||||
robots: {
|
||||
sitemap: `${wpUrl}/sitemap_index.xml`,
|
||||
},
|
||||
|
||||
sitemap: false,
|
||||
|
||||
svgo: {
|
||||
autoImportPath: "~/assets/svg/",
|
||||
componentPrefix: "Svg",
|
||||
defaultImport: "component",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,43 +1,65 @@
|
||||
{
|
||||
"name": "@lewebsimple/moonshine",
|
||||
"description": "Headless WordPress theme based on Nuxt.",
|
||||
"version": "0.1.2",
|
||||
"type": "module",
|
||||
"version": "0.1.13",
|
||||
"private": true,
|
||||
"description": "Headless WordPress theme based on Nuxt.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
"build": "pnpm --sequential /build:.*/",
|
||||
"build:nuxt": "nuxt build",
|
||||
"dev": "nuxt dev",
|
||||
"lint": "eslint --fix .",
|
||||
"editor-style": "pnpx @tailwindcss/cli -i ./app/assets/css/_main.css -o ./editor-style.css --minify",
|
||||
"format": "oxfmt .",
|
||||
"lint": "oxlint . --fix",
|
||||
"postinstall": "pnpm --sequential /postinstall:.*/",
|
||||
"postinstall:wrangler-types": "wrangler types ./server/types/cloudflare.d.ts",
|
||||
"postinstall:nuxt": "nuxt prepare",
|
||||
"preview": "nuxt preview",
|
||||
"release": "pnpm lint && pnpm typecheck && changelogen --noAuthors --release --push",
|
||||
"typecheck": "nuxt typecheck"
|
||||
"preview": "pnpm --sequential /preview:.*/",
|
||||
"preview:build": "pnpm run build",
|
||||
"preview:wrangler-dev": "wrangler dev --port 3000",
|
||||
"release": "pnpm --sequential /release:.*/",
|
||||
"release:lint": "oxlint .",
|
||||
"release:typecheck": "nuxt typecheck",
|
||||
"release:changelogen": "changelogen --noAuthors --release --push"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify-json/lucide": "^1.2.84",
|
||||
"@lewebsimple/nuxt-graphql": "^0.4.0",
|
||||
"@iconify-json/cib": "^1.2.3",
|
||||
"@iconify-json/lucide": "^1.2.88",
|
||||
"@lewebsimple/nuxt-graphql": "^0.6.8",
|
||||
"@nuxt/image": "^2.0.0",
|
||||
"@nuxt/ui": "4.3.0",
|
||||
"@nuxtjs/device": "4.0.0",
|
||||
"@nuxtjs/seo": "^3.4.0",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"nuxt": "^4.2.2",
|
||||
"nuxt-auth-utils": "^0.5.27",
|
||||
"nuxt": "^4.3.0",
|
||||
"nuxt-auth-utils": "^0.5.28",
|
||||
"nuxt-svgo": "^4.2.6",
|
||||
"tailwindcss": "^4.1.18",
|
||||
"vue": "^3.5.26",
|
||||
"vue": "^3.5.27",
|
||||
"vue-router": "^4.6.4",
|
||||
"zod": "^4.3.5"
|
||||
"zod": "^4.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/eslint": "^1.12.1",
|
||||
"changelogen": "^0.6.2",
|
||||
"eslint": "^9.39.2",
|
||||
"oxfmt": "^0.28.0",
|
||||
"oxlint": "^1.43.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vue-tsc": "^3.2.2"
|
||||
"vue-tsc": "^3.2.4",
|
||||
"wrangler": "^4.62.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"@tiptap/core": "3.14.0",
|
||||
"@tiptap/pm": "3.14.0"
|
||||
}
|
||||
},
|
||||
"onlyBuiltDependencies": [
|
||||
"@parcel/watcher",
|
||||
"esbuild",
|
||||
"sharp",
|
||||
"unrs-resolver",
|
||||
"vue-demi",
|
||||
"workerd"
|
||||
]
|
||||
},
|
||||
"changelog": {
|
||||
"types": {
|
||||
|
||||
7114
wp-content/themes/moonshine/pnpm-lock.yaml
generated
7114
wp-content/themes/moonshine/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
||||
onlyBuiltDependencies:
|
||||
- '@parcel/watcher'
|
||||
- esbuild
|
||||
- unrs-resolver
|
||||
- vue-demi
|
||||
@@ -1,2 +0,0 @@
|
||||
User-Agent: *
|
||||
Disallow:
|
||||
21
wp-content/themes/moonshine/server/api/login.post.ts
Normal file
21
wp-content/themes/moonshine/server/api/login.post.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export default defineEventHandler(async (event) => {
|
||||
try {
|
||||
const variables = await readBody<AuthLoginForm>(event);
|
||||
const { data } = await useGraphQLOperation(event, "AuthLogin", variables);
|
||||
if (!data?.login) {
|
||||
throw new Error("INVALID_LOGIN");
|
||||
}
|
||||
if (!(await handleLogin(event, data))) {
|
||||
throw new Error("LOGIN_FAILED");
|
||||
}
|
||||
return { success: true, message: "Connexion réussie" };
|
||||
} catch (error) {
|
||||
const messages = {
|
||||
INVALID_LOGIN: "Identifiants invalides. Veuillez réessayer.",
|
||||
LOGIN_FAILED: "Une erreur est survenue lors de la connexion. Veuillez réessayer plus tard.",
|
||||
};
|
||||
const message =
|
||||
error instanceof Error && error.message in messages ? error.message : "LOGIN_FAILED";
|
||||
return { success: false, message: messages[message as keyof typeof messages] };
|
||||
}
|
||||
});
|
||||
@@ -4,9 +4,9 @@ export default defineEventHandler(async (event) => {
|
||||
try {
|
||||
await handleLogout(event);
|
||||
return { success: true, message: "Déconnexion réussie" };
|
||||
}
|
||||
catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Une erreur est survenue lors de la déconnexion.";
|
||||
} catch (error) {
|
||||
const message =
|
||||
error instanceof Error ? error.message : "Une erreur est survenue lors de la déconnexion.";
|
||||
return { success: false, message };
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import { defineGraphQLContext } from "@lewebsimple/nuxt-graphql/helpers";
|
||||
import type { AuthLoginMutation } from "#graphql/typed-documents";
|
||||
|
||||
export default defineGraphQLContext(async (event) => {
|
||||
const authToken = await getAuthToken(event);
|
||||
|
||||
return {
|
||||
authToken,
|
||||
handleLogin: async (loginData: AuthLoginMutation) => handleLogin(event, loginData),
|
||||
};
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user