Initial succesful implementation of Drupal + Fornax static site generation

This commit is contained in:
Ismael Abu-jadur Garcia
2025-11-14 12:26:52 +00:00
committed by Jonas Juselius
parent f3bad135c8
commit df2207f158
315 changed files with 26192 additions and 88 deletions

297
.ddev/config.yaml Normal file
View File

@@ -0,0 +1,297 @@
name: oceanbox
type: drupal
docroot: web
php_version: "8.3"
webserver_type: nginx-fpm
xdebug_enabled: false
additional_hostnames: []
additional_fqdns: []
database:
type: mariadb
version: "10.11"
use_dns_when_possible: true
composer_version: "2"
web_environment: []
corepack_enable: true
# Key features of DDEV's config.yaml:
# name: <projectname> # Name of the project, automatically provides
# http://projectname.ddev.site and https://projectname.ddev.site
# If the name is omitted, the project will take the name of the enclosing directory,
# which is useful if you want to have a copy of the project side by side with this one.
# type: <projecttype> # backdrop, cakephp, craftcms, drupal, drupal6, drupal7, drupal8, drupal9, drupal10, drupal11, generic, laravel, magento, magento2, php, shopware6, silverstripe, symfony, typo3, wordpress
# See https://docs.ddev.com/en/stable/users/quickstart/ for more
# information on the different project types
# docroot: <relative_path> # Relative path to the directory containing index.php.
# php_version: "8.3" # PHP version to use, "5.6" through "8.4"
# You can explicitly specify the webimage but this
# is not recommended, as the images are often closely tied to DDEV's' behavior,
# so this can break upgrades.
# webimage: <docker_image>
# Its unusual to change this option, and we dont recommend it without Docker experience and a good reason.
# Typically, this means additions to the existing web image using a .ddev/web-build/Dockerfile.*
# database:
# type: <dbtype> # mysql, mariadb, postgres
# version: <version> # database version, like "10.11" or "8.0"
# MariaDB versions can be 5.5-10.8, 10.11, 11.4, 11.8
# MySQL versions can be 5.5-8.0, 8.4
# PostgreSQL versions can be 9-17
# router_http_port: <port> # Port to be used for http (defaults to global configuration, usually 80)
# router_https_port: <port> # Port for https (defaults to global configuration, usually 443)
# xdebug_enabled: false # Set to true to enable Xdebug and "ddev start" or "ddev restart"
# Note that for most people the commands
# "ddev xdebug" to enable Xdebug and "ddev xdebug off" to disable it work better,
# as leaving Xdebug enabled all the time is a big performance hit.
# xhgui_http_port: "8143"
# xhgui_https_port: "8142"
# The XHGui ports can be changed from the default 8143 and 8142
# Very rarely used
# host_xhgui_port: "8142"
# Can be used to change the host binding port of the XHGui
# application. Rarely used; only when port conflict and
# bind_all_ports is used (normally with router disabled)
# xhprof_mode: [prepend|xhgui|global]
# Set to "xhgui" to enable XHGui features
# "xhgui" will become default in a future major release
# webserver_type: nginx-fpm, apache-fpm, generic
# timezone: Europe/Berlin
# If timezone is unset, DDEV will attempt to derive it from the host system timezone
# using the $TZ environment variable or the /etc/localtime symlink.
# This is the timezone used in the containers and by PHP;
# it can be set to any valid timezone,
# see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
# For example Europe/Dublin or MST7MDT
# composer_root: <relative_path>
# Relative path to the Composer root directory from the project root. This is
# the directory which contains the composer.json and where all Composer related
# commands are executed.
# composer_version: "2"
# You can set it to "" or "2" (default) for Composer v2 or "1" for Composer v1
# to use the latest major version available at the time your container is built.
# It is also possible to use each other Composer version channel. This includes:
# - 2.2 (latest Composer LTS version)
# - stable
# - preview
# - snapshot
# Alternatively, an explicit Composer version may be specified, for example "2.2.18".
# To reinstall Composer after the image was built, run "ddev debug rebuild".
# nodejs_version: "22"
# change from the default system Node.js version to any other version.
# See https://docs.ddev.com/en/stable/users/configuration/config/#nodejs_version for more information
# and https://www.npmjs.com/package/n#specifying-nodejs-versions for the full documentation,
# Note that using of 'ddev nvm' is discouraged because "nodejs_version" is much easier to use,
# can specify any version, and is more robust than using 'nvm'.
# corepack_enable: false
# Change to 'true' to 'corepack enable' and gain access to latest versions of yarn/pnpm
# additional_hostnames:
# - somename
# - someothername
# would provide http and https URLs for "somename.ddev.site"
# and "someothername.ddev.site".
# additional_fqdns:
# - example.com
# - sub1.example.com
# would provide http and https URLs for "example.com" and "sub1.example.com"
# Please take care with this because it can cause great confusion.
# upload_dirs: "custom/upload/dir"
#
# upload_dirs:
# - custom/upload/dir
# - ../private
#
# would set the destination paths for ddev import-files to <docroot>/custom/upload/dir
# When Mutagen is enabled this path is bind-mounted so that all the files
# in the upload_dirs don't have to be synced into Mutagen.
# disable_upload_dirs_warning: false
# If true, turns off the normal warning that says
# "You have Mutagen enabled and your 'php' project type doesn't have upload_dirs set"
# ddev_version_constraint: ""
# Example:
# ddev_version_constraint: ">= 1.24.8"
# This will enforce that the running ddev version is within this constraint.
# See https://github.com/Masterminds/semver#checking-version-constraints for
# supported constraint formats
# working_dir:
# web: /var/www/html
# db: /home
# would set the default working directory for the web and db services.
# These values specify the destination directory for ddev ssh and the
# directory in which commands passed into ddev exec are run.
# omit_containers: [db, ddev-ssh-agent]
# Currently only these containers are supported. Some containers can also be
# omitted globally in the ~/.ddev/global_config.yaml. Note that if you omit
# the "db" container, several standard features of DDEV that access the
# database container will be unusable. In the global configuration it is also
# possible to omit ddev-router, but not here.
# performance_mode: "global"
# DDEV offers performance optimization strategies to improve the filesystem
# performance depending on your host system. Should be configured globally.
#
# If set, will override the global config. Possible values are:
# - "global": uses the value from the global config.
# - "none": disables performance optimization for this project.
# - "mutagen": enables Mutagen for this project.
# - "nfs": enables NFS for this project.
#
# See https://docs.ddev.com/en/stable/users/install/performance/#nfs
# See https://docs.ddev.com/en/stable/users/install/performance/#mutagen
# fail_on_hook_fail: False
# Decide whether 'ddev start' should be interrupted by a failing hook
# host_https_port: "59002"
# The host port binding for https can be explicitly specified. It is
# dynamic unless otherwise specified.
# This is not used by most people, most people use the *router* instead
# of the localhost port.
# host_webserver_port: "59001"
# The host port binding for the ddev-webserver can be explicitly specified. It is
# dynamic unless otherwise specified.
# This is not used by most people, most people use the *router* instead
# of the localhost port.
# host_db_port: "59002"
# The host port binding for the ddev-dbserver can be explicitly specified. It is dynamic
# unless explicitly specified.
# mailpit_http_port: "8025"
# mailpit_https_port: "8026"
# The Mailpit ports can be changed from the default 8025 and 8026
# host_mailpit_port: "8025"
# The mailpit port is not normally bound on the host at all, instead being routed
# through ddev-router, but it can be bound directly to localhost if specified here.
# webimage_extra_packages: [php7.4-tidy, php-bcmath]
# Extra Debian packages that are needed in the webimage can be added here
# dbimage_extra_packages: [telnet,netcat]
# Extra Debian packages that are needed in the dbimage can be added here
# use_dns_when_possible: true
# If the host has internet access and the domain configured can
# successfully be looked up, DNS will be used for hostname resolution
# instead of editing /etc/hosts
# Defaults to true
# project_tld: ddev.site
# The top-level domain used for project URLs
# The default "ddev.site" allows DNS lookup via a wildcard
# If you prefer you can change this to "ddev.local" to preserve
# pre-v1.9 behavior.
# ngrok_args: --basic-auth username:pass1234
# Provide extra flags to the "ngrok http" command, see
# https://ngrok.com/docs/agent/config/v3/#agent-configuration or run "ngrok http -h"
# disable_settings_management: false
# If true, DDEV will not create CMS-specific settings files like
# Drupal's settings.php/settings.ddev.php or TYPO3's additional.php
# In this case the user must provide all such settings.
# You can inject environment variables into the web container with:
# web_environment:
# - SOMEENV=somevalue
# - SOMEOTHERENV=someothervalue
# no_project_mount: false
# (Experimental) If true, DDEV will not mount the project into the web container;
# the user is responsible for mounting it manually or via a script.
# This is to enable experimentation with alternate file mounting strategies.
# For advanced users only!
# bind_all_interfaces: false
# If true, host ports will be bound on all network interfaces,
# not the localhost interface only. This means that ports
# will be available on the local network if the host firewall
# allows it.
# default_container_timeout: 120
# The default time that DDEV waits for all containers to become ready can be increased from
# the default 120. This helps in importing huge databases, for example.
#web_extra_exposed_ports:
#- name: nodejs
# container_port: 3000
# http_port: 2999
# https_port: 3000
#- name: something
# container_port: 4000
# https_port: 4000
# http_port: 3999
# Allows a set of extra ports to be exposed via ddev-router
# Fill in all three fields even if you dont intend to use the https_port!
# If you dont add https_port, then it defaults to 0 and ddev-router will fail to start.
#
# The port behavior on the ddev-webserver must be arranged separately, for example
# using web_extra_daemons.
# For example, with a web app on port 3000 inside the container, this config would
# expose that web app on https://<project>.ddev.site:9999 and http://<project>.ddev.site:9998
# web_extra_exposed_ports:
# - name: myapp
# container_port: 3000
# http_port: 9998
# https_port: 9999
#web_extra_daemons:
#- name: "http-1"
# command: "/var/www/html/node_modules/.bin/http-server -p 3000"
# directory: /var/www/html
#- name: "http-2"
# command: "/var/www/html/node_modules/.bin/http-server /var/www/html/sub -p 3000"
# directory: /var/www/html
# override_config: false
# By default, config.*.yaml files are *merged* into the configuration
# But this means that some things can't be overridden
# For example, if you have 'use_dns_when_possible: true'' you can't override it with a merge
# and you can't erase existing hooks or all environment variables.
# However, with "override_config: true" in a particular config.*.yaml file,
# 'use_dns_when_possible: false' can override the existing values, and
# hooks:
# post-start: []
# or
# web_environment: []
# or
# additional_hostnames: []
# can have their intended affect. 'override_config' affects only behavior of the
# config.*.yaml file it exists in.
# Many DDEV commands can be extended to run tasks before or after the
# DDEV command is executed, for example "post-start", "post-import-db",
# "pre-composer", "post-composer"
# See https://docs.ddev.com/en/stable/users/extend/custom-commands/ for more
# information on the commands that can be extended and the tasks you can define
# for them. Example:
#hooks:
# post-import-db:
# - exec: drush sql:sanitize
# - exec: drush updatedb
# - exec: drush cache:rebuild

65
.gitattributes vendored Normal file
View File

@@ -0,0 +1,65 @@
# Drupal git normalization
# @see https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html
# @see https://www.drupal.org/node/1542048
# Normally these settings would be done with macro attributes for improved
# readability and easier maintenance. However macros can only be defined at the
# repository root directory. Drupal avoids making any assumptions about where it
# is installed.
# Define text file attributes.
# - Treat them as text.
# - Ensure no CRLF line-endings, neither on checkout nor on checkin.
# - Detect whitespace errors.
# - Exposed by default in `git diff --color` on the CLI.
# - Validate with `git diff --check`.
# - Deny applying with `git apply --whitespace=error-all`.
# - Fix automatically with `git apply --whitespace=fix`.
*.config text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.css text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.dist text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.engine text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
*.html text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=html
*.inc text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
*.install text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
*.js text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.json text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.lock text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.map text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.md text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.module text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
*.php text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
*.po text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.profile text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
*.script text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.sh text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
*.sql text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.svg text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.theme text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2 diff=php linguist-language=php
*.twig text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.txt text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.xml text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
*.yml text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tab-in-indent,tabwidth=2
# PHPStan's baseline uses tabs instead of spaces.
core/.phpstan-baseline.php text eol=lf whitespace=blank-at-eol,-blank-at-eof,-space-before-tab,tabwidth=2 diff=php linguist-language=php
# Define binary file attributes.
# - Do not treat them as text.
# - Include binary diff in patches instead of "binary files differ."
*.avif -text diff
*.eot -text diff
*.exe -text diff
*.gif -text diff
*.gz -text diff
*.ico -text diff
*.jpeg -text diff
*.jpg -text diff
*.otf -text diff
*.phar -text diff
*.png -text diff
*.svgz -text diff
*.ttf -text diff
*.woff -text diff
*.woff2 -text diff

76
.gitignore vendored Normal file
View File

@@ -0,0 +1,76 @@
# Hidden files.
.DS*
.project
# Temporary files.
tmp*
# Ignore editor config
.editorconfig
# Ignore F# build
obj
bin
# Ignore public files
/frontend/_public
# Ignore configuration files that may contain sensitive information
/web/sites/*/*settings*.php
/web/sites/*/*services*.yml
# Ignore paths that may contain user-generated content
/web/sites/*/files
/web/sites/*/public
/web/sites/*/private
/web/sites/*/files-public
/web/sites/*/files-private
# Ignore paths that may contain temporary files
/web/sites/*/translations
/web/sites/*/tmp
/web/sites/*/cache
# Ignore drupal core
/web/vendor
/web/core
/web/modules/README.txt
/web/modules/contrib
/web/profiles/README.txt
/web/profiles/contrib
/web/sites/development.services.yml
/web/sites/example.settings.local.php
/web/sites/example.sites.php
/web/sites/README.txt
/web/themes/README.txt
/web/themes/contrib
/web/.csslintrc
/web/.editorconfig
/web/.eslintignore
/web/.eslintrc.json
/web/.gitattributes
/web/.htaccess
/web/.ht.router.php
/web/autoload.php
/web/composer.json
/web/composer.lock
/web/example.gitignore
/web/index.php
/web/INSTALL.txt
/web/LICENSE.txt
/web/README.txt
/web/robots.txt
/web/update.php
/web/web.config
/recipes
# Ignore vendor dependencies and scripts
/vendor
/composer.phar
/composer
/robo.phar
/robo
/drush.phar
/drush
/drupal.phar
/drupal

102
README.md
View File

@@ -1,93 +1,19 @@
# Fornix
# Drupal + Fornax
Small decoupled setup that pulls content from Drupal through JSONAPI and
converts it into a static site using Fornax and F#.
## What it decoupled
- Fetches content from the Drupal site exposed through JSONAPI
- Deserializes Drupal into F# types
- Uses Fornax loaders + generators to render the content into static HTML
## Getting started
## Tech stack (currently)
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
- Drupal 11 + JSONAPI
- F#
- Fornax
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://gitlab.com/oceanbox/fornix.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://gitlab.com/oceanbox/fornix/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
## Must knows
Drupal JSONAPI Extras has been patched with a custom patch to make sure that we
can use _default_include to include nested relationships.

124
composer.json Normal file
View File

@@ -0,0 +1,124 @@
{
"name": "drupal/recommended-project",
"description": "Project template for Drupal projects with a relocated document root",
"type": "project",
"license": "GPL-2.0-or-later",
"homepage": "https://www.drupal.org/project/drupal",
"support": {
"docs": "https://www.drupal.org/docs/user_guide/en/index.html",
"chat": "https://www.drupal.org/node/314178"
},
"repositories": [
{
"type": "composer",
"url": "https://packages.drupal.org/8"
}
],
"require": {
"composer/installers": "^2.3",
"cweagans/composer-patches": "^2.0",
"drupal/admin_toolbar": "^3.6",
"drupal/core-composer-scaffold": "^11.2",
"drupal/core-project-message": "^11.2",
"drupal/core-recipe-unpack": "^11.2",
"drupal/core-recommended": "^11.2",
"drupal/devel": "^5.4",
"drupal/field_group": "^4.0",
"drupal/jsonapi_extras": "^3.27",
"drupal/jsonapi_include": "^2.0",
"drupal/jsonapi_resources": "^1.3",
"drupal/paragraphs": "^1.19",
"drupal/pathauto": "^1.14",
"drupal/rest_absolute_urls": "^2.0"
},
"conflict": {
"drupal/drupal": "*"
},
"minimum-stability": "stable",
"prefer-stable": true,
"config": {
"allow-plugins": {
"composer/installers": true,
"cweagans/composer-patches": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"drupal/core-composer-scaffold": true,
"drupal/core-project-message": true,
"drupal/core-recipe-unpack": true,
"php-http/discovery": true,
"php-tuf/composer-integration": true,
"phpstan/extension-installer": true
},
"sort-packages": true
},
"extra": {
"patches": {
"drupal/jsonapi_include": {
"Issue #3490592: Incompatile with jsonapi_default fix": "https://git.drupalcode.org/project/jsonapi_include/-/merge_requests/28.diff"
},
"drupal/jsonapi_extras": {
"Issue #3373151: Auto include default includes of related entities": "patches/jsonapi_extras_default_includes.patch"
}
},
"drupal-scaffold": {
"locations": {
"web-root": "web/"
}
},
"installer-paths": {
"web/core": [
"type:drupal-core"
],
"web/libraries/{$name}": [
"type:drupal-library"
],
"web/modules/contrib/{$name}": [
"type:drupal-module"
],
"web/profiles/contrib/{$name}": [
"type:drupal-profile"
],
"web/themes/contrib/{$name}": [
"type:drupal-theme"
],
"drush/Commands/contrib/{$name}": [
"type:drupal-drush"
],
"web/modules/custom/{$name}": [
"type:drupal-custom-module"
],
"web/profiles/custom/{$name}": [
"type:drupal-custom-profile"
],
"web/themes/custom/{$name}": [
"type:drupal-custom-theme"
],
"recipes/{$name}": [
"type:drupal-recipe"
]
},
"drupal-core-project-message": {
"include-keys": [
"homepage",
"support"
],
"post-create-project-cmd-message": [
"<bg=blue;fg=white> </>",
"<bg=blue;fg=white> Congratulations, youve installed the Drupal codebase </>",
"<bg=blue;fg=white> from the drupal/recommended-project template! </>",
"<bg=blue;fg=white> </>",
"",
"<bg=yellow;fg=black>Next steps</>:",
" * Install the site: https://www.drupal.org/docs/installing-drupal",
" * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html",
" * Get support: https://www.drupal.org/support",
" * Get involved with the Drupal community:",
" https://www.drupal.org/getting-involved",
" * Remove the plugin that prints this message:",
" composer remove drupal/core-project-message"
]
}
},
"require-dev": {
"drush/drush": "^13.6"
}
}

7706
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {
"fornax": {
"version": "0.16.0",
"commands": [
"fornax"
],
"rollForward": false
}
}
}

2
frontend/Program.fs Normal file
View File

@@ -0,0 +1,2 @@
// For more information see https://aka.ms/fsharp-console-apps
printfn "Hello from F#"

44
frontend/config.fsx Executable file
View File

@@ -0,0 +1,44 @@
#r "_lib/Fornax.Core.dll"
open Config
open System.IO
let postPredicate (projectRoot: string, page: string) =
let fileName = Path.Combine(projectRoot,page)
let ext = Path.GetExtension page
if ext = ".md" then
let ctn = File.ReadAllText fileName
page.Contains("_public") |> not
&& ctn.Contains("layout: post")
else
false
let staticPredicate (projectRoot: string, page: string) =
let ext = Path.GetExtension page
let fileShouldBeExcluded =
ext = ".fsx" ||
ext = ".md" ||
page.Contains "_public" ||
page.Contains "_bin" ||
page.Contains "_lib" ||
page.Contains "_data" ||
page.Contains "_settings" ||
page.Contains "_config.yml" ||
page.Contains ".sass-cache" ||
page.Contains ".git" ||
page.Contains ".ionide"
fileShouldBeExcluded |> not
let config = {
Generators = [
{Script = "less.fsx"; Trigger = OnFileExt ".less"; OutputFile = ChangeExtension "css" }
{Script = "sass.fsx"; Trigger = OnFileExt ".scss"; OutputFile = ChangeExtension "css" }
{Script = "post.fsx"; Trigger = OnFilePredicate postPredicate; OutputFile = ChangeExtension "html" }
{Script = "staticfile.fsx"; Trigger = OnFilePredicate staticPredicate; OutputFile = SameFileName }
{Script = "index.fsx"; Trigger = Once; OutputFile = MultipleFiles id }
{Script = "about.fsx"; Trigger = Once; OutputFile = NewFileName "about.html" }
{Script = "contact.fsx"; Trigger = Once; OutputFile = NewFileName "contact.html" }
{Script = "basicpage.fsx"; Trigger = Once; OutputFile = MultipleFiles id }
]
}

17
frontend/frontend.fsproj Normal file
View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FSharp.Data" Version="6.6.0" />
<PackageReference Include="FSharp.SystemTextJson" Version="1.4.36" />
</ItemGroup>
</Project>

40
frontend/generators/about.fsx Executable file
View File

@@ -0,0 +1,40 @@
#r "../_lib/Fornax.Core.dll"
#load "layout.fsx"
open Html
let about = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi nisi diam, vehicula quis blandit id, suscipit sed libero. Proin at diam dolor. In hac habitasse platea dictumst. Donec quis dui vitae quam eleifend dignissim non sed libero. In hac habitasse platea dictumst. In ullamcorper mollis risus, a vulputate quam accumsan at. Donec sed felis sodales, blandit orci id, vulputate orci."
let generate' (ctx : SiteContents) (_: string) =
let siteInfo = ctx.TryGetValue<Globalloader.SiteInfo> ()
let desc =
siteInfo
|> Option.map (fun si -> si.description)
|> Option.defaultValue ""
Layout.layout ctx "About" [
section [Class "hero is-info is-medium is-bold"] [
div [Class "hero-body"] [
div [Class "container has-text-centered"] [
h1 [Class "title"] [!!desc]
]
]
]
div [Class "container"] [
section [Class "articles"] [
div [Class "column is-8 is-offset-2"] [
div [Class "card article"] [
div [Class "card-content"] [
div [Class "content article-body"] [
!! about
]
]
]
]
]
]]
let generate (ctx : SiteContents) (projectRoot: string) (page: string) =
generate' ctx page
|> Layout.render ctx

View File

@@ -0,0 +1,60 @@
#r "../_lib/Fornax.Core.dll"
#r "../src/Types/bin/Debug/netstandard2.0/Types.dll"
#load "./layout.fsx"
open Html
open Types.Types
let generate' (ctx: SiteContents) (_: string) =
let basicPageContent = ctx.TryGetValues<DocData>() |> Option.defaultValue Seq.empty
let siteUrl = "http://oceanbox.ddev.site"
let paragraphLayout (paragraph: Paragraph) =
match paragraph with
| Hero hero ->
div [Class "hero"] [
h1 [Class "header"] [!! hero.FieldTitle]
h2 [Class "sub-header"] [!! hero.FieldSubtitle]
match hero.FieldBackgroundImage with
| MediaVideo video ->
let videoUrl = siteUrl + video.FieldMediaVideoFile.Uri.Url
div [] [
p [Class "video"] [!! videoUrl]
]
| MediaImage image ->
let imgUrl = siteUrl + image.FieldMediaImage.Uri.Url
div [] [
img [Src imgUrl ; Alt image.FieldMediaImage.Meta.Alt ]
]
]
| SimpleText simpletext ->
// eprintfn "Simple text field body: %s" simpletext.attrs.field_body
div [Class "text"] [!! simpletext.FieldBody]
| Ignore ->
div [Class "ignored"] []
let pageContentLayout (title, paragraphs) =
let processedParagraphs =
paragraphs |> Array.map paragraphLayout
Layout.layout ctx title [
div [Class "container"] [
!! title
div [Class "content"] (processedParagraphs |> Array.toList)
]
]
let processTitle (title: string) =
title.ToLower().Replace (" ", "-") + ".html"
let processedContent =
basicPageContent
|> Seq.toList
|> List.map(fun content ->
processTitle (content.Title),
pageContentLayout (content.Title, content.FieldContent) |> Layout.render ctx
)
processedContent
let generate (ctx: SiteContents) (projectRoot: string) (page:string) =
generate' ctx page

40
frontend/generators/contact.fsx Executable file
View File

@@ -0,0 +1,40 @@
#r "../_lib/Fornax.Core.dll"
#load "layout.fsx"
open Html
let about = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi nisi diam, vehicula quis blandit id, suscipit sed libero. Proin at diam dolor. In hac habitasse platea dictumst. Donec quis dui vitae quam eleifend dignissim non sed libero. In hac habitasse platea dictumst. In ullamcorper mollis risus, a vulputate quam accumsan at. Donec sed felis sodales, blandit orci id, vulputate orci."
let generate' (ctx : SiteContents) (_: string) =
let siteInfo = ctx.TryGetValue<Globalloader.SiteInfo> ()
let desc =
siteInfo
|> Option.map (fun si -> si.description)
|> Option.defaultValue ""
Layout.layout ctx "Home" [
section [Class "hero is-info is-medium is-bold"] [
div [Class "hero-body"] [
div [Class "container has-text-centered"] [
h1 [Class "title"] [!!desc]
]
]
]
div [Class "container"] [
section [Class "articles"] [
div [Class "column is-8 is-offset-2"] [
div [Class "card article"] [
div [Class "card-content"] [
div [Class "content article-body"] [
!! about
]
]
]
]
]
]]
let generate (ctx : SiteContents) (projectRoot: string) (page: string) =
generate' ctx page
|> Layout.render ctx

67
frontend/generators/index.fsx Executable file
View File

@@ -0,0 +1,67 @@
#r "../_lib/Fornax.Core.dll"
#load "layout.fsx"
open Html
let generate' (ctx : SiteContents) (_: string) =
let posts = ctx.TryGetValues<Postloader.Post> () |> Option.defaultValue Seq.empty
let siteInfo = ctx.TryGetValue<Globalloader.SiteInfo> ()
let desc, postPageSize =
siteInfo
|> Option.map (fun si -> si.description, si.postPageSize)
|> Option.defaultValue ("", 10)
let psts =
posts
|> Seq.sortByDescending Layout.published
|> Seq.toList
|> List.chunkBySize postPageSize
|> List.map (List.map (Layout.postLayout true))
let pages = List.length psts
let getFilenameForIndex i =
if i = 0 then
sprintf "index.html"
else
sprintf "posts/page%i.html" i
let layoutForPostSet i psts =
let nextPage =
if i = (pages - 1) then "#"
else "/" + getFilenameForIndex (i + 1)
let previousPage =
if i = 0 then "#"
else "/" + getFilenameForIndex (i - 1)
Layout.layout ctx "Home" [
section [Class "hero is-info is-medium is-bold"] [
div [Class "hero-body"] [
div [Class "container has-text-centered"] [
h1 [Class "title"] [!!desc]
]
]
]
div [Class "container"] [
section [Class "articles"] [
div [Class "column is-8 is-offset-2"] psts
]
]
div [Class "container"] [
div [Class "container has-text-centered"] [
a [Href previousPage] [!! "Previous"]
!! (sprintf "%i of %i" (i + 1) pages)
a [Href nextPage] [!! "Next"]
]
]]
psts
|> List.mapi (fun i psts ->
getFilenameForIndex i,
layoutForPostSet i psts
|> Layout.render ctx)
let generate (ctx : SiteContents) (projectRoot: string) (page: string) =
generate' ctx page

106
frontend/generators/layout.fsx Executable file
View File

@@ -0,0 +1,106 @@
#r "../_lib/Fornax.Core.dll"
#if !FORNAX
#load "../loaders/postloader.fsx"
#load "../loaders/pageloader.fsx"
#load "../loaders/globalloader.fsx"
#endif
open Html
let injectWebsocketCode (webpage:string) =
let websocketScript =
"""
<script type="text/javascript">
var wsUri = "ws://localhost:8080/websocket";
function init()
{
websocket = new WebSocket(wsUri);
websocket.onclose = function(evt) { onClose(evt) };
}
function onClose(evt)
{
console.log('closing');
websocket.close();
document.location.reload();
}
window.addEventListener("load", init, false);
</script>
"""
let head = "<head>"
let index = webpage.IndexOf head
webpage.Insert ( (index + head.Length + 1),websocketScript)
let layout (ctx : SiteContents) active bodyCnt =
let pages = ctx.TryGetValues<Pageloader.Page> () |> Option.defaultValue Seq.empty
let siteInfo = ctx.TryGetValue<Globalloader.SiteInfo> ()
let ttl =
siteInfo
|> Option.map (fun si -> si.title)
|> Option.defaultValue ""
let menuEntries =
pages
|> Seq.map (fun p ->
let cls = if p.title = active then "navbar-item is-active" else "navbar-item"
a [Class cls; Href p.link] [!! p.title ])
|> Seq.toList
html [] [
head [] [
meta [CharSet "utf-8"]
meta [Name "viewport"; Content "width=device-width, initial-scale=1"]
title [] [!! ttl]
link [Rel "icon"; Type "image/png"; Sizes "32x32"; Href "/images/favicon.png"]
link [Rel "stylesheet"; Href "https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"]
link [Rel "stylesheet"; Href "https://fonts.googleapis.com/css?family=Open+Sans"]
link [Rel "stylesheet"; Href "https://unpkg.com/bulma@0.8.0/css/bulma.min.css"]
link [Rel "stylesheet"; Type "text/css"; Href "/style/style.css"]
]
body [] [
nav [Class "navbar"] [
div [Class "container"] [
div [Class "navbar-brand"] [
a [Class "navbar-item"; Href "/"] [
img [Src "/images/bulma.png"; Alt "Logo"]
]
span [Class "navbar-burger burger"; HtmlProperties.Custom ("data-target", "navbarMenu")] [
span [] []
span [] []
span [] []
]
]
div [Id "navbarMenu"; Class "navbar-menu"] menuEntries
]
]
yield! bodyCnt
]
]
let render (ctx : SiteContents) cnt =
let disableLiveRefresh = ctx.TryGetValue<Postloader.PostConfig> () |> Option.map (fun n -> n.disableLiveRefresh) |> Option.defaultValue false
cnt
|> HtmlElement.ToString
|> fun n -> if disableLiveRefresh then n else injectWebsocketCode n
let published (post: Postloader.Post) =
post.published
|> Option.defaultValue System.DateTime.Now
|> fun n -> n.ToString("yyyy-MM-dd")
let postLayout (useSummary: bool) (post: Postloader.Post) =
div [Class "card article"] [
div [Class "card-content"] [
div [Class "media-content has-text-centered"] [
p [Class "title article-title"; ] [ a [Href post.link] [!! post.title]]
p [Class "subtitle is-6 article-subtitle"] [
a [Href "#"] [!! (defaultArg post.author "")]
!! (sprintf "on %s" (published post))
]
]
div [Class "content article-body"] [
!! (if useSummary then post.summary else post.content)
]
]
]

38
frontend/generators/post.fsx Executable file
View File

@@ -0,0 +1,38 @@
#r "../_lib/Fornax.Core.dll"
#load "layout.fsx"
open Html
let generate' (ctx : SiteContents) (page: string) =
let post =
ctx.TryGetValues<Postloader.Post> ()
|> Option.defaultValue Seq.empty
|> Seq.find (fun n -> n.file = page)
let siteInfo = ctx.TryGetValue<Globalloader.SiteInfo> ()
let desc =
siteInfo
|> Option.map (fun si -> si.description)
|> Option.defaultValue ""
Layout.layout ctx post.title [
section [Class "hero is-info is-medium is-bold"] [
div [Class "hero-body"] [
div [Class "container has-text-centered"] [
h1 [Class "title"] [!!desc]
]
]
]
div [Class "container"] [
section [Class "articles"] [
div [Class "column is-8 is-offset-2"] [
Layout.postLayout false post
]
]
]
]
let generate (ctx : SiteContents) (projectRoot: string) (page: string) =
generate' ctx page
|> Layout.render ctx

View File

@@ -0,0 +1,7 @@
#r "../_lib/Fornax.Core.dll"
open System.IO
let generate (ctx : SiteContents) (projectRoot: string) (page: string) =
let inputPath = Path.Combine(projectRoot, page)
File.ReadAllBytes inputPath

BIN
frontend/images/avatar.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
frontend/images/bulma.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
frontend/images/favicon.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

1
frontend/js/sampleJsFile.js Executable file
View File

@@ -0,0 +1 @@
var x = 1

View File

@@ -0,0 +1,43 @@
#r "../_lib/Fornax.Core.dll"
#r "../src/Types/bin/Debug/netstandard2.0/Types.dll"
#r "nuget: FSharp.Data"
#r "nuget: FSharp.SystemTextJson"
open FSharp.Data
open System.Text.Json
open System.Text.Json.Serialization
open Types.Types
let baseUrl = "http://oceanbox.ddev.site/jsonapi/node/page"
type Content = {
Data: DocData[]
}
let options =
let opts =
JsonFSharpOptions.Default()
.WithAllowNullFields(true)
.WithUnionInternalTag()
.WithUnionNamedFields()
.WithUnionUnwrapRecordCases()
.WithUnionTagName("type")
.ToJsonSerializerOptions()
opts.PropertyNamingPolicy <- JsonNamingPolicy.SnakeCaseLower
opts
let deserialize (str: string) =
JsonSerializer.Deserialize<Content>(str,options)
let loader (projectRoot: string) (siteContent: SiteContents) =
let url = baseUrl + "?page[limit]=75"
let basicpages = Http.RequestString url
let json = deserialize basicpages
json.Data
|> Array.iter siteContent.Add
siteContent

View File

@@ -0,0 +1,16 @@
#r "../_lib/Fornax.Core.dll"
type SiteInfo = {
title: string
description: string
postPageSize: int
}
let loader (projectRoot: string) (siteContent: SiteContents) =
let siteInfo =
{ title = "Sample Fornax blog";
description = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
postPageSize = 5 }
siteContent.Add(siteInfo)
siteContent

13
frontend/loaders/pageloader.fsx Executable file
View File

@@ -0,0 +1,13 @@
#r "../_lib/Fornax.Core.dll"
type Page = {
title: string
link: string
}
let loader (projectRoot: string) (siteContent: SiteContents) =
siteContent.Add({title = "Home"; link = "/"})
siteContent.Add({title = "About"; link = "/about.html"})
siteContent.Add({title = "Contact"; link = "/contact.html"})
siteContent

129
frontend/loaders/postloader.fsx Executable file
View File

@@ -0,0 +1,129 @@
#r "../_lib/Fornax.Core.dll"
#r "../_lib/Markdig.dll"
open System.IO
open Markdig
type PostConfig = {
disableLiveRefresh: bool
}
type Post = {
file: string
link : string
title: string
author: string option
published: System.DateTime option
tags: string list
content: string
summary: string
}
let contentDir = "posts"
let markdownPipeline =
MarkdownPipelineBuilder()
.UsePipeTables()
.UseGridTables()
.Build()
let isSeparator (input : string) =
input.StartsWith "---"
let isSummarySeparator (input: string) =
input.Contains "<!--more-->"
///`fileContent` - content of page to parse. Usually whole content of `.md` file
///returns content of config that should be used for the page
let getConfig (fileContent : string) =
let fileContent = fileContent.Split '\n'
let fileContent = fileContent |> Array.skip 1 //First line must be ---
let indexOfSeperator = fileContent |> Array.findIndex isSeparator
let splitKey (line: string) =
let seperatorIndex = line.IndexOf(':')
if seperatorIndex > 0 then
let key = line.[.. seperatorIndex - 1].Trim().ToLower()
let value = line.[seperatorIndex + 1 ..].Trim()
Some(key, value)
else
None
fileContent
|> Array.splitAt indexOfSeperator
|> fst
|> Seq.choose splitKey
|> Map.ofSeq
///`fileContent` - content of page to parse. Usually whole content of `.md` file
///returns HTML version of content of the page
let getContent (fileContent : string) =
let fileContent = fileContent.Split '\n'
let fileContent = fileContent |> Array.skip 1 //First line must be ---
let indexOfSeperator = fileContent |> Array.findIndex isSeparator
let _, content = fileContent |> Array.splitAt indexOfSeperator
let summary, content =
match content |> Array.tryFindIndex isSummarySeparator with
| Some indexOfSummary ->
let summary, _ = content |> Array.splitAt indexOfSummary
summary, content
| None ->
content, content
let summary = summary |> Array.skip 1 |> String.concat "\n"
let content = content |> Array.skip 1 |> String.concat "\n"
Markdown.ToHtml(summary, markdownPipeline),
Markdown.ToHtml(content, markdownPipeline)
let trimString (str : string) =
str.Trim().TrimEnd('"').TrimStart('"')
let loadFile (rootDir: string) (n: string) =
let text = File.ReadAllText n
let config = getConfig text
let summary, content = getContent text
let chopLength =
if rootDir.EndsWith(Path.DirectorySeparatorChar) then rootDir.Length
else rootDir.Length + 1
let dirPart =
n
|> Path.GetDirectoryName
|> fun x -> x.[chopLength .. ]
let file = Path.Combine(dirPart, (n |> Path.GetFileNameWithoutExtension) + ".md").Replace("\\", "/")
let link = "/" + Path.Combine(dirPart, (n |> Path.GetFileNameWithoutExtension) + ".html").Replace("\\", "/")
let title = config |> Map.find "title" |> trimString
let author = config |> Map.tryFind "author" |> Option.map trimString
let published = config |> Map.tryFind "published" |> Option.map (trimString >> System.DateTime.Parse)
let tags =
let tagsOpt =
config
|> Map.tryFind "tags"
|> Option.map (trimString >> fun n -> n.Split ',' |> Array.toList)
defaultArg tagsOpt []
{ file = file
link = link
title = title
author = author
published = published
tags = tags
content = content
summary = summary }
let loader (projectRoot: string) (siteContent: SiteContents) =
let postsPath = Path.Combine(projectRoot, contentDir)
let options = EnumerationOptions(RecurseSubdirectories = true)
let files = Directory.GetFiles(postsPath, "*", options)
files
|> Array.filter (fun n -> n.EndsWith ".md")
|> Array.map (loadFile projectRoot)
|> Array.iter siteContent.Add
siteContent.Add({disableLiveRefresh = false})
siteContent

15
frontend/posts/post.md Executable file
View File

@@ -0,0 +1,15 @@
---
layout: post
title: Some nice post title
author: @k_cieslak
published: 2020-02-19
---
# Introduction
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi nisi diam, vehicula quis blandit id, suscipit sed libero. Proin at diam dolor. In hac habitasse platea dictumst. Donec quis dui vitae quam eleifend dignissim non sed libero. In hac habitasse platea dictumst. In ullamcorper mollis risus, a vulputate quam accumsan at. Donec sed felis sodales, blandit orci id, vulputate orci.
<!--more-->
Phasellus aliquam tellus eu augue vulputate laoreet. Nunc tincidunt sed mauris eu vestibulum. Quisque id ex eget erat elementum euismod vel nec ex. Nunc et blandit neque. Duis erat ex, facilisis non consectetur sit amet, consectetur mattis ex. Vestibulum quis ligula pharetra, semper nibh nec, porta augue. In placerat auctor risus, eu dictum purus iaculis et. Vivamus viverra sollicitudin augue, in sollicitudin leo malesuada non.
In hac habitasse platea dictumst. Quisque a diam egestas, ornare felis quis, gravida arcu. In vel tellus facilisis, rhoncus ligula sit amet, feugiat massa. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur varius interdum dolor, ut pretium augue egestas id. Aenean vulputate commodo nibh tristique egestas. Interdum et malesuada fames ac ante ipsum primis in faucibus. Vivamus elementum non mi sit amet lacinia.

15
frontend/posts/post2.md Executable file
View File

@@ -0,0 +1,15 @@
---
layout: post
title: Some other post title
author: @k_cieslak
published: 2020-02-20
---
# Something else
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi nisi diam, vehicula quis blandit id, suscipit sed libero. Proin at diam dolor. In hac habitasse platea dictumst. Donec quis dui vitae quam eleifend dignissim non sed libero. In hac habitasse platea dictumst. In ullamcorper mollis risus, a vulputate quam accumsan at. Donec sed felis sodales, blandit orci id, vulputate orci.
<!--more-->
In est nulla, ornare vitae elit sed, consequat sollicitudin dui. Duis posuere nulla malesuada elit volutpat ultricies. Mauris et tellus tortor. In ligula elit, pellentesque eget est et, mattis rhoncus nisl. Sed orci ex, mollis quis justo eu, dapibus tincidunt turpis. Sed rhoncus odio non lacus ullamcorper volutpat. Suspendisse blandit ullamcorper condimentum. Quisque et viverra nisi. Vivamus in mollis nulla. Nulla faucibus sed ligula et blandit.
Vivamus nec libero faucibus, cursus ex et, consequat mauris. Pellentesque commodo ullamcorper vestibulum. Donec efficitur, ipsum et dapibus varius, purus mauris gravida augue, eu mattis lorem turpis eget dui. Curabitur nibh erat, posuere sed eros a, blandit venenatis risus. Vestibulum cursus imperdiet ultrices. In eu efficitur dui, eget tempus enim. Nunc imperdiet, enim et sagittis lacinia, lacus metus eleifend purus, blandit pellentesque leo ante ac velit. Nam ac sagittis est. Cras accumsan, odio vel lacinia mollis, metus tortor malesuada nisi, et consectetur neque quam in erat. Sed ultricies aliquam hendrerit. Etiam non aliquam ipsum, id rutrum magna. Morbi id tincidunt mauris. Vestibulum nec iaculis massa. Etiam fringilla, orci quis faucibus vulputate, risus nibh finibus nisl, et vehicula ipsum leo a tortor. Curabitur mauris elit, bibendum vitae velit at, dignissim ornare arcu.

15
frontend/posts/post3.md Executable file
View File

@@ -0,0 +1,15 @@
---
layout: post
title: On this great day
author: @k_cieslak
published: 2020-03-20
---
# On this great day
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi nisi diam, vehicula quis blandit id, suscipit sed libero. Proin at diam dolor. In hac habitasse platea dictumst. Donec quis dui vitae quam eleifend dignissim non sed libero. In hac habitasse platea dictumst. In ullamcorper mollis risus, a vulputate quam accumsan at. Donec sed felis sodales, blandit orci id, vulputate orci.
<!--more-->
In est nulla, ornare vitae elit sed, consequat sollicitudin dui. Duis posuere nulla malesuada elit volutpat ultricies. Mauris et tellus tortor. In ligula elit, pellentesque eget est et, mattis rhoncus nisl. Sed orci ex, mollis quis justo eu, dapibus tincidunt turpis. Sed rhoncus odio non lacus ullamcorper volutpat. Suspendisse blandit ullamcorper condimentum. Quisque et viverra nisi. Vivamus in mollis nulla. Nulla faucibus sed ligula et blandit.
Vivamus nec libero faucibus, cursus ex et, consequat mauris. Pellentesque commodo ullamcorper vestibulum. Donec efficitur, ipsum et dapibus varius, purus mauris gravida augue, eu mattis lorem turpis eget dui. Curabitur nibh erat, posuere sed eros a, blandit venenatis risus. Vestibulum cursus imperdiet ultrices. In eu efficitur dui, eget tempus enim. Nunc imperdiet, enim et sagittis lacinia, lacus metus eleifend purus, blandit pellentesque leo ante ac velit. Nam ac sagittis est. Cras accumsan, odio vel lacinia mollis, metus tortor malesuada nisi, et consectetur neque quam in erat. Sed ultricies aliquam hendrerit. Etiam non aliquam ipsum, id rutrum magna. Morbi id tincidunt mauris. Vestibulum nec iaculis massa. Etiam fringilla, orci quis faucibus vulputate, risus nibh finibus nisl, et vehicula ipsum leo a tortor. Curabitur mauris elit, bibendum vitae velit at, dignissim ornare arcu.

15
frontend/posts/post4.md Executable file
View File

@@ -0,0 +1,15 @@
---
layout: post
title: We learnt
author: @k_cieslak
published: 2020-03-25
---
# We learnt
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi nisi diam, vehicula quis blandit id, suscipit sed libero. Proin at diam dolor. In hac habitasse platea dictumst. Donec quis dui vitae quam eleifend dignissim non sed libero. In hac habitasse platea dictumst. In ullamcorper mollis risus, a vulputate quam accumsan at. Donec sed felis sodales, blandit orci id, vulputate orci.
<!--more-->
In est nulla, ornare vitae elit sed, consequat sollicitudin dui. Duis posuere nulla malesuada elit volutpat ultricies. Mauris et tellus tortor. In ligula elit, pellentesque eget est et, mattis rhoncus nisl. Sed orci ex, mollis quis justo eu, dapibus tincidunt turpis. Sed rhoncus odio non lacus ullamcorper volutpat. Suspendisse blandit ullamcorper condimentum. Quisque et viverra nisi. Vivamus in mollis nulla. Nulla faucibus sed ligula et blandit.
Vivamus nec libero faucibus, cursus ex et, consequat mauris. Pellentesque commodo ullamcorper vestibulum. Donec efficitur, ipsum et dapibus varius, purus mauris gravida augue, eu mattis lorem turpis eget dui. Curabitur nibh erat, posuere sed eros a, blandit venenatis risus. Vestibulum cursus imperdiet ultrices. In eu efficitur dui, eget tempus enim. Nunc imperdiet, enim et sagittis lacinia, lacus metus eleifend purus, blandit pellentesque leo ante ac velit. Nam ac sagittis est. Cras accumsan, odio vel lacinia mollis, metus tortor malesuada nisi, et consectetur neque quam in erat. Sed ultricies aliquam hendrerit. Etiam non aliquam ipsum, id rutrum magna. Morbi id tincidunt mauris. Vestibulum nec iaculis massa. Etiam fringilla, orci quis faucibus vulputate, risus nibh finibus nisl, et vehicula ipsum leo a tortor. Curabitur mauris elit, bibendum vitae velit at, dignissim ornare arcu.

15
frontend/posts/post5.md Executable file
View File

@@ -0,0 +1,15 @@
---
layout: post
title: All about
author: @k_cieslak
published: 2020-04-21
---
# All about
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi nisi diam, vehicula quis blandit id, suscipit sed libero. Proin at diam dolor. In hac habitasse platea dictumst. Donec quis dui vitae quam eleifend dignissim non sed libero. In hac habitasse platea dictumst. In ullamcorper mollis risus, a vulputate quam accumsan at. Donec sed felis sodales, blandit orci id, vulputate orci.
<!--more-->
In est nulla, ornare vitae elit sed, consequat sollicitudin dui. Duis posuere nulla malesuada elit volutpat ultricies. Mauris et tellus tortor. In ligula elit, pellentesque eget est et, mattis rhoncus nisl. Sed orci ex, mollis quis justo eu, dapibus tincidunt turpis. Sed rhoncus odio non lacus ullamcorper volutpat. Suspendisse blandit ullamcorper condimentum. Quisque et viverra nisi. Vivamus in mollis nulla. Nulla faucibus sed ligula et blandit.
Vivamus nec libero faucibus, cursus ex et, consequat mauris. Pellentesque commodo ullamcorper vestibulum. Donec efficitur, ipsum et dapibus varius, purus mauris gravida augue, eu mattis lorem turpis eget dui. Curabitur nibh erat, posuere sed eros a, blandit venenatis risus. Vestibulum cursus imperdiet ultrices. In eu efficitur dui, eget tempus enim. Nunc imperdiet, enim et sagittis lacinia, lacus metus eleifend purus, blandit pellentesque leo ante ac velit. Nam ac sagittis est. Cras accumsan, odio vel lacinia mollis, metus tortor malesuada nisi, et consectetur neque quam in erat. Sed ultricies aliquam hendrerit. Etiam non aliquam ipsum, id rutrum magna. Morbi id tincidunt mauris. Vestibulum nec iaculis massa. Etiam fringilla, orci quis faucibus vulputate, risus nibh finibus nisl, et vehicula ipsum leo a tortor. Curabitur mauris elit, bibendum vitae velit at, dignissim ornare arcu.

15
frontend/posts/post6.md Executable file
View File

@@ -0,0 +1,15 @@
---
layout: post
title: Paging
author: @k_cieslak
published: 2020-05-01
---
# Paging
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi nisi diam, vehicula quis blandit id, suscipit sed libero. Proin at diam dolor. In hac habitasse platea dictumst. Donec quis dui vitae quam eleifend dignissim non sed libero. In hac habitasse platea dictumst. In ullamcorper mollis risus, a vulputate quam accumsan at. Donec sed felis sodales, blandit orci id, vulputate orci.
<!--more-->
In est nulla, ornare vitae elit sed, consequat sollicitudin dui. Duis posuere nulla malesuada elit volutpat ultricies. Mauris et tellus tortor. In ligula elit, pellentesque eget est et, mattis rhoncus nisl. Sed orci ex, mollis quis justo eu, dapibus tincidunt turpis. Sed rhoncus odio non lacus ullamcorper volutpat. Suspendisse blandit ullamcorper condimentum. Quisque et viverra nisi. Vivamus in mollis nulla. Nulla faucibus sed ligula et blandit.
Vivamus nec libero faucibus, cursus ex et, consequat mauris. Pellentesque commodo ullamcorper vestibulum. Donec efficitur, ipsum et dapibus varius, purus mauris gravida augue, eu mattis lorem turpis eget dui. Curabitur nibh erat, posuere sed eros a, blandit venenatis risus. Vestibulum cursus imperdiet ultrices. In eu efficitur dui, eget tempus enim. Nunc imperdiet, enim et sagittis lacinia, lacus metus eleifend purus, blandit pellentesque leo ante ac velit. Nam ac sagittis est. Cras accumsan, odio vel lacinia mollis, metus tortor malesuada nisi, et consectetur neque quam in erat. Sed ultricies aliquam hendrerit. Etiam non aliquam ipsum, id rutrum magna. Morbi id tincidunt mauris. Vestibulum nec iaculis massa. Etiam fringilla, orci quis faucibus vulputate, risus nibh finibus nisl, et vehicula ipsum leo a tortor. Curabitur mauris elit, bibendum vitae velit at, dignissim ornare arcu.

15
frontend/posts/subdir/post3.md Executable file
View File

@@ -0,0 +1,15 @@
---
layout: post
title: A post in sub-dir
author: @k_cieslak
published: 2020-04-29
---
# A post in sub-dir
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi nisi diam, vehicula quis blandit id, suscipit sed libero. Proin at diam dolor. In hac habitasse platea dictumst. Donec quis dui vitae quam eleifend dignissim non sed libero. In hac habitasse platea dictumst. In ullamcorper mollis risus, a vulputate quam accumsan at. Donec sed felis sodales, blandit orci id, vulputate orci.
<!--more-->
In est nulla, ornare vitae elit sed, consequat sollicitudin dui. Duis posuere nulla malesuada elit volutpat ultricies. Mauris et tellus tortor. In ligula elit, pellentesque eget est et, mattis rhoncus nisl. Sed orci ex, mollis quis justo eu, dapibus tincidunt turpis. Sed rhoncus odio non lacus ullamcorper volutpat. Suspendisse blandit ullamcorper condimentum. Quisque et viverra nisi. Vivamus in mollis nulla. Nulla faucibus sed ligula et blandit.
Vivamus nec libero faucibus, cursus ex et, consequat mauris. Pellentesque commodo ullamcorper vestibulum. Donec efficitur, ipsum et dapibus varius, purus mauris gravida augue, eu mattis lorem turpis eget dui. Curabitur nibh erat, posuere sed eros a, blandit venenatis risus. Vestibulum cursus imperdiet ultrices. In eu efficitur dui, eget tempus enim. Nunc imperdiet, enim et sagittis lacinia, lacus metus eleifend purus, blandit pellentesque leo ante ac velit. Nam ac sagittis est. Cras accumsan, odio vel lacinia mollis, metus tortor malesuada nisi, et consectetur neque quam in erat. Sed ultricies aliquam hendrerit. Etiam non aliquam ipsum, id rutrum magna. Morbi id tincidunt mauris. Vestibulum nec iaculis massa. Etiam fringilla, orci quis faucibus vulputate, risus nibh finibus nisl, et vehicula ipsum leo a tortor. Curabitur mauris elit, bibendum vitae velit at, dignissim ornare arcu.

View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Lib</OutputType>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="types.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FSharp.SystemTextJson" Version="1.4.36" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,75 @@
open System.Text.Json
open System.Text.Json.Serialization
module Types =
type Path = {
Alias: string
Langcode: string
}
type Uri = {
Url: string
}
type ImageMeta = {
Alt: string
Title: string
Width: string
Height: string
}
type VideoMeta = {
display: string
description: string
}
type ImageFile = {
Uri: Uri
Meta: ImageMeta
}
type VideoFile = {
Uri: Uri
Meta: VideoMeta
}
type MediaImage = {
FieldMediaImage: ImageFile
}
type MediaVideo = {
FieldMediaVideoFile: VideoFile
}
type Media =
| [<JsonName("media--image")>]
MediaImage of MediaImage
| [<JsonName("media--video")>]
MediaVideo of MediaVideo
type Hero = {
FieldTitle: string
FieldSubtitle: string
FieldHeroSize: string
FieldBackgroundImage: Media
}
type SimpleText = {
FieldBody: string
}
type Paragraph =
| [<JsonName("paragraph--hero_banner")>]
Hero of Hero
| [<JsonName("paragraph--simple_text")>]
SimpleText of SimpleText
| Ignore
type DocData = {
Type: string
Id: string
Title: string
Path: Path
FieldContent: Paragraph[]
}

73
frontend/style/style.css Executable file
View File

@@ -0,0 +1,73 @@
html,body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
font-size: 14px;
background: #F0F2F4;
}
.navbar.is-white {
background: #F0F2F4;
}
.navbar-brand .brand-text {
font-size: 1.11rem;
font-weight: bold;
}
.hero-body
{background-image: url(https://upload.wikimedia.org/wikipedia/commons/thumb/f/f6/Plum_trees_Kitano_Tenmangu.jpg/1200px-Plum_trees_Kitano_Tenmangu.jpg);
background-position: center;
background-size: cover;
background-repeat: no-repeat;
height: 500px;
}
.articles {
margin: 5rem 0;
margin-top: -200px;
}
.articles .content p {
line-height: 1.9;
margin: 15px 0;
}
.author-image {
position: absolute;
top: -30px;
left: 50%;
width: 60px;
height: 60px;
margin-left: -30px;
border: 3px solid #ccc;
border-radius: 50%;
}
.media-center {
display: block;
margin-bottom: 1rem;
}
.media-content {
margin-top: 3rem;
}
.article, .promo-block {
margin-top: 6rem;
}
div.column.is-8:first-child {
padding-top: 0;
margin-top: 0;
}
.article-title {
font-size: 2rem;
font-weight: lighter;
line-height: 2;
}
.article-subtitle {
color: #909AA0;
margin-bottom: 3rem;
}
.article-body {
line-height: 1.4;
margin: 0 6rem;
}
@media screen and (max-width: 991px) {
.article-body {
line-height: 1.4;
margin: 0;
}
}
.promo-block .container {
margin: 1rem 5rem;
}

29
patches.lock.json Normal file
View File

@@ -0,0 +1,29 @@
{
"_hash": "ef0ee84ef0e79d4bd4dfeee777cedbc5d1feff406a58ecc542c1eca8500d8da8",
"patches": {
"drupal/jsonapi_include": [
{
"package": "drupal/jsonapi_include",
"description": "Issue #3490592: Incompatile with jsonapi_default fix",
"url": "https://git.drupalcode.org/project/jsonapi_include/-/merge_requests/28.diff",
"sha256": "e1d2432d70a9b366ac2e6f2104988beac00bc3fc5cf16482a57bdb454479a308",
"depth": 1,
"extra": {
"provenance": "root"
}
}
],
"drupal/jsonapi_extras": [
{
"package": "drupal/jsonapi_extras",
"description": "Issue #3373151: Auto include default includes of related entities",
"url": "patches/jsonapi_extras_default_includes.patch",
"sha256": "75cfc0f2e7a1d0117d445cbc3e266e4320f8c9cffbb7e819bdb3d1ffe5eefe55",
"depth": 1,
"extra": {
"provenance": "root"
}
}
]
}
}

View File

@@ -0,0 +1,140 @@
diff --git i/modules/jsonapi_defaults/jsonapi_defaults.module w/modules/jsonapi_defaults/jsonapi_defaults.module
index c91b5a7..6a6d699 100644
--- i/modules/jsonapi_defaults/jsonapi_defaults.module
+++ w/modules/jsonapi_defaults/jsonapi_defaults.module
@@ -7,6 +7,7 @@
use Drupal\Core\Form\FormStateInterface;
use Drupal\jsonapi\Query\OffsetPage;
+use Drupal\jsonapi_defaults\Controller\EntityResource;
use Drupal\jsonapi_extras\Entity\JsonapiResourceConfig;
/**
@@ -61,7 +62,11 @@ function _jsonapi_defaults_form_alter(array &$form, FormStateInterface $form_sta
'#type' => 'textarea',
'#title' => 'Default include list',
'#default_value' => $includes ? implode("\n", $includes) : '',
- '#description' => t('Specify includes here (For example uid or field_image). Enter one include per line. If a request contains an "include" query string parameter this defaults will be ignored.'),
+ '#description' =>
+ t('Specify includes here (For example uid or field_image). Enter one include per line. If a request contains an "include" query string parameter this defaults will be ignored.')
+ . '<br/>' . t('You can use the <code>field_name.@keyword</code> keyword for entity reference fields to expose the default includes from the target entity.', [
+ '@keyword' => EntityResource::EXPOSE_INCLUDES_KEYWORD,
+ ]),
];
$form['bundle_wrapper']['fields_wrapper']['defaults']['default_filter'] = [
diff --git i/modules/jsonapi_defaults/src/Controller/EntityResource.php w/modules/jsonapi_defaults/src/Controller/EntityResource.php
index 392d6f6..b351011 100644
--- i/modules/jsonapi_defaults/src/Controller/EntityResource.php
+++ w/modules/jsonapi_defaults/src/Controller/EntityResource.php
@@ -10,6 +10,7 @@ use Drupal\jsonapi\Query\Sort;
use Drupal\jsonapi\ResourceType\ResourceType;
use Drupal\jsonapi_defaults\JsonapiDefaultsInterface;
use Drupal\jsonapi_extras\Entity\JsonapiResourceConfig;
+use Drupal\jsonapi_extras\ResourceType\ConfigurableResourceType;
use Symfony\Component\HttpFoundation\Request;
/**
@@ -17,6 +18,20 @@ use Symfony\Component\HttpFoundation\Request;
*/
class EntityResource extends JsonApiEntityResource {
+ /**
+ * A keyword used to expose default includes for an entity reference field.
+ *
+ * @var string
+ */
+ const EXPOSE_INCLUDES_KEYWORD = '_default_include';
+
+ /**
+ * A regular expression to detect exposing default includes keyword.
+ *
+ * @var string
+ */
+ const EXPOSE_INCLUDES_REGEXP = '#^(.+)\.' . self::EXPOSE_INCLUDES_KEYWORD . '$#';
+
/**
* The jsonapi defaults service.
*
@@ -156,6 +171,10 @@ class EntityResource extends JsonApiEntityResource {
$includes = array_unique(array_filter(array_merge($defaultIncludes)));
$request->query->set('include', implode(',', $includes));
}
+ $includes = explode(',', $request->query->get('include', ''));
+ if ($this->exposeDefaultIncludes($includes, $data)) {
+ $request->query->set('include', implode(',', $includes));
+ }
}
return parent::getIncludes($request, $data);
@@ -223,5 +242,70 @@ class EntityResource extends JsonApiEntityResource {
);
}
}
+
+ /**
+ * Gets the list of default includes from all related entities of a field.
+ *
+ * @param string $field_name
+ * A field name.
+ * @param Drupal\jsonapi_extras\ResourceType\ConfigurableResourceType $resource_type
+ * An item.
+ * @param array $includes
+ * A list of includes to extend.
+ *
+ * @return array
+ * The combined list of all default includes.
+ */
+ protected function getDefaultIncludeFromRelationField(string $field_name, ConfigurableResourceType $resource_type, array $includes = []) {
+ $field_resource = $resource_type->getFieldByInternalName($field_name);
+ $relatable_resources = $field_resource->getRelatableResourceTypes();
+ foreach ($relatable_resources as $relatable_resource) {
+ $type_name = $relatable_resource->getTypeName();
+ $related_resource_type = $this->resourceTypeRepository->getByTypeName($type_name);
+ $type_includes = $related_resource_type->getJsonapiResourceConfig()->getThirdPartySetting(
+ 'jsonapi_defaults',
+ 'default_include',
+ []
+ );
+ foreach ($type_includes as $delta => $type_include) {
+ if(preg_match(self::EXPOSE_INCLUDES_REGEXP, $type_include, $matches)) {
+ $relation_field_name = $matches[1];
+ $type_includes_relation = $this->getDefaultIncludeFromRelationField($relation_field_name, $relatable_resource);
+ foreach ($type_includes_relation as $type_include_relation) {
+ $includes[] = $field_name . '.' . $type_include_relation;
+ }
+ }
+ else {
+ $includes[] = $field_name . '.' . $type_include;
+ }
+ }
+ }
+ $includes = array_unique($includes);
+ return $includes;
+ }
+
+ /**
+ * Replaces `_default_include` to the list of includes from all the targets.
+ *
+ * @param array $includes.
+ * The list of includes.
+ * @param
+ * \Drupal\jsonapi\JsonApiResource\ResourceObject|\Drupal\jsonapi\JsonApiResource\ResourceObjectData $data
+ * The response data from which to resolve includes.
+ */
+ protected function exposeDefaultIncludes(array &$includes, $data): bool {
+ $exposed = FALSE;
+ foreach($includes as $delta => $include) {
+ if(preg_match(self::EXPOSE_INCLUDES_REGEXP, $include, $matches)) {
+ $exposed = TRUE;
+ foreach ($data as $item) {
+ unset($includes[$delta]);
+ $resource_type = $item->getResourceType();
+ $includes = $this->getDefaultIncludeFromRelationField($matches[1], $resource_type, $includes);
+ }
+ }
+ }
+ return $exposed;
+ }
}

75
web/README.md Normal file
View File

@@ -0,0 +1,75 @@
<img alt="Drupal Logo" src="https://www.drupal.org/files/Wordmark_blue_RGB.png" height="60px">
Drupal is an open source content management platform supporting a variety of
websites ranging from personal weblogs to large community-driven websites. For
more information, visit the Drupal website, [Drupal.org][Drupal.org], and join
the [Drupal community][Drupal community].
## Contributing
Drupal is developed on [Drupal.org][Drupal.org], the home of the international
Drupal community since 2001!
[Drupal.org][Drupal.org] hosts Drupal's [GitLab repository][GitLab repository],
its [issue queue][issue queue], and its [documentation][documentation]. Before
you start working on code, be sure to search the [issue queue][issue queue] and
create an issue if your aren't able to find an existing issue.
Every issue on Drupal.org automatically creates a new community-accessible fork
that you can contribute to. Learn more about the code contribution process on
the [Issue forks & merge requests page][issue forks].
## Usage
For a brief introduction, see [USAGE.txt](/core/USAGE.txt). You can also find
guides, API references, and more by visiting Drupal's [documentation
page][documentation].
You can quickly extend Drupal's core feature set by installing any of its
[thousands of free and open source modules][modules]. With Drupal and its
module ecosystem, you can often build most or all of what your project needs
before writing a single line of code.
## Changelog
Drupal keeps detailed [change records][changelog]. You can search Drupal's
changes for a record of every notable breaking change and new feature since
2011.
## Security
For a list of security announcements, see the [Security advisories
page][Security advisories] (available as [an RSS feed][security RSS]). This
page also describes how to subscribe to these announcements via email.
For information about the Drupal security process, or to find out how to report
a potential security issue to the Drupal security team, see the [Security team
page][security team].
## Need a helping hand?
Visit the [Support page][support] or browse [over a thousand Drupal
providers][service providers] offering design, strategy, development, and
hosting services.
## Legal matters
Know your rights when using Drupal by reading Drupal core's
[license](/core/LICENSE.txt).
Learn about the [Drupal trademark and logo policy here][trademark].
[Drupal.org]: https://www.drupal.org
[Drupal community]: https://www.drupal.org/community
[GitLab repository]: https://git.drupalcode.org/project/drupal
[issue queue]: https://www.drupal.org/project/issues/drupal
[issue forks]: https://www.drupal.org/drupalorg/docs/gitlab-integration/issue-forks-merge-requests
[documentation]: https://www.drupal.org/documentation
[changelog]: https://www.drupal.org/list-changes/drupal
[modules]: https://www.drupal.org/project/project_module
[security advisories]: https://www.drupal.org/security
[security RSS]: https://www.drupal.org/security/rss.xml
[security team]: https://www.drupal.org/drupal-security-team
[service providers]: https://www.drupal.org/drupal-services
[support]: https://www.drupal.org/support
[trademark]: https://www.drupal.com/trademark

View File

@@ -0,0 +1,8 @@
_core:
default_config_hash: uyQNqftluizBjDPnFYOJseLmtGK0tyiCkOyBmLkjOio
enable_toggle_shortcut: false
menu_depth: 4
sticky_behavior: enabled
hoverintent_behavior:
enabled: true
timeout: 500

View File

@@ -0,0 +1,5 @@
_core:
default_config_hash: 0G5pZBcxbg8ONYzNLd1RJIsvuFFewm9htnS4I-ABKJ8
max_age: 86400
cron_interval: 21600
limit: 10

View File

@@ -0,0 +1,3 @@
_core:
default_config_hash: fUksROt4FfkAU9BV4hV2XvhTBSS2nTNrZS4U7S-tKrs
interval: 10800

View File

@@ -0,0 +1,22 @@
uuid: daea11af-243c-42ff-94ce-aac0cd0355de
langcode: en
status: true
dependencies:
module:
- system
theme:
- claro
_core:
default_config_hash: NjcxOBrPOiK5-38t56DwFBDVY4yer7YSlbRWXFuHe7A
id: claro_breadcrumbs
theme: claro
region: breadcrumb
weight: 0
provider: null
plugin: system_breadcrumb_block
settings:
id: system_breadcrumb_block
label: Breadcrumbs
label_display: '0'
provider: system
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: 7b4cb724-62b0-40c8-82b7-dc947387a14b
langcode: en
status: true
dependencies:
module:
- system
theme:
- claro
_core:
default_config_hash: a0Yyx1GeyKarZ4T_yXQBR_ZFKnXiFLtxAb6gWLd8nr0
id: claro_content
theme: claro
region: content
weight: 0
provider: null
plugin: system_main_block
settings:
id: system_main_block
label: 'Main page content'
label_display: '0'
provider: system
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: e3c4d047-cbdc-44b3-af92-1ae0663344ef
langcode: en
status: true
dependencies:
module:
- help
theme:
- claro
_core:
default_config_hash: jccFSSVqV0WCDb6NtML1VWAWTtDbZ-zn5YgTRMgMrIM
id: claro_help
theme: claro
region: help
weight: 0
provider: null
plugin: help_block
settings:
id: help_block
label: Help
label_display: '0'
provider: help
visibility: { }

View File

@@ -0,0 +1,32 @@
uuid: fab69d58-c17d-4321-9e76-4f67b63ebe23
langcode: en
status: true
dependencies:
module:
- search
- system
theme:
- claro
enforced:
config:
- search.page.help_search
_core:
default_config_hash: 2ToeZLvlHKTeFY74gpgu1PejLoFyCECLO_gw6rAZwqw
id: claro_help_search
theme: claro
region: help
weight: -4
provider: null
plugin: search_form_block
settings:
id: search_form_block
label: 'Search help'
label_display: visible
provider: search
page_id: help_search
visibility:
request_path:
id: request_path
negate: false
context_mapping: { }
pages: /admin/help

View File

@@ -0,0 +1,20 @@
uuid: c439eb4e-6e64-4a82-abce-83b785055ad5
langcode: en
status: true
dependencies:
theme:
- claro
_core:
default_config_hash: CdXfDmRgAvms7EQovxxWPdYi0GitxeRbVtScYK16ZH0
id: claro_local_actions
theme: claro
region: content
weight: -10
provider: null
plugin: local_actions_block
settings:
id: local_actions_block
label: 'Primary admin actions'
label_display: '0'
provider: core
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: 0b43b329-9285-4c6c-a963-03ebe5990d3f
langcode: en
status: true
dependencies:
module:
- system
theme:
- claro
_core:
default_config_hash: '-Ac3ISpIT0PQ-whzD7_dw0SdKi6dAbRFNWdSjOiVDqg'
id: claro_messages
theme: claro
region: highlighted
weight: 0
provider: null
plugin: system_messages_block
settings:
id: system_messages_block
label: 'Status messages'
label_display: '0'
provider: system
visibility: { }

View File

@@ -0,0 +1,20 @@
uuid: 4017dd8a-e65c-428f-9c51-1ce030be7014
langcode: en
status: true
dependencies:
theme:
- claro
_core:
default_config_hash: fNwDdW063tk_ktzSWzZVeQS9wzvLooVO280BQ9WrsIs
id: claro_page_title
theme: claro
region: header
weight: -30
provider: null
plugin: page_title_block
settings:
id: page_title_block
label: 'Page title'
label_display: '0'
provider: core
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: d9cbe80d-5e97-46b3-98ac-d07fb6e2d8b1
langcode: en
status: true
dependencies:
theme:
- claro
_core:
default_config_hash: ACjBZI5shAMiiUpsz-inLYVXDqNNXRnSzAWV3kV_8Hw
id: claro_primary_local_tasks
theme: claro
region: header
weight: 0
provider: null
plugin: local_tasks_block
settings:
id: local_tasks_block
label: 'Primary tabs'
label_display: '0'
provider: core
primary: true
secondary: false
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: 448c1333-0404-4a34-96e0-f95be42ef581
langcode: en
status: true
dependencies:
theme:
- claro
_core:
default_config_hash: 2L0geP-ixCbCkEpW6BVF6H7vDUZN4ea07_Y9CociQm4
id: claro_secondary_local_tasks
theme: claro
region: pre_content
weight: 0
provider: null
plugin: local_tasks_block
settings:
id: local_tasks_block
label: 'Secondary tabs'
label_display: '0'
provider: core
primary: false
secondary: true
visibility: { }

View File

@@ -0,0 +1,27 @@
uuid: ef0bbe55-2ebb-4ef7-b62a-65bebe57e68e
langcode: en
status: true
dependencies:
config:
- system.menu.account
module:
- system
theme:
- olivero
_core:
default_config_hash: gmxYWWHmgbe0Pnv8y48ZLSLH5mEHejOjAP6RLxUfdzU
id: olivero_account_menu
theme: olivero
region: secondary_menu
weight: -4
provider: null
plugin: 'system_menu_block:account'
settings:
id: 'system_menu_block:account'
label: 'User account menu'
label_display: '0'
provider: system
level: 1
depth: 1
expand_all_items: false
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: d0a5c7af-c722-4d6f-aa62-ddf10d8a54c5
langcode: en
status: true
dependencies:
module:
- system
theme:
- olivero
_core:
default_config_hash: VhBzWb7lMRtIOg9G7VSw_0uopi-7zXeHq4vXqqV1HFE
id: olivero_breadcrumbs
theme: olivero
region: breadcrumb
weight: 0
provider: null
plugin: system_breadcrumb_block
settings:
id: system_breadcrumb_block
label: Breadcrumbs
label_display: '0'
provider: system
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: cd2b11fc-d1ae-455e-8523-bd0918ed9841
langcode: en
status: true
dependencies:
module:
- system
theme:
- olivero
_core:
default_config_hash: erQSEZF2XUjNmgTl0uNRBzmg18ZGXwUcw2FhApoeuHk
id: olivero_content
theme: olivero
region: content
weight: 0
provider: null
plugin: system_main_block
settings:
id: system_main_block
label: 'Main page content'
label_display: '0'
provider: system
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: 3b694649-8c29-4ca3-8a6e-149476a6fc94
langcode: en
status: true
dependencies:
module:
- help
theme:
- olivero
_core:
default_config_hash: VfPFqqxfkomud5CO8DUijw85QIl9GIxh_nIxLOYESxg
id: olivero_help
theme: olivero
region: content_above
weight: 0
provider: null
plugin: help_block
settings:
id: help_block
label: Help
label_display: '0'
provider: help
visibility: { }

View File

@@ -0,0 +1,27 @@
uuid: 1bacc21c-50eb-41ec-8bac-10c35feeabea
langcode: en
status: true
dependencies:
config:
- system.menu.main
module:
- system
theme:
- olivero
_core:
default_config_hash: KWAiziL39uEzmOJEql_wbUP2RtqGceL3WM2CfxhMelE
id: olivero_main_menu
theme: olivero
region: primary_menu
weight: 0
provider: null
plugin: 'system_menu_block:main'
settings:
id: 'system_menu_block:main'
label: 'Main navigation'
label_display: '0'
provider: system
level: 1
depth: 2
expand_all_items: true
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: 2fd80184-c38b-45e6-9bc4-a3eaea8f8713
langcode: en
status: true
dependencies:
module:
- system
theme:
- olivero
_core:
default_config_hash: BZ5tpW7H8X4PVGRm3MImTIHd2tN0eF7zOtp4SpRYUA0
id: olivero_messages
theme: olivero
region: highlighted
weight: -5
provider: null
plugin: system_messages_block
settings:
id: system_messages_block
label: 'Status messages'
label_display: '0'
provider: system
visibility: { }

View File

@@ -0,0 +1,20 @@
uuid: cd522704-4ce3-4fec-97cb-9500e606b070
langcode: en
status: true
dependencies:
theme:
- olivero
_core:
default_config_hash: 6aOgWsNTXjqrDm98TXSAjP6qd2nCijD1xw45MrnbK-Y
id: olivero_page_title
theme: olivero
region: content_above
weight: -5
provider: null
plugin: page_title_block
settings:
id: page_title_block
label: 'Page title'
label_display: '0'
provider: core
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: a1226f3d-6cdf-4046-8170-2b79ff35e63f
langcode: en
status: true
dependencies:
module:
- system
theme:
- olivero
_core:
default_config_hash: eYL19CLDyinGTWYQfBD1DswWzglEotE_kHnHx3AxTXM
id: olivero_powered
theme: olivero
region: footer_bottom
weight: 0
provider: null
plugin: system_powered_by_block
settings:
id: system_powered_by_block
label: 'Powered by Drupal'
label_display: '0'
provider: system
visibility: { }

View File

@@ -0,0 +1,20 @@
uuid: 7cbb24e5-49a4-4f89-a3cb-0affac6c0962
langcode: en
status: true
dependencies:
theme:
- olivero
_core:
default_config_hash: Q9_2whdOj1YIomfvsIfopROW4FT_X5pY0DjdOiOaQ5U
id: olivero_primary_admin_actions
theme: olivero
region: highlighted
weight: -5
provider: null
plugin: local_actions_block
settings:
id: local_actions_block
label: 'Primary admin actions'
label_display: '0'
provider: core
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: 219c53b3-a686-4fef-909c-5d61c0fb21c8
langcode: en
status: true
dependencies:
theme:
- olivero
_core:
default_config_hash: nGE3EoPQQaQCuqTUtZgw0-KIzmrqdKDzdNQf2JyPUt4
id: olivero_primary_local_tasks
theme: olivero
region: highlighted
weight: -4
provider: null
plugin: local_tasks_block
settings:
id: local_tasks_block
label: 'Primary tabs'
label_display: '0'
provider: core
primary: true
secondary: false
visibility: { }

View File

@@ -0,0 +1,23 @@
uuid: 913ebf26-b34e-492c-b120-2aa555495ba8
langcode: en
status: true
dependencies:
module:
- search
theme:
- olivero
_core:
default_config_hash: _nZjxxdypO6xrOAJkCYD81v0L7wh2zbCAVO7_C-UKIc
id: olivero_search_form_narrow
theme: olivero
region: primary_menu
weight: -4
provider: null
plugin: search_form_block
settings:
id: search_form_block
label: 'Search form (narrow)'
label_display: '0'
provider: search
page_id: null
visibility: { }

View File

@@ -0,0 +1,23 @@
uuid: ec7bbe47-91bd-4663-ae21-76883a8da56a
langcode: en
status: true
dependencies:
module:
- search
theme:
- olivero
_core:
default_config_hash: pbbed0hdqGDF-_QWVVTWRAwgDIotFuAvWH5mWUZu0fA
id: olivero_search_form_wide
theme: olivero
region: secondary_menu
weight: -5
provider: null
plugin: search_form_block
settings:
id: search_form_block
label: 'Search form (wide)'
label_display: '0'
provider: search
page_id: null
visibility: { }

View File

@@ -0,0 +1,22 @@
uuid: fa6299a9-fb51-4838-8cf6-40743e4729d5
langcode: en
status: true
dependencies:
theme:
- olivero
_core:
default_config_hash: ydSxdq7R66I8UMC460rOzlfzvlUL4VRbdwc6z9DWaUI
id: olivero_secondary_local_tasks
theme: olivero
region: highlighted
weight: -2
provider: null
plugin: local_tasks_block
settings:
id: local_tasks_block
label: 'Secondary tabs'
label_display: '0'
provider: core
primary: false
secondary: true
visibility: { }

View File

@@ -0,0 +1,25 @@
uuid: f9d7e643-9a2f-40b1-b297-0c216617774a
langcode: en
status: true
dependencies:
module:
- system
theme:
- olivero
_core:
default_config_hash: '-OAAZDw1OR_UyAEPEKX0Hu4LaZD149vW9PmMnIC-v0o'
id: olivero_site_branding
theme: olivero
region: header
weight: 0
provider: null
plugin: system_branding_block
settings:
id: system_branding_block
label: 'Site branding'
label_display: '0'
provider: system
use_site_logo: true
use_site_name: true
use_site_slogan: true
visibility: { }

View File

@@ -0,0 +1,10 @@
uuid: 9565e777-64e0-47f6-b185-93c232f33a82
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: pQP5iQy4SdhAMVcjDUncCfkJmTofnHVtXrsMzx4k6Yk
id: basic
label: 'Basic block'
revision: false
description: 'A basic block contains a title and a body.'

View File

@@ -0,0 +1,3 @@
third_party_settings:
shortcut:
module_link: true

View File

@@ -0,0 +1,3 @@
_core:
default_config_hash: YNUW2Ij5uE7a4oaXp3i_2lvaFdYM1zNKPPfnEjB0jEc
log_ip_addresses: false

View File

@@ -0,0 +1,10 @@
uuid: ff3962f1-e900-4b97-a79e-a8f6eefd59a0
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: bqZsN31T2n0UjcbyCpOPi9D2iO0sAOHR7FnEs9qMvaA
id: comment
label: 'Default comments'
target_entity_type_id: node
description: 'Allows commenting on content'

View File

@@ -0,0 +1,14 @@
uuid: d01574c0-a5c7-4d2d-a408-1d8a5d0b8ff6
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: vymHlgJy26BuI5GGj9-IXjwR3dRC5C0tij4BpWJnoqw
id: feedback
label: 'Website feedback'
recipients:
- admin@example.com
reply: ''
weight: 0
message: 'Your message has been sent.'
redirect: ''

View File

@@ -0,0 +1,13 @@
uuid: 31c1005c-7615-4300-8b78-8a2aa0f25ff5
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: jonvgt3CkUM2eMLTFwWfHileWWDC4YtXCuIlCahTk_I
id: personal
label: 'Personal contact form'
recipients: { }
reply: ''
weight: 0
message: 'Your message has been sent.'
redirect: ''

View File

@@ -0,0 +1,7 @@
_core:
default_config_hash: U69DBeuvXuNVOC15rVNaBjDPK2fWFbo9v4takdYSSO8
default_form: feedback
flood:
limit: 5
interval: 3600
user_default_enabled: true

View File

@@ -0,0 +1,24 @@
uuid: 7395ac45-667a-4abd-9b97-0d18b2aa0553
langcode: en
status: true
dependencies:
config:
- node.type.page
_core:
default_config_hash: fPUEnm4T5zfZRr3ttDUqq7yCDd2uW3clWD-pvos4tlQ
id: node.page.promote
field_name: promote
entity_type: node
bundle: page
label: 'Promoted to front page'
description: ''
required: false
translatable: false
default_value:
-
value: 0
default_value_callback: ''
settings:
on_label: 'On'
off_label: 'Off'
field_type: boolean

View File

@@ -0,0 +1,10 @@
uuid: bdb911f2-3966-4bcf-b1c8-199ca2ea26d7
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: iIBLu1j9n6Oo5PW-wpu5gdyNs9Kvv4LMRqtQUdJjRz8
id: fallback
label: 'Fallback date format'
locked: true
pattern: 'D, j M Y - H:i'

View File

@@ -0,0 +1,10 @@
uuid: c3954127-1e6b-4712-94a8-712164e253ee
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: EOQltUQPmgc6UQ2rcJ4Xi_leCEJj5ui0TR-12duS-Tk
id: html_date
label: 'HTML Date'
locked: true
pattern: Y-m-d

View File

@@ -0,0 +1,10 @@
uuid: a364d96b-cb1d-4998-9329-f8104329b231
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: jxfClwZIRXIdcvMrE--WkcZxDGUVoOIE3Sm2NRZlFuE
id: html_datetime
label: 'HTML Datetime'
locked: true
pattern: 'Y-m-d\TH:i:sO'

View File

@@ -0,0 +1,10 @@
uuid: f93bad1f-10bc-4d05-a5ec-e5ccbcee4616
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: Z7KuCUwM_WdTNvLcoltuX3_8d-s-8FZkTN6KgNwF0eM
id: html_month
label: 'HTML Month'
locked: true
pattern: Y-m

View File

@@ -0,0 +1,10 @@
uuid: 9e94c358-aebe-4fcc-9d59-2d0365f52a40
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: M7yqicYkU36hRy5p9drAaGBBihhUD1OyujFrAaQ93ZE
id: html_time
label: 'HTML Time'
locked: true
pattern: 'H:i:s'

View File

@@ -0,0 +1,10 @@
uuid: 95af0b31-5e0c-4a44-ac05-8cf1e88fab37
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: wKD4WsoV_wFgv2vgI4mcAAFSIzrye17ykzdwrnApkfY
id: html_week
label: 'HTML Week'
locked: true
pattern: Y-\WW

View File

@@ -0,0 +1,10 @@
uuid: 1f5c8607-76da-4117-a680-8d6cc98e847c
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: OjekiQuX9RbVQ2_8jOHBL94RgYLePqX7wpfNGgcQzrk
id: html_year
label: 'HTML Year'
locked: true
pattern: 'Y'

View File

@@ -0,0 +1,10 @@
uuid: a2740dbc-5ee4-4db6-95f7-fc8a830674d7
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: 5VpawMrKPEPCkoO4YpPa0TDFO2dgiIHfTziJtwlmUxc
id: html_yearless_date
label: 'HTML Yearless date'
locked: true
pattern: m-d

View File

@@ -0,0 +1,10 @@
uuid: c8245d96-867c-4429-af93-5fba23a79fbc
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: 5B4_r5Vd0_9UaJwtAC5yFCm9-k8NNvp1xiQNhFFkknU
id: long
label: 'Default long date'
locked: false
pattern: 'l, j F Y - H:i'

View File

@@ -0,0 +1,10 @@
uuid: 319dc20d-08c3-46b5-af32-bee52fc00542
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: q7pDV2d9qFh1IVqvymOxUUYGSziZDeg961wURC0cSLs
id: medium
label: 'Default medium date'
locked: false
pattern: 'D, j M Y - H:i'

View File

@@ -0,0 +1,13 @@
uuid: a0fbcc38-0350-4957-9a87-5f6d14e8ca98
langcode: en
status: true
dependencies:
enforced:
theme:
- olivero
_core:
default_config_hash: z7ynTCss9wwEi8ojENJ08qx44RN6leI-tqoN2o5QzdE
id: olivero_medium
label: 'Olivero Medium'
locked: false
pattern: 'j F Y'

View File

@@ -0,0 +1,10 @@
uuid: b5015ace-a72f-40fe-9c7c-fd1e840ccee4
langcode: en
status: true
dependencies: { }
_core:
default_config_hash: SAeixlV7Djy_Ggv_1P95TiqD4KUihA5icvU521tA84Y
id: short
label: 'Default short date'
locked: false
pattern: 'j M Y - H:i'

View File

@@ -0,0 +1,35 @@
uuid: c09d3377-22a6-4d59-bf1d-21b02c671188
langcode: en
status: true
dependencies:
config:
- block_content.type.basic
- field.field.block_content.basic.body
module:
- text
_core:
default_config_hash: jAps3FCxvKecABS_tgExbhCZrBLQB3bNPWw18WjE3ss
id: block_content.basic.default
targetEntityType: block_content
bundle: basic
mode: default
content:
body:
type: text_textarea_with_summary
weight: -4
region: content
settings:
rows: 9
summary_rows: 3
placeholder: ''
show_summary: false
third_party_settings: { }
info:
type: string_textfield
weight: -5
region: content
settings:
size: 60
placeholder: ''
third_party_settings: { }
hidden: { }

View File

@@ -0,0 +1,36 @@
uuid: d7a1bff6-28d7-417b-97f1-248111da06e8
langcode: en
status: true
dependencies:
config:
- comment.type.comment
- field.field.comment.comment.comment_body
module:
- text
_core:
default_config_hash: I0Pa0aQvT_jawlPo9oz4FE3h_ickc55dYKTPl6gILes
id: comment.comment.default
targetEntityType: comment
bundle: comment
mode: default
content:
author:
weight: -2
region: content
comment_body:
type: text_textarea
weight: 11
region: content
settings:
rows: 5
placeholder: ''
third_party_settings: { }
subject:
type: string_textfield
weight: 10
region: content
settings:
size: 60
placeholder: ''
third_party_settings: { }
hidden: { }

View File

@@ -0,0 +1,55 @@
uuid: b4f1d47f-d5de-4d78-8cb4-01026f404cd4
langcode: en
status: true
dependencies:
config:
- field.field.media.audio.field_media_audio_file
- media.type.audio
module:
- file
- path
_core:
default_config_hash: G2_SKH3jmI9FQeXSUxo3KgQqiyF1hPDEkc7-3-rCSbc
id: media.audio.default
targetEntityType: media
bundle: audio
mode: default
content:
created:
type: datetime_timestamp
weight: 10
region: content
settings: { }
third_party_settings: { }
field_media_audio_file:
type: file_generic
weight: 0
region: content
settings:
progress_indicator: throbber
third_party_settings: { }
path:
type: path
weight: 30
region: content
settings: { }
third_party_settings: { }
status:
type: boolean_checkbox
weight: 100
region: content
settings:
display_label: true
third_party_settings: { }
uid:
type: entity_reference_autocomplete
weight: 5
region: content
settings:
match_operator: CONTAINS
match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
hidden:
name: true

View File

@@ -0,0 +1,22 @@
uuid: 85e9b8ae-b346-4cf1-b403-7b8fa82a1a27
langcode: en
status: true
dependencies:
config:
- core.entity_form_mode.media.media_library
- field.field.media.audio.field_media_audio_file
- media.type.audio
_core:
default_config_hash: 28vwMIYtvyjPcD4RyciZXIztxtZgmuWRCNgYemr_SZE
id: media.audio.media_library
targetEntityType: media
bundle: audio
mode: media_library
content: { }
hidden:
created: true
field_media_audio_file: true
name: true
path: true
status: true
uid: true

View File

@@ -0,0 +1,55 @@
uuid: 06215e61-b277-408e-80df-86bdbcc2481c
langcode: en
status: true
dependencies:
config:
- field.field.media.document.field_media_document
- media.type.document
module:
- file
- path
_core:
default_config_hash: aewrRkePgJzdD5kPOq8JeMcKHs6yat49nE7ZeCQzQZg
id: media.document.default
targetEntityType: media
bundle: document
mode: default
content:
created:
type: datetime_timestamp
weight: 10
region: content
settings: { }
third_party_settings: { }
field_media_document:
type: file_generic
weight: 0
region: content
settings:
progress_indicator: throbber
third_party_settings: { }
path:
type: path
weight: 30
region: content
settings: { }
third_party_settings: { }
status:
type: boolean_checkbox
weight: 100
region: content
settings:
display_label: true
third_party_settings: { }
uid:
type: entity_reference_autocomplete
weight: 5
region: content
settings:
match_operator: CONTAINS
match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
hidden:
name: true

View File

@@ -0,0 +1,22 @@
uuid: 84eefd83-e8a7-474d-889f-2c9203a9f1e1
langcode: en
status: true
dependencies:
config:
- core.entity_form_mode.media.media_library
- field.field.media.document.field_media_document
- media.type.document
_core:
default_config_hash: dcpfpqyLXOSGpulacMAJW3H-G34_LeNsjdfxd1_oCfY
id: media.document.media_library
targetEntityType: media
bundle: document
mode: media_library
content: { }
hidden:
created: true
field_media_document: true
name: true
path: true
status: true
uid: true

View File

@@ -0,0 +1,57 @@
uuid: 74fdf008-ca9b-4896-a13d-64378252926d
langcode: en
status: true
dependencies:
config:
- field.field.media.image.field_media_image
- image.style.thumbnail
- media.type.image
module:
- image
- path
_core:
default_config_hash: JSY4-JPyNZBiYYo6imdRYF6_SdtWQexPndrLvn3-vw4
id: media.image.default
targetEntityType: media
bundle: image
mode: default
content:
created:
type: datetime_timestamp
weight: 10
region: content
settings: { }
third_party_settings: { }
field_media_image:
type: image_image
weight: 0
region: content
settings:
progress_indicator: throbber
preview_image_style: thumbnail
third_party_settings: { }
path:
type: path
weight: 30
region: content
settings: { }
third_party_settings: { }
status:
type: boolean_checkbox
weight: 100
region: content
settings:
display_label: true
third_party_settings: { }
uid:
type: entity_reference_autocomplete
weight: 5
region: content
settings:
match_operator: CONTAINS
match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
hidden:
name: true

View File

@@ -0,0 +1,32 @@
uuid: 7b37a82d-1f42-4dbe-be5e-940a85822340
langcode: en
status: true
dependencies:
config:
- core.entity_form_mode.media.media_library
- field.field.media.image.field_media_image
- image.style.thumbnail
- media.type.image
module:
- image
_core:
default_config_hash: BMLrK4zKp8-FFnMseBdT_6h6YipUsKRfbDf_3WUB5HA
id: media.image.media_library
targetEntityType: media
bundle: image
mode: media_library
content:
field_media_image:
type: image_image
weight: 1
region: content
settings:
progress_indicator: throbber
preview_image_style: thumbnail
third_party_settings: { }
hidden:
created: true
name: true
path: true
status: true
uid: true

View File

@@ -0,0 +1,56 @@
uuid: 732267a5-5251-4966-8e8d-14480af797cf
langcode: en
status: true
dependencies:
config:
- field.field.media.remote_video.field_media_oembed_video
- media.type.remote_video
module:
- media
- path
_core:
default_config_hash: pM8mGlwfpvfG_y5tZn0lGAXFLXz2_yKkL7MvWZsRqdA
id: media.remote_video.default
targetEntityType: media
bundle: remote_video
mode: default
content:
created:
type: datetime_timestamp
weight: 10
region: content
settings: { }
third_party_settings: { }
field_media_oembed_video:
type: oembed_textfield
weight: 0
region: content
settings:
size: 60
placeholder: ''
third_party_settings: { }
path:
type: path
weight: 30
region: content
settings: { }
third_party_settings: { }
status:
type: boolean_checkbox
weight: 100
region: content
settings:
display_label: true
third_party_settings: { }
uid:
type: entity_reference_autocomplete
weight: 5
region: content
settings:
match_operator: CONTAINS
match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
hidden:
name: true

View File

@@ -0,0 +1,22 @@
uuid: 163d2ce1-4f56-472c-843d-7cab4a09ca79
langcode: en
status: true
dependencies:
config:
- core.entity_form_mode.media.media_library
- field.field.media.remote_video.field_media_oembed_video
- media.type.remote_video
_core:
default_config_hash: TBgPW-uaXRaICBwLaVc16rXpRiLSknDIdF9q0XL7qso
id: media.remote_video.media_library
targetEntityType: media
bundle: remote_video
mode: media_library
content: { }
hidden:
created: true
field_media_oembed_video: true
name: true
path: true
status: true
uid: true

View File

@@ -0,0 +1,55 @@
uuid: 24641f71-f894-47f8-8320-21f2f9b3bfe1
langcode: en
status: true
dependencies:
config:
- field.field.media.video.field_media_video_file
- media.type.video
module:
- file
- path
_core:
default_config_hash: 0kIIaDTt6dixXy8TZkat2MNGZJ6vkRG8TaBWTy3E1bM
id: media.video.default
targetEntityType: media
bundle: video
mode: default
content:
created:
type: datetime_timestamp
weight: 10
region: content
settings: { }
third_party_settings: { }
field_media_video_file:
type: file_generic
weight: 0
region: content
settings:
progress_indicator: throbber
third_party_settings: { }
path:
type: path
weight: 30
region: content
settings: { }
third_party_settings: { }
status:
type: boolean_checkbox
weight: 100
region: content
settings:
display_label: true
third_party_settings: { }
uid:
type: entity_reference_autocomplete
weight: 5
region: content
settings:
match_operator: CONTAINS
match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
hidden:
name: true

View File

@@ -0,0 +1,22 @@
uuid: eaa20ed4-3d89-454e-98f7-9f9606bdee9a
langcode: en
status: true
dependencies:
config:
- core.entity_form_mode.media.media_library
- field.field.media.video.field_media_video_file
- media.type.video
_core:
default_config_hash: kGv8YsopqHvzTzb7QTINWcv0fnNa5ZDQyZxpOQR2vro
id: media.video.media_library
targetEntityType: media
bundle: video
mode: media_library
content: { }
hidden:
created: true
field_media_video_file: true
name: true
path: true
status: true
uid: true

View File

@@ -0,0 +1,109 @@
uuid: ebc5f4e3-5d4a-4e71-a0bc-7a78aeea9b8b
langcode: en
status: true
dependencies:
config:
- field.field.node.article.body
- field.field.node.article.comment
- field.field.node.article.field_image
- field.field.node.article.field_tags
- image.style.thumbnail
- node.type.article
module:
- comment
- image
- path
- text
_core:
default_config_hash: ewbd6G2uX456-bgwseM2Q-KQG3RkASoyHmTh-XR3oLU
id: node.article.default
targetEntityType: node
bundle: article
mode: default
content:
body:
type: text_textarea_with_summary
weight: 2
region: content
settings:
rows: 9
summary_rows: 3
placeholder: ''
show_summary: false
third_party_settings: { }
comment:
type: comment_default
weight: 20
region: content
settings: { }
third_party_settings: { }
created:
type: datetime_timestamp
weight: 10
region: content
settings: { }
third_party_settings: { }
field_image:
type: image_image
weight: 1
region: content
settings:
progress_indicator: throbber
preview_image_style: thumbnail
third_party_settings: { }
field_tags:
type: entity_reference_autocomplete_tags
weight: 3
region: content
settings:
match_operator: CONTAINS
match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
path:
type: path
weight: 30
region: content
settings: { }
third_party_settings: { }
promote:
type: boolean_checkbox
weight: 15
region: content
settings:
display_label: true
third_party_settings: { }
status:
type: boolean_checkbox
weight: 120
region: content
settings:
display_label: true
third_party_settings: { }
sticky:
type: boolean_checkbox
weight: 16
region: content
settings:
display_label: true
third_party_settings: { }
title:
type: string_textfield
weight: 0
region: content
settings:
size: 60
placeholder: ''
third_party_settings: { }
uid:
type: entity_reference_autocomplete
weight: 5
region: content
settings:
match_operator: CONTAINS
match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
hidden: { }

View File

@@ -0,0 +1,87 @@
uuid: 6921be2c-e89c-414a-9a29-1488582547af
langcode: en
status: true
dependencies:
config:
- field.field.node.page.field_content
- node.type.page
module:
- paragraphs
- path
_core:
default_config_hash: SfpLhPExzvR0MgFp0Wp7CrmgEnhcqQ-fXIWFhbf4ue0
id: node.page.default
targetEntityType: node
bundle: page
mode: default
content:
created:
type: datetime_timestamp
weight: 10
region: content
settings: { }
third_party_settings: { }
field_content:
type: paragraphs
weight: 121
region: content
settings:
title: Paragraph
title_plural: Paragraphs
edit_mode: open
closed_mode: summary
autocollapse: none
closed_mode_threshold: 0
add_mode: dropdown
form_display_mode: default
default_paragraph_type: ''
features:
collapse_edit_all: collapse_edit_all
duplicate: duplicate
third_party_settings: { }
path:
type: path
weight: 30
region: content
settings: { }
third_party_settings: { }
promote:
type: boolean_checkbox
weight: 15
region: content
settings:
display_label: true
third_party_settings: { }
status:
type: boolean_checkbox
weight: 120
region: content
settings:
display_label: true
third_party_settings: { }
sticky:
type: boolean_checkbox
weight: 16
region: content
settings:
display_label: true
third_party_settings: { }
title:
type: string_textfield
weight: -5
region: content
settings:
size: 60
placeholder: ''
third_party_settings: { }
uid:
type: entity_reference_autocomplete
weight: 5
region: content
settings:
match_operator: CONTAINS
match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
hidden: { }

View File

@@ -0,0 +1,102 @@
uuid: d294dc7b-03f3-43bd-9066-81d5df2405cc
langcode: en
status: true
dependencies:
config:
- field.field.paragraph.hero_banner.field_background_image
- field.field.paragraph.hero_banner.field_hero_size
- field.field.paragraph.hero_banner.field_subtitle
- field.field.paragraph.hero_banner.field_title
- paragraphs.paragraphs_type.hero_banner
module:
- field_group
- media_library
third_party_settings:
field_group:
group_tabs:
children:
- group_content
- group_display
label: Tabs
region: content
parent_name: ''
weight: 0
format_type: tabs
format_settings:
classes: ''
show_empty_fields: false
id: ''
label_as_html: false
direction: horizontal
width_breakpoint: 640
group_display:
children:
- field_hero_size
label: Display
region: content
parent_name: group_tabs
weight: 11
format_type: tab
format_settings:
classes: ''
show_empty_fields: false
id: ''
label_as_html: false
formatter: closed
description: ''
required_fields: true
group_content:
children:
- field_title
- field_subtitle
- field_background_image
label: Content
region: content
parent_name: group_tabs
weight: 10
format_type: tab
format_settings:
classes: ''
show_empty_fields: false
id: ''
label_as_html: false
formatter: closed
description: ''
required_fields: true
id: paragraph.hero_banner.default
targetEntityType: paragraph
bundle: hero_banner
mode: default
content:
field_background_image:
type: media_library_widget
weight: 3
region: content
settings:
media_types: { }
third_party_settings: { }
field_hero_size:
type: options_select
weight: 4
region: content
settings: { }
third_party_settings: { }
field_subtitle:
type: string_textfield
weight: 2
region: content
settings:
size: 60
placeholder: ''
third_party_settings: { }
field_title:
type: string_textfield
weight: 1
region: content
settings:
size: 60
placeholder: ''
third_party_settings: { }
hidden:
created: true
status: true

View File

@@ -0,0 +1,25 @@
uuid: aabbc05e-d010-40e3-ae73-67b390cf7c86
langcode: en
status: true
dependencies:
config:
- field.field.paragraph.simple_text.field_body
- paragraphs.paragraphs_type.simple_text
module:
- text
id: paragraph.simple_text.default
targetEntityType: paragraph
bundle: simple_text
mode: default
content:
field_body:
type: text_textarea
weight: 0
region: content
settings:
rows: 5
placeholder: ''
third_party_settings: { }
hidden:
created: true
status: true

Some files were not shown because too many files have changed in this diff Show More