diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..7e1663a --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/_hugo-site/.browserslistrc b/_hugo-site/.browserslistrc new file mode 100644 index 0000000..b4e0f56 --- /dev/null +++ b/_hugo-site/.browserslistrc @@ -0,0 +1,2 @@ +> 0.5% +last 2 versions diff --git a/_hugo-site/.gitignore b/_hugo-site/.gitignore new file mode 100644 index 0000000..5aee146 --- /dev/null +++ b/_hugo-site/.gitignore @@ -0,0 +1,28 @@ +# Hugo cache files +/resources +public + +# Cache folder for Hugo Modules +_vendor + +# Node modules +node_modules + +# Used to control concurrency between multiple Hugo instances +.hugo_build.lock + +# Needed for navigation/intellisense help inside code editors +jsconfig.json + +# IntelliJ IDEA modules and interim config files +*.iml +.idea/*.xml +.idea/.name +.idea/artifacts +.idea/libraries +.idea/modules +.idea/shelf + +!.idea/misc.xml +!.idea/codeStyles/ +!.idea/copyright/ diff --git a/_hugo-site/assets/scss/docs/_home.scss b/_hugo-site/assets/scss/docs/_home.scss new file mode 100644 index 0000000..dbf6332 --- /dev/null +++ b/_hugo-site/assets/scss/docs/_home.scss @@ -0,0 +1,64 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.home { + background-color: $body-light-gray-color; + font-family: $main-font; + + .container { + background-color: white; + border: 1px solid #e6ecf1; + max-width: 760px; + padding: 48px 56px; + + @media (max-width: $phone-medium) { + padding: 24px; + } + + h1 { + font-size: $font-size--xxxl; + font-weight: 300; + color: rgba(0, 0, 0, .4); + line-height: 1.2; + margin-bottom: 32px; + padding-top: 16px; + + @media (max-width: $phone-medium) { + font-size: $font-size--xl; + } + } + + a { + color: $main-brand-color; + } + + .subtle { + color: rgba(0, 0, 0, .46); + margin-top: 40px; + font-size: 14px; + } + } +} diff --git a/_hugo-site/assets/scss/docs/_layout.scss b/_hugo-site/assets/scss/docs/_layout.scss new file mode 100644 index 0000000..18526b4 --- /dev/null +++ b/_hugo-site/assets/scss/docs/_layout.scss @@ -0,0 +1,33 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.page-content { + .three-column { + .sticky-col { + top: 0; + } + } +} diff --git a/_hugo-site/assets/scss/main.scss b/_hugo-site/assets/scss/main.scss new file mode 100644 index 0000000..f687a3b --- /dev/null +++ b/_hugo-site/assets/scss/main.scss @@ -0,0 +1,36 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import "node_modules/bootstrap/scss/bootstrap"; + +@import "docs-common"; +@import "docs"; + +// Styles that should only be used to build this site. +// They should not be imported into the main spine.io site +// to not override or duplicate styles there. +@import "docs/home"; +@import "docs/layout"; diff --git a/_hugo-site/config/_default/hugo.toml b/_hugo-site/config/_default/hugo.toml new file mode 100644 index 0000000..1a87dd8 --- /dev/null +++ b/_hugo-site/config/_default/hugo.toml @@ -0,0 +1,47 @@ +baseURL = 'https://spine.io/' +languageCode = 'en-us' +title = 'Documentation preview' + +[module] + # First theme has higher priority than later ones. + [[module.imports]] + path = '../../_hugo-theme' + [[module.imports]] + path = 'github.com/TeamDev-Ltd/site-commons' + +# Enables HTML rendering in markdown files. +[markup] + [markup.goldmark] + [markup.goldmark.renderer] + unsafe = true + [markup.highlight] + noClasses = false + +# Version control config. +# To change the current main version, update only the `path` parameter. +# Read more in the `SPINE_RELEASE.md` guide. +# +# The same settings should be copied to the `SpineEventEngine/SpineEventEngine.github.io` +# project due to the issue with the cascade arrays: +# https://github.com/gohugoio/hugo/issues/13869 +[[cascade]] + [cascade.params] + url = 'docs/' + [cascade.target] + # The path to the `_index.md` of the current main version. + path = '{/docs/1}' + kind = 'section' +[[cascade]] + [cascade.params] + url = 'docs/:sections[2:]/' + [cascade.target] + # The path to the current main version. + path = '{/docs/1/**}' + kind = 'section' +[[cascade]] + [cascade.params] + url = 'docs/:sections[2:]/:contentbasename/' + [cascade.target] + # The path to the current main version. + path = '{/docs/1/**}' + kind = 'page' diff --git a/_hugo-site/content/_index.md b/_hugo-site/content/_index.md new file mode 100644 index 0000000..a48fb5a --- /dev/null +++ b/_hugo-site/content/_index.md @@ -0,0 +1,14 @@ +--- +title: Documentation preview +--- + +# Welcome to Spine Documentation + +Go to the [documentation section](docs/). + +Read a [guide][authoring] on adding the content to the documentation. + +

The page is only available on this site and will not be +rendered on the spine.io.

+ +[authoring]: https://github.com/SpineEventEngine/SpineEventEngine.github.io/blob/master/AUTHORING.md diff --git a/_hugo-site/go.mod b/_hugo-site/go.mod new file mode 100644 index 0000000..60f25e8 --- /dev/null +++ b/_hugo-site/go.mod @@ -0,0 +1,5 @@ +module github.com/SpineEventEngine/documentation/_hugo-site + +go 1.22.0 + +require github.com/TeamDev-Ltd/site-commons v0.0.0-20251202150534-a795438915ff // indirect diff --git a/_hugo-site/go.sum b/_hugo-site/go.sum new file mode 100644 index 0000000..44e846e --- /dev/null +++ b/_hugo-site/go.sum @@ -0,0 +1,2 @@ +github.com/TeamDev-Ltd/site-commons v0.0.0-20251202150534-a795438915ff h1:8kjfGJhf6LeS+IlK9NRktxtcv6O/WDneBuQD3QLPGIs= +github.com/TeamDev-Ltd/site-commons v0.0.0-20251202150534-a795438915ff/go.mod h1:atDeksDWBzsIidpW6Ivz2yYHwp2JPa1i1KXIxkctQ3c= diff --git a/_hugo-site/layouts/_default/baseof.html b/_hugo-site/layouts/_default/baseof.html new file mode 100644 index 0000000..4f16f9a --- /dev/null +++ b/_hugo-site/layouts/_default/baseof.html @@ -0,0 +1,15 @@ + + +{{ partial "head/head.html" . }} +{{ $bodyClass := partial "functions/get-body-class.html" . }} + +
+
+ {{ block "main" . }}{{ end }} +
+
+ {{ partial "scripts/body-scripts.html" . }} + + diff --git a/_hugo-site/layouts/_default/page.html b/_hugo-site/layouts/_default/page.html new file mode 100644 index 0000000..bf703c8 --- /dev/null +++ b/_hugo-site/layouts/_default/page.html @@ -0,0 +1,3 @@ +{{ define "main" }} + {{ .Content }} +{{ end }} diff --git a/_hugo-site/layouts/_default/section.html b/_hugo-site/layouts/_default/section.html new file mode 100644 index 0000000..bf703c8 --- /dev/null +++ b/_hugo-site/layouts/_default/section.html @@ -0,0 +1,3 @@ +{{ define "main" }} + {{ .Content }} +{{ end }} diff --git a/_hugo-site/layouts/_partials/head/head.html b/_hugo-site/layouts/_partials/head/head.html new file mode 100644 index 0000000..55a1490 --- /dev/null +++ b/_hugo-site/layouts/_partials/head/head.html @@ -0,0 +1,35 @@ + + + + + + + {{ partial "head/title.html" . }} + {{ partial "docs/head/code-theme.html" . }} + {{ partial "head/stylesheet.html" . }} + {{ partial "scripts/head-scripts.html" . }} + diff --git a/_hugo-site/layouts/_partials/head/stylesheet.html b/_hugo-site/layouts/_partials/head/stylesheet.html new file mode 100644 index 0000000..22f8444 --- /dev/null +++ b/_hugo-site/layouts/_partials/head/stylesheet.html @@ -0,0 +1,43 @@ + + +{{ partial "docs/head/icon-font.html" . }} + +{{ $options := (dict + "targetPath" "main.css" + "outputStyle" "compressed" + "includePaths" (slice "node_modules") +) }} + +{{ $postCSSConfig := dict "config" "postcss.config.js" }} +{{ $scssPath := "scss/main.scss" }} +{{ $style := resources.Get $scssPath | toCSS $options | postCSS $postCSSConfig }} + +{{ if ne hugo.Environment "development" }} + {{ $style = $style | resources.Minify | fingerprint }} +{{ end }} + + diff --git a/_hugo-site/layouts/_partials/head/title.html b/_hugo-site/layouts/_partials/head/title.html new file mode 100644 index 0000000..44f310f --- /dev/null +++ b/_hugo-site/layouts/_partials/head/title.html @@ -0,0 +1,30 @@ + + +{{ $title := .Title | default site.Params.title }} +{{ $title = replace $title " " " " }} + +{{ $title }} diff --git a/_hugo-site/layouts/_partials/scripts/body-scripts.html b/_hugo-site/layouts/_partials/scripts/body-scripts.html new file mode 100644 index 0000000..60bbeb0 --- /dev/null +++ b/_hugo-site/layouts/_partials/scripts/body-scripts.html @@ -0,0 +1,64 @@ + + + +{{ partial "scripts/libs.html" . }} + +{{ partial "scripts/body/baseurl.html" . }} + +{{ $environment := hugo.Environment }} +{{ $defaultCodeTheme := site.Params.defaultCodeTheme }} + +{{ $params := (dict + "environment" $environment + "defaultCodeTheme" $defaultCodeTheme +)}} + +{{ $jsBootstrap := resources.Get "js/bootstrap.js" }} +{{ $jsDocsMain := resources.Get "js/docs-main.js" }} +{{ $js := (slice + $jsBootstrap $jsDocsMain +) }} + +{{ $js = $js | resources.Concat "js/main.js" | js.Build (dict "params" $params) }} + + + +{{ with .Page.Params.customjs }} + {{ $jsCustom := . }} + {{ if reflect.IsSlice $jsCustom }} + {{ range $jsCustom }} + {{ $path := strings.TrimPrefix "/" . }} + {{ $js := resources.Get $path | js.Build (dict "params" $params) }} + + {{ end }} + {{ else }} + {{ $path := strings.TrimPrefix "/" $jsCustom }} + {{ $js := resources.Get $path | js.Build (dict "params" $params) }} + + {{ end }} +{{ end }} diff --git a/_hugo-site/layouts/_partials/scripts/head-scripts.html b/_hugo-site/layouts/_partials/scripts/head-scripts.html new file mode 100644 index 0000000..7005c0c --- /dev/null +++ b/_hugo-site/layouts/_partials/scripts/head-scripts.html @@ -0,0 +1,27 @@ + + +{{ partial "scripts/head/jquery.html" . }} diff --git a/_hugo-site/layouts/index.html b/_hugo-site/layouts/index.html new file mode 100644 index 0000000..ba4c079 --- /dev/null +++ b/_hugo-site/layouts/index.html @@ -0,0 +1,7 @@ +{{ define "main" }} +
+
+ {{ .Content }} +
+
+{{ end }} diff --git a/_hugo-site/package-lock.json b/_hugo-site/package-lock.json new file mode 100644 index 0000000..0812faa --- /dev/null +++ b/_hugo-site/package-lock.json @@ -0,0 +1,1351 @@ +{ + "name": "spine-docs", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "spine-docs", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "bootstrap": "^5.3.8" + }, + "devDependencies": { + "@fullhuman/postcss-purgecss": "^7.0.2", + "autoprefixer": "^10.4.22", + "postcss": "^8.5.6", + "postcss-cli": "^11.0.1", + "postcss-discard-comments": "^7.0.5" + } + }, + "node_modules/@fullhuman/postcss-purgecss": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@fullhuman/postcss-purgecss/-/postcss-purgecss-7.0.2.tgz", + "integrity": "sha512-U4zAXNaVztbDxO9EdcLp51F3UxxYsb/7DN89rFxFJhfk2Wua2pvw2Kf3HdspbPhW/wpHjSjsxWYoIlbTgRSjbQ==", + "dev": true, + "dependencies": { + "purgecss": "^7.0.2" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", + "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.27.0", + "caniuse-lite": "^1.0.30001754", + "fraction.js": "^5.3.4", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.31", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.31.tgz", + "integrity": "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==", + "dev": true, + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bootstrap": { + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz", + "integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", + "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "baseline-browser-mapping": "^2.8.25", + "caniuse-lite": "^1.0.30001754", + "electron-to-chromium": "^1.5.249", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.1.4" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001757", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz", + "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dependency-graph": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz", + "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.262", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.262.tgz", + "integrity": "sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs-extra": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "dev": true, + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lru-cache": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.2.tgz", + "integrity": "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==", + "dev": true, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-cli": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.1.tgz", + "integrity": "sha512-0UnkNPSayHKRe/tc2YGW6XnSqqOA9eqpiRMgRlV1S6HdGi16vwJBx7lviARzbV1HpQHqLLRH3o8vTcB0cLc+5g==", + "dev": true, + "dependencies": { + "chokidar": "^3.3.0", + "dependency-graph": "^1.0.0", + "fs-extra": "^11.0.0", + "picocolors": "^1.0.0", + "postcss-load-config": "^5.0.0", + "postcss-reporter": "^7.0.0", + "pretty-hrtime": "^1.0.3", + "read-cache": "^1.0.0", + "slash": "^5.0.0", + "tinyglobby": "^0.2.12", + "yargs": "^17.0.0" + }, + "bin": { + "postcss": "index.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-discard-comments": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-7.0.5.tgz", + "integrity": "sha512-IR2Eja8WfYgN5n32vEGSctVQ1+JARfu4UH8M7bgGh1bC+xI/obsPJXaBpQF7MAByvgwZinhpHpdrmXtvVVlKcQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^7.1.0" + }, + "engines": { + "node": "^18.12.0 || ^20.9.0 || >=22.0" + }, + "peerDependencies": { + "postcss": "^8.4.32" + } + }, + "node_modules/postcss-discard-comments/node_modules/postcss-selector-parser": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", + "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-load-config": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.1.0.tgz", + "integrity": "sha512-G5AJ+IX0aD0dygOE0yFZQ/huFFMSNneyfp0e3/bT05a8OfPC5FUoZRPfGijUdGOJNMewJiwzcHJXFafFzeKFVA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.1.1", + "yaml": "^2.4.2" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + } + } + }, + "node_modules/postcss-reporter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.1.0.tgz", + "integrity": "sha512-/eoEylGWyy6/DOiMP5lmFRdmDKThqgn7D6hP2dXKJI/0rJSO1ADFNngZfDzxL0YAxFvws+Rtpuji1YIHj4mySA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "picocolors": "^1.0.0", + "thenby": "^1.3.4" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/purgecss": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-7.0.2.tgz", + "integrity": "sha512-4Ku8KoxNhOWi9X1XJ73XY5fv+I+hhTRedKpGs/2gaBKU8ijUiIKF/uyyIyh7Wo713bELSICF5/NswjcuOqYouQ==", + "dev": true, + "dependencies": { + "commander": "^12.1.0", + "glob": "^11.0.0", + "postcss": "^8.4.47", + "postcss-selector-parser": "^6.1.2" + }, + "bin": { + "purgecss": "bin/purgecss.js" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/thenby": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.3.4.tgz", + "integrity": "sha512-89Gi5raiWA3QZ4b2ePcEwswC3me9JIg+ToSgtE0JWeCynLnLxNr/f9G+xfo9K+Oj4AFdom8YNJjibIARTJmapQ==", + "dev": true + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + } + } +} diff --git a/_hugo-site/package.json b/_hugo-site/package.json new file mode 100644 index 0000000..343a8ff --- /dev/null +++ b/_hugo-site/package.json @@ -0,0 +1,21 @@ +{ + "name": "spine-docs", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "@fullhuman/postcss-purgecss": "^7.0.2", + "autoprefixer": "^10.4.22", + "postcss": "^8.5.6", + "postcss-cli": "^11.0.1", + "postcss-discard-comments": "^7.0.5" + }, + "dependencies": { + "bootstrap": "^5.3.8" + } +} diff --git a/_hugo-site/postcss.config.js b/_hugo-site/postcss.config.js new file mode 100644 index 0000000..a69ff3e --- /dev/null +++ b/_hugo-site/postcss.config.js @@ -0,0 +1,22 @@ +/** + * Adds vendor prefixes to CSS. + * + * See the `.browserslistrc` file in the root for the actual list of browsers, + * where `> 0.5%` means all browsers that are used by more than 0.5% + * of users worldwide. See https://github.com/browserslist/browserslist#queries. + */ +const autoprefixer = require('autoprefixer'); + +/** + * Discards comments from the CSS. + * + * See https://www.npmjs.com/package/postcss-discard-comments. + */ +const discardComments = require('postcss-discard-comments'); + +module.exports = { + plugins: [ + autoprefixer, + discardComments({removeAllButFirst: true}) + ] +} diff --git a/_hugo-theme/assets/js/bootstrap.js b/_hugo-theme/assets/js/bootstrap.js new file mode 100644 index 0000000..364f6be --- /dev/null +++ b/_hugo-theme/assets/js/bootstrap.js @@ -0,0 +1,28 @@ +/* + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import 'bootstrap/js/dist/collapse'; +import 'bootstrap/js/dist/dropdown'; diff --git a/_hugo-theme/assets/js/docs-main.js b/_hugo-theme/assets/js/docs-main.js new file mode 100644 index 0000000..6e4bab5 --- /dev/null +++ b/_hugo-theme/assets/js/docs-main.js @@ -0,0 +1,46 @@ +/* + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Theme JS from the `TeamDev-Ltd/site-commons`. +/* TODO:2025-12-03:julia.evseeva: Enable when the icon position will be approved. */ +/*import 'js/components/copy-code.js'*/ + +import {interactiveToc} from 'js/docs/interactive-toc'; +import {setElementMaxHeight} from 'js/docs/element-max-height'; +import {initSidenav} from 'js/docs/sidenav'; +import {initCodeTheme} from 'js/docs/code-theme'; +import {setupAnchorClick} from 'js/docs/anchor-icon'; + +$(function() { + initCodeTheme(); + setElementMaxHeight(); + + if ($('body').hasClass('docs')) { + interactiveToc(); + initSidenav(); + setupAnchorClick(); + } +}); diff --git a/_hugo-theme/assets/js/docs/anchor-icon.js b/_hugo-theme/assets/js/docs/anchor-icon.js new file mode 100644 index 0000000..6702397 --- /dev/null +++ b/_hugo-theme/assets/js/docs/anchor-icon.js @@ -0,0 +1,49 @@ +/* + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +'use strict'; + +import {copyToClipboard} from "js/components/copy-to-clipboard"; + +/** + * Manages the anchor icon click. + * + *

Also, copies the `href` to clipboard. + */ +export function setupAnchorClick() { + const anchorIconClass = 'anchor-icon'; + const $anchorLinks = $('a[href^="#"]'); + + $anchorLinks.on('click', function() { + const $this = $(this); + const anchor = $this.attr('href'); + + if ($this.hasClass(anchorIconClass)) { + window.location.hash = anchor; + copyToClipboard(window.location.href); + } + }); +} diff --git a/_hugo-theme/assets/js/docs/architecture-diagram.js b/_hugo-theme/assets/js/docs/architecture-diagram.js new file mode 100644 index 0000000..e68c3e6 --- /dev/null +++ b/_hugo-theme/assets/js/docs/architecture-diagram.js @@ -0,0 +1,380 @@ +/* + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * This is a JavaScript file which backs the Spine architecture diagram. + * + * Please see `/docs/1/introduction/architecture.md` for usage. + */ + +$( + /** + * This function is executed upon page load. + * + * Binds the handlers to the events in this HTML page. + */ + function () { + const baseURL = BASE_URL; + + console.log(`baseurl ${baseURL}`) + + /** + * CSS classes used as selectors to manipulate the elements of SVG diagram. + */ + const endUserClass = "end-user"; + const boxCaptionClass = "box-caption"; + const arrowCaptionClass = "arrow-caption"; + const titleCaptionClass = "title-caption"; + const arrowClass = "arrow"; + const pathOnlyClass = "path-only"; + + /** + * CSS classes of the HTML elements on the page. + * @type {string} + */ + let architectureLinkClass = "architecture-link"; + let noSelectClass = "noselect"; + + let useFacingLink = $("#display-user-facing-components"); + let allComponentLink = $("#display-all-components"); + let selectedElementColor = "#8d28e0"; + let selectedCaptionColor = "#fafafa"; + let selectedBodyBgColor = "#e7ecfa"; + let selectedBodyBgCaptionColor = "#505050"; + + const originFillAttr = "origin-fill"; + const originStrokeAttr = "origin-stroke"; + + const fillAttr = "fill"; + const strokeAttr = "stroke"; + const fillOpacityAttr = "fill-opacity"; + const strokeOpacityAttr = "stroke-opacity"; + const pointerEvents = "pointer-events"; + + const textTag = "text"; + const rectTag = "rect"; + const pathTag = "path"; + + function setupLookAndFeel() { + + // Back up the original fill color and color of elements to use in `mouseleave` later. + let contents = $(".diagram-content").find("*"); + for (let index = 0; index < contents.length; index++) { + const item = $(contents[index]); + const elementName = item[0].nodeName.toLowerCase(); + if (textTag === elementName) { + + if (hasClass(item, boxCaptionClass) + || hasClass(item, arrowCaptionClass) + || hasClass(item, titleCaptionClass)) { + item.attr(originFillAttr, item.attr(fillAttr)); + + // Make all TEXTs non-selectable. + item.addClass(noSelectClass); + } + } + if (rectTag === elementName || pathTag === elementName) { + item.attr(originFillAttr, item.attr(fillAttr)); + item.attr(originStrokeAttr, item.attr(strokeAttr)) + } + } + } + + + /** + * Changes opacity of the elements, not marked as "end-user". + * + * The opacity value is expected to be [0; 1] range. + * + * @param textOpacity the opacity to apply to text elements + * @param elementOpacity the opacity to apply "rect" and "path" elements + */ + function fade(textOpacity, elementOpacity) { + let contents = $(".diagram-content").find("*"); + for (let index = 0; index < contents.length; index++) { + const item = $(contents[index]); + if (hasClass(item, endUserClass)) { + continue; + } + const elementName = item[0].nodeName.toLowerCase(); + + if (textTag === elementName) { + + if (hasClass(item, boxCaptionClass) + || hasClass(item, arrowCaptionClass) + || hasClass(item, titleCaptionClass)) { + + item.attr(fillOpacityAttr, textOpacity); + } + } + if (rectTag === elementName) { + item.attr(fillOpacityAttr, elementOpacity); + } + if (pathTag === elementName) { + item.attr(fillOpacityAttr, elementOpacity); + + item.attr(strokeOpacityAttr, elementOpacity); + } + } + } + + /** + * A custom implementation of `jQuery.hasClass()` suitable for SVG elements. + * + * In the jQuery 1.11.2 currently used, SVG elements are not supported + * by `jQuery.hasClass()`. + * + * @param element an element wrapped in jQuery. + * @param className a class name to detect + * @return `true` if such a class name is declared for this element, `false` otherwise. + */ + function hasClass(element, className) { + const firstChild = element[0]; + for (let classIndex = 0; classIndex < firstChild.classList.length; classIndex++) { + if (className === firstChild.classList[classIndex]) { + return true; + } + } + return false; + } + + /** + * Adds a link behavior to an element. + * + * @param linkElement the jQuery object wrapping the DOM element + * @param onClickCallback the callback to set upon 'click' event + */ + function enableLink(linkElement, onClickCallback) { + linkElement + .addClass(architectureLinkClass) + .click(function () { + onClickCallback() + }); + } + + /** + * Disables a link behaviour of an element. + * + * @param linkElement the jQuery object wrapping the DOM element + */ + function disableLink(linkElement) { + linkElement + .removeClass(architectureLinkClass) + .unbind("click"); + } + + function makeClickable(selector, url) { + + $(".g-caption" + selector) + .css("cursor", "pointer") + .attr("pointer-events", "all") + .mouseover(function () { + let matched = $(selector); + + for (let index = 0; index < matched.length; index++) { + const item = $(matched[index]); + const elementName = item[0].nodeName.toLowerCase(); + if(textTag === elementName) { + item.attr(fillAttr, selectedCaptionColor); + } + if (rectTag === elementName || pathTag === elementName) { + item.attr(fillAttr, selectedElementColor); + } + if(hasClass(item, arrowClass)) { + item.attr(strokeAttr, selectedElementColor); + } + if(hasClass(item, pathOnlyClass)) { + item.attr(fillAttr, "none"); + } + } + }) + .mouseout(function () { + let matched = $(selector); + for (let index = 0; index < matched.length; index++) { + const item = $(matched[index]); + const elementName = item[0].nodeName.toLowerCase(); + if (textTag === elementName + || rectTag === elementName + || pathTag === elementName) { + let originFillValue = item.attr(originFillAttr); + item.attr(fillAttr, originFillValue); + } + + if(hasClass(item, arrowClass)) { + let originStrokeValue = item.attr(originStrokeAttr); + item.attr(strokeAttr, originStrokeValue); + } + } + + }) + .click(function () { + document.location.href = baseURL + url; + }); + + $(".g-caption-bounded-context" + selector) + .css("cursor", "pointer") + .attr("pointer-events", "all") + .mouseover(function () { + let matched = $(selector); + + for (let index = 0; index < matched.length; index++) { + const item = $(matched[index]); + const elementName = item[0].nodeName.toLowerCase(); + if(textTag === elementName) { + item.attr(fillAttr, selectedBodyBgCaptionColor); + } + if (rectTag === elementName || pathTag === elementName) { + item.attr(pointerEvents, "none"); + item.attr(fillAttr, selectedBodyBgColor); + } + if(hasClass(item, arrowClass)) { + item.attr(strokeAttr, selectedBodyBgColor); + } + } + }) + .mouseout(function () { + let matched = $(selector); + for (let index = 0; index < matched.length; index++) { + const item = $(matched[index]); + const elementName = item[0].nodeName.toLowerCase(); + if (textTag === elementName + || rectTag === elementName + || pathTag === elementName) { + let originFillValue = item.attr(originFillAttr); + item.attr(fillAttr, originFillValue); + } + + if(hasClass(item, arrowClass)) { + let originStrokeValue = item.attr(originStrokeAttr); + item.attr(strokeAttr, originStrokeValue); + } + } + + }) + .click(function () { + document.location.href = baseURL + url; + }); + + + $(".g-arrow" + selector) + .css("cursor", "pointer") + .attr("pointer-events", "all") + .mouseover(function () { + let matched = $(selector); + + for (let index = 0; index < matched.length; index++) { + const item = $(matched[index]); + const elementName = item[0].nodeName.toLowerCase(); + if (textTag === elementName) { + item.attr(fillAttr, selectedElementColor); + } + if(hasClass(item, arrowClass)) { + item.attr(fillAttr, selectedElementColor); + } + } + }) + .mouseout(function () { + let matched = $(selector); + for (let index = 0; index < matched.length; index++) { + const item = $(matched[index]); + const elementName = item[0].nodeName.toLowerCase(); + if (textTag === elementName) { + let originFillValue = item.attr(originFillAttr); + item.attr(fillAttr, originFillValue); + } + if(hasClass(item, arrowClass)) { + let originFillValue = item.attr(originFillAttr); + item.attr(fillAttr, originFillValue); + } + } + + }) + .click(function () { + document.location.href = baseURL + url; + }); + + } + + /** + * Displays the user-facing components and fades out the rest. + */ + function displayUserFacing() { + fade("0.65", "0.2"); + enableLink(allComponentLink, displayAll); + disableLink(useFacingLink); + } + + /** + * Displays all the Spine components and removes the fading. + */ + function displayAll() { + fade("1", "1"); + + enableLink(useFacingLink, displayUserFacing); + disableLink(allComponentLink); + } + + /** + * Changes the diagram visibility to make it visible on UI. + * + *

This is useful to avoid the diagram from flickering during loading. + * The styles that hide the diagram are in the file `_sass/base/_diagram.scss`. + */ + function changeDiagramVisibility() { + $("#spine-architecture-diagram").css("visibility", "visible"); + } + + setupLookAndFeel(); + displayUserFacing(); + changeDiagramVisibility(); + + // Link items to the corresponding pages. + + // Boxes: + makeClickable(".aggregate", "docs/introduction/concepts#aggregate"); + makeClickable(".bounded-context", "docs/introduction/concepts#bounded-context"); + makeClickable(".pm", "docs/introduction/concepts#process-manager"); + makeClickable(".projection", "docs/introduction/concepts#projection"); + makeClickable(".aggregate-repo", "docs/introduction/concepts#repository"); + makeClickable(".pm-repo", "docs/introduction/concepts#repository"); + makeClickable(".projection-repo", "docs/introduction/concepts#repository"); + makeClickable(".command-bus", "docs/introduction/concepts#command-bus"); + makeClickable(".event-bus", "docs/introduction/concepts#event-bus"); + makeClickable(".aggregate-mirror", "docs/introduction/concepts#aggregate-mirror"); + makeClickable(".command-store", "docs/introduction/concepts#command-store"); + makeClickable(".event-store", "docs/introduction/concepts#event-store"); + makeClickable(".command-service", "docs/introduction/concepts#command-service"); + makeClickable(".query-service", "docs/introduction/concepts#query-service"); + makeClickable(".subscription-service", "docs/introduction/concepts#subscription-service"); + makeClickable(".stand", "docs/introduction/concepts#stand"); + + // Arrows: + makeClickable(".ui-command-service", "docs/introduction/concepts#command"); + makeClickable(".command-service-ui", "docs/introduction/concepts#acknowledgement"); + makeClickable(".event-bus-aggregate-repo", "docs/introduction/concepts#event"); + makeClickable(".integration-events", "docs/introduction/concepts#integration-event"); + } +); diff --git a/_hugo-theme/assets/js/docs/code-theme.js b/_hugo-theme/assets/js/docs/code-theme.js new file mode 100644 index 0000000..65b6960 --- /dev/null +++ b/_hugo-theme/assets/js/docs/code-theme.js @@ -0,0 +1,99 @@ +/* + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +'use strict'; + +import * as params from '@params'; + +/** + * Changes the code theme styles and body class on the toggle click. + * + *

The selected theme will be saved in cookies and the user will be able + * to navigate between pages without selecting the theme again. + * + *

The stylesheet is applied in `layouts/_partials/head/code-theme.html`. + */ +export function initCodeTheme() { + const $body = $('body'); + const $themeCSS = $('#code-theme-css'); + const $themeToggle = $('#code-theme-toggle'); + const $codeBlock = $('div.highlight'); + const themeClass = { + dark: 'dark-code-theme', + light: 'light-code-theme' + } + const toggleClass = { + toggle: 'code-theme-toggle', + dark: 'dark', + light: 'light' + } + const defaultTheme = params.defaultCodeTheme || 'dark'; + let theme = Cookies.get('code-theme') || defaultTheme; + + setTheme(theme); + createToggleIcon(); + + /** + * Creates the theme toggle icon under each code block. + */ + function createToggleIcon() { + if (!$codeBlock) return; + + $codeBlock.each(function () { + const icon = $(``) + $(this).append(icon); + }); + } + + /** + * Updates the theme on the toggle icon click. + */ + $(document).on('click', `.${toggleClass.toggle}`, function () { + const currentHref = $themeCSS.attr('href'); + const lightHref = $themeCSS.data('light'); + const isLight = currentHref === lightHref; + const newTheme = isLight ? 'dark' : 'light'; + + setTheme(newTheme); + Cookies.set('code-theme', newTheme); + }); + + /** + * Sets the provided theme as the body class and changes the CSS URL + * to the corresponding one. + * + * @param {string} theme the code theme to be set + */ + function setTheme(theme) { + $themeCSS.attr('href', $themeCSS.data(theme)); + $body.removeClass(`${themeClass.dark} ${themeClass.light}`) + .addClass(themeClass[theme]); + $themeToggle.removeClass(`${toggleClass.dark} ${toggleClass.light}`) + .addClass(toggleClass[theme]); + } +} diff --git a/_hugo-theme/assets/js/docs/element-max-height.js b/_hugo-theme/assets/js/docs/element-max-height.js new file mode 100644 index 0000000..d8fd530 --- /dev/null +++ b/_hugo-theme/assets/js/docs/element-max-height.js @@ -0,0 +1,88 @@ +/* + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +'use strict'; + +/** + * Sets the `max-height` property to an element with the `.set-max-height` class. + * + *

The `max-height` value is calculated depending on the current window + * height and will be updated on window resize. + */ +export function setElementMaxHeight() { + const $element = $('.set-max-height'); + const $footer = $('.footer'); + const headerHeight = $('#header').length ? $('#header').outerHeight() : 0; + const footerTopPosition = $footer.length ? $footer.position().top : 0; + + if ($element.length) { + updateMaxHeight(); + + $(window).on('resize scroll', function () { + updateMaxHeight(); + }); + } + + /** + * Sets the `max-height` value to the element + * to be sure that it always fits on the page. + */ + function updateMaxHeight() { + const maxHeight = calculateMaxHeight(); + + $element.each(function() { + $(this).css({ + 'overflow': 'auto', + 'max-height': maxHeight + }); + }); + } + + /** + * Calculates the possible element `max-height` based on the window + * and navigation heights. + * + * @return {number} maxHeight the value of the maximum possible height + */ + function calculateMaxHeight() { + const windowHeight = $(window).height(); + const scrollTop = $(window).scrollTop(); + const elementTopMargin = 24; + const elementBottomMargin = 20; + const elementTopPosition = headerHeight + elementTopMargin; + const maxHeight = windowHeight - elementTopPosition - elementBottomMargin; + + if ($footer.length) { + const isFooterVisible = windowHeight + scrollTop > footerTopPosition; + + if (isFooterVisible) { + return footerTopPosition - scrollTop - elementTopPosition - elementBottomMargin; + } + } + + return maxHeight; + } +} diff --git a/_hugo-theme/assets/js/docs/interactive-toc.js b/_hugo-theme/assets/js/docs/interactive-toc.js new file mode 100644 index 0000000..b28d79f --- /dev/null +++ b/_hugo-theme/assets/js/docs/interactive-toc.js @@ -0,0 +1,185 @@ +/* + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +'use strict'; + +/** + * Makes the Hugo TOC items interactive. + * + *

During scrolling, adds the `current` class to the anchor, the heading + * of which is now visible on the page. + * + *

Note, that the TOC element should be wrapped into the `div` with + * the `interactive-toc` class. For example: + * ``` + *

+ * {{ .TableOfContents }} + *
+ * ``` + */ +export function interactiveToc() { + const $interactiveToc = $('.interactive-toc'); + const $tocItems = $interactiveToc.find('#TableOfContents a'); + const currentClass = 'current'; + let anchors = null; + let lastActiveElement = null; + let disableScroll = false; + + if ($interactiveToc.length) { + getAnchors(); + markCurrentTocItem(); + + $(window).on('load', function() { + getAnchors(); + markCurrentTocItem(); + }); + + $(window).on('scroll', function() { + if (disableScroll) return; + markCurrentTocItem(); + }); + } + + /** + * Makes the clicked TOC item active. + * + *

Prevents the default scroll to avoid active item overriding. + */ + $tocItems.on('click', function (e) { + e.preventDefault(); + const $current = $(this); + const anchor = $current.attr('href'); + + disableScroll = true; + $tocItems.removeClass(currentClass); + $current.addClass(currentClass); + window.location.hash = anchor; + + $('html, body').animate( + {scrollTop: $(anchor).offset().top - 80}, + 300, + function () { + disableScroll = false; + } + ); + }); + + /** + * Marks the current TOC item with the `currentClass`. + */ + function markCurrentTocItem() { + if (!anchors) return; + $tocItems.removeClass(currentClass); + const $active = getCurrentTocItem().addClass(currentClass); + scrollToActiveTocItem($active.get(0)); + } + + /** + * Returns the TOC item, heading of which is now visible on the page. + * + * @returns {jQuery|HTMLElement} the current TOC item + */ + function getCurrentTocItem() { + const scrollPosition = window.pageYOffset; + const windowIncrement = 0.14; + let currentAnchor = null; + anchors.each(function() { + let headingPosition = getHeading(this).position().top; + if (headingPosition < scrollPosition + window.innerHeight * windowIncrement) { + currentAnchor = this; + return; + } + }) + return getTocItem(currentAnchor); + } + + /** + * Returns the TOC item corresponding to the provided `anchor`. + * + * @param {String} anchor the anchor of the visible heading + * @returns {*|jQuery|HTMLElement} the TOC item corresponding to the `anchor` + */ + function getTocItem(anchor) { + return $('#TableOfContents a[href=\"' + anchor + '\"]'); + } + + /** + * Returns the heading element corresponding to the provided `anchor`. + * + * @param {String} anchor the anchor of the heading + * @returns {*|jQuery|HTMLElement} the heading element + */ + function getHeading(anchor) { + return $(':header[id=' + anchor.substring(1) + ']'); + } + + /** + * Returns the list of available anchors on the page. + * + * @returns {Array} the list of anchors + */ + function getAnchors() { + if (!anchors) { + anchors = $tocItems.map(function() { + return $(this).attr("href"); + }); + } + return anchors; + } + + /** + * Scrolls the TOC container to the active item. + * + * @param {DOM node} activeElement the active element in the TOC + */ + function scrollToActiveTocItem(activeElement) { + if (!activeElement) return; + + if ($interactiveToc && $interactiveToc[0].contains(activeElement) && !isElementInView(activeElement)) { + if (activeElement !== lastActiveElement) { + activeElement.scrollIntoView({ + block: 'nearest', + inline: 'nearest', + behavior: 'smooth' + }); + lastActiveElement = activeElement; + } + } + } + + /** + * Checks if the element is in view. + * + *

Helps to avoid scroll jumping at the top of the page. + * + * @param element the element that should be in the view + * @return {boolean} + */ + function isElementInView(element) { + const rect = element.getBoundingClientRect(); + return rect.top >= 0 && rect.bottom <= window.innerHeight; + } +} diff --git a/_hugo-theme/assets/js/docs/sidenav.js b/_hugo-theme/assets/js/docs/sidenav.js new file mode 100644 index 0000000..a22e49d --- /dev/null +++ b/_hugo-theme/assets/js/docs/sidenav.js @@ -0,0 +1,65 @@ +/* + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Toggles the sidenav on mobile devices. + */ +export function initSidenav() { + const $body = $('body'); + const $mobileSidenavToggle = $('#mobile-sidenav-toggle'); + const $mobileSidenavCloseBtn = $('#close-mobile-sidenav'); + const mobileSidenavOpenedClass = 'mobile-sidenav-opened'; + + $(window).on('resize', function() { + hideMobileSidenavOnResize(); + }); + + /** + * Shows the mobile sidenav panel on the toggle click. + */ + $mobileSidenavToggle.click(function () { + $body.addClass(mobileSidenavOpenedClass); + }); + + /** + * Closes the mobile sidenav panel on the close button click. + */ + $mobileSidenavCloseBtn.click(function () { + $body.removeClass(mobileSidenavOpenedClass); + }); + + /** + * Hides the mobile sidenav on window resizing. + */ + function hideMobileSidenavOnResize() { + const tabletWidth = 880; + const mobileWindow = $(window).width() <= tabletWidth; + + if (!mobileWindow) { + $body.removeClass(mobileSidenavOpenedClass); + } + } +} diff --git a/_hugo-theme/assets/docs-common.scss b/_hugo-theme/assets/scss/docs-common.scss similarity index 93% rename from _hugo-theme/assets/docs-common.scss rename to _hugo-theme/assets/scss/docs-common.scss index 86644c3..f7a639e 100644 --- a/_hugo-theme/assets/docs-common.scss +++ b/_hugo-theme/assets/scss/docs-common.scss @@ -30,3 +30,6 @@ @import "docs-common/config"; @import "docs-common/mixins"; @import "docs-common/layout"; +@import "docs-common/code"; +@import "docs-common/snackbar"; +@import "docs-common/anchor-icon"; diff --git a/_hugo-theme/assets/scss/docs-common/_anchor-icon.scss b/_hugo-theme/assets/scss/docs-common/_anchor-icon.scss new file mode 100644 index 0000000..bb63372 --- /dev/null +++ b/_hugo-theme/assets/scss/docs-common/_anchor-icon.scss @@ -0,0 +1,41 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +$icon-color: #1a96de; +$icon-opacity: .38; +$icon-size-s: 24px; + +// Common theme styles from the `TeamDev-Ltd/site-commons`. +@import "../anchor-icon"; + +.anchor-icon { + color: $icon-color !important; + font-weight: 700; + + &:after { + margin-bottom: 2px; + } +} diff --git a/_hugo-theme/assets/scss/docs-common/_config.scss b/_hugo-theme/assets/scss/docs-common/_config.scss index 332688a..1f93e55 100755 --- a/_hugo-theme/assets/scss/docs-common/_config.scss +++ b/_hugo-theme/assets/scss/docs-common/_config.scss @@ -26,8 +26,7 @@ // Layout $layout-max-width: 1260px; -$custom-side-col-width: 240px; -$center-col-width: $layout-max-width - $custom-side-col-width - $custom-side-col-width; // 780px; +$doc-sidenav-mobile-breakpoint: 880px; // Line heights $article-line-height: 1.74; @@ -74,18 +73,5 @@ $icon-size--m : 32px; $icon-size--l : 40px; $icon-size--xl : 48px; -// Width for the element that is inside the custom column in 240px -// Width equals `custom-column-width` minus `padding` (240px - 15px - 15px = 210px) -$sticky-el-width: 210px; - -// Collapsible item -$icon-right-offset: 48px; - -// Container top offset for pages with a fixed header. For example a page with a single post. -$page-top-offset: $header-height + 32px; -$page-top-offset-mobile: $header-height + 16px; - // Inputs $input-border-radius: $border-radius; - -$doc-sidenav-mobile-breakpoint: 880px; diff --git a/_hugo-theme/assets/scss/docs-common/_layout.scss b/_hugo-theme/assets/scss/docs-common/_layout.scss index 8dc1260..9feb8c4 100644 --- a/_hugo-theme/assets/scss/docs-common/_layout.scss +++ b/_hugo-theme/assets/scss/docs-common/_layout.scss @@ -28,6 +28,10 @@ --text-color: #3a3a3a; } +html { + scroll-padding-top: $header-height; +} + html, body { height: 100%; diff --git a/_hugo-theme/assets/scss/docs-common/_mixins.scss b/_hugo-theme/assets/scss/docs-common/_mixins.scss index c2d36ac..5bc83b9 100644 --- a/_hugo-theme/assets/scss/docs-common/_mixins.scss +++ b/_hugo-theme/assets/scss/docs-common/_mixins.scss @@ -40,7 +40,7 @@ $breakpoints: ( lg-desktop: 1440px ); -/* Usage: `@include breakpoint(desktop)` */ +// Usage: `@include breakpoint(desktop)` @mixin breakpoint($deviceWidth) { @if map-has-key($breakpoints, $deviceWidth) { $value: map-get($breakpoints, $deviceWidth); diff --git a/_hugo-theme/assets/scss/docs-common/_snackbar.scss b/_hugo-theme/assets/scss/docs-common/_snackbar.scss new file mode 100644 index 0000000..a8eb3e4 --- /dev/null +++ b/_hugo-theme/assets/scss/docs-common/_snackbar.scss @@ -0,0 +1,30 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +$dark-color: #232526; + +// Common theme styles from the `TeamDev-Ltd/site-commons`. +@import "../snackbar"; diff --git a/_hugo-theme/assets/scss/docs-common/code/_code-block.scss b/_hugo-theme/assets/scss/docs-common/code/_code-block.scss new file mode 100644 index 0000000..4fe4d6e --- /dev/null +++ b/_hugo-theme/assets/scss/docs-common/code/_code-block.scss @@ -0,0 +1,86 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + Extends the `_code.scss` styles. + + The `.code-block` wrapper is available when using the `{{< highlight >}}` + shortcode with the file name parameter or with using the `code-tabs`. +*/ +.code-block { + $code-block-background: var(--code-block-background); + $header-name-font-size: 12px; + $header-bg-color: var(--code-block-background); + $header-divider-color: var(--code-block-header-divider-color); + + margin-bottom: 40px; + background-color: $code-block-background; + border-radius: $code-block-border-radius; + + .code-block-header { + position: relative; + display: flex; + align-items: center; + background-color: $header-bg-color; + border-radius: $code-block-border-radius $code-block-border-radius 0 0; + border-bottom: 1px solid $header-divider-color; + + .file-name { + color: var(--code-block-text-color); + font-size: $header-name-font-size; + font-weight: bold; + line-height: 1; + padding: 14px $code-block-padding; + } + + .copy-code-to-clipboard-icon { + background-color: unset; + top: 0; + } + } + + .highlight { + margin-bottom: 0; + + pre { + border-radius: 0 0 $code-block-border-radius $code-block-border-radius; + } + + table tr td { + &:first-child { + pre { + border-top-left-radius: 0; + } + } + + &:last-child { + pre { + border-top-right-radius: 0; + } + } + } + } +} diff --git a/_hugo-theme/assets/scss/docs-common/code/_code-copy-icon.scss b/_hugo-theme/assets/scss/docs-common/code/_code-copy-icon.scss new file mode 100644 index 0000000..c388f2a --- /dev/null +++ b/_hugo-theme/assets/scss/docs-common/code/_code-copy-icon.scss @@ -0,0 +1,96 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// The icon is added to the DOM in `assets/js/components/docs/copy-code.js`. +.copy-code-to-clipboard-icon { + $icon-container-size: 40px; + $icon-size: 16px; + $icon-color: var(--copy-code-icon-color); + $icon-color-hover: var(--copy-code-icon-hover-color); + $icon-bg-color: var(--code-block-background); + + position: absolute; + display: flex; + align-items: center; + justify-content: center; + width: $icon-container-size; + height: $icon-container-size; + font-size: $icon-size; + color: $icon-color; + background-color: $icon-bg-color; + border-radius: $code-block-border-radius; + top: 0; + right: 0; + transition: color .2s ease-in-out; + cursor: pointer; + + &:hover { + color: $icon-color-hover + } + + $tooltip-top-position: -16px; + $tooltip-right-position: -5px; + + + .copy-code-tooltip { + position: absolute; + visibility: hidden; + font-family: $main-font; + top: $tooltip-top-position; + right: $tooltip-right-position; + font-size: 12px; + background: rgba(0, 0, 0, .9); + color: white; + padding: 4px 6px; + border-radius: 3px; + + &.show { + visibility: visible; + animation: tooltipFadeIn .5s, tooltipFadeOut .5s 2.5s; + } + } + + @keyframes tooltipFadeIn { + 0% { + top: 0; + opacity: 0; + } + 100% { + top: $tooltip-top-position; + opacity: 1; + } + } + + @keyframes tooltipFadeOut { + 0% { + top: $tooltip-top-position; + opacity: 1; + } + 100% { + top: 0; + opacity: 0; + } + } +} diff --git a/_hugo-theme/assets/scss/docs-common/code/_code-tabs.scss b/_hugo-theme/assets/scss/docs-common/code/_code-tabs.scss new file mode 100644 index 0000000..581ca92 --- /dev/null +++ b/_hugo-theme/assets/scss/docs-common/code/_code-tabs.scss @@ -0,0 +1,120 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The tabs are managed by `assets/js/components/docs/code-tabs.js`. + * The layout of tabs depends on the `assets/scss/components/code/_code-block.scss`. + */ +.code-tabs { + $code-tab-color: var(--code-tab-color); + $code-tab-active-color: var(--code-tab-active-color); + $code-tab-indicator-color: var(--code-tab-indicator-color); + $code-tab-font: var(--main-font); + $code-tab-padding: 14px 16px; + $border-radius: 3px; + $indicator-line-height: 3px; + $indicator-line-border-radius: $indicator-line-height/2; + + margin: 20px 0 32px; + + .tabs { + position: relative; + display: flex; + + .indicator { + content: ''; + position: absolute; + display: block; + bottom: -1px; + min-width: 0; + width: 0; + height: $indicator-line-height; + background: $code-tab-indicator-color; + border-radius: $indicator-line-border-radius; + will-change: left, width; + transition: left .3s ease, width .3s ease; + } + + .tab { + position: relative; + display: inline-block; + padding: $code-tab-padding; + font-family: $code-tab-font; + color: $code-tab-color; + font-weight: bold; + font-size: 12px; + line-height: 1; + transition: color .2s ease-in-out; + cursor: pointer; + + &.active { + color: $code-tab-active-color; + + &.show-static-indicator { + &:after { + content: ''; + position: absolute; + display: block; + left: 0; + bottom: -1px; + width: 100%; + height: $indicator-line-height; + background: red; + } + } + } + } + + &.one-tab { + .indicator { + display: none; + } + } + } + + .code-tab-content { + p { + padding-top: 0 !important; + margin-bottom: 8px; + } + } +} + +.code-tab-content { + display: none; + + &.active { + display: block; + } + + &.inline.active { + display: inline-block; + } + + p:first-child { + padding-top: 0 !important; + } +} diff --git a/_hugo-theme/assets/scss/docs-common/code/_code-theme-toggle.scss b/_hugo-theme/assets/scss/docs-common/code/_code-theme-toggle.scss new file mode 100644 index 0000000..81f445e --- /dev/null +++ b/_hugo-theme/assets/scss/docs-common/code/_code-theme-toggle.scss @@ -0,0 +1,64 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.highlight { + position: relative; +} + +.light-code-theme { + .code-theme-toggle { + opacity: .26; + } +} + +.code-theme-toggle { + $toggle-size: 24px; + $icon-size: 18px; + + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: calc((#{$toggle-size} + 2px) * -1); + right: 0; + width: $toggle-size; + height: $toggle-size; + opacity: .38; + transition: opacity .2s ease-in-out; + cursor: pointer; + + &:before { + content: ''; + position: absolute; + background: url('img/icons/brightness.svg') no-repeat center/cover; + width: $icon-size; + height: $icon-size; + } + + &:hover { + opacity: .54; + } +} diff --git a/_hugo-theme/assets/scss/docs-common/code/_code.scss b/_hugo-theme/assets/scss/docs-common/code/_code.scss new file mode 100644 index 0000000..91cfd1a --- /dev/null +++ b/_hugo-theme/assets/scss/docs-common/code/_code.scss @@ -0,0 +1,198 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +:root { + --code-background: #ffffff; + --code-text-color: inherit; + --code-padding: 0; +} + +.dark-code-theme { + --code-block-background: #2b2b2b; + --code-block-text-color: #a9b7c6; + --code-block-box-shadow: unset; + --code-block-header-divider-color: rgba(255, 255, 255, .08); + --code-block-highlighted-line-bg: #2c3035; + --copy-code-icon-color: #{$gray-600}; + --copy-code-icon-hover-color: rgba(255, 255, 255, .8); + --code-tab-color: #{$gray-600}; + --code-tab-active-color: #f8f8f2; + --code-tab-indicator-color: #{$gray-700}; +} + +.light-code-theme { + --code-block-background: #ffffff; + --code-block-text-color: var(--text-color); + --code-block-box-shadow: 0 3px 12px 0 rgba(35, 37, 38, .1); + --code-block-header-divider-color: rgba(0, 0, 0, .07); + --code-block-highlighted-line-bg: #e9f0e9; + --copy-code-icon-color: #{$gray-600}; + --copy-code-icon-hover-color: #{$gray-700}; + --code-tab-color: #{$gray-600}; + --code-tab-active-color: var(--text-color); + --code-tab-indicator-color: $main-brand-color; +} + +$mono-font-family: $main-mono-font; +$code-block-font-size: 13px; +$code-block-line-height: 1.6; +$code-block-border-radius: 6px; +$code-block-padding: 16px; + +pre, +code { + font-family: $mono-font-family; + color: var(--code-text-color); +} + +pre { + overflow-x: auto; + margin: 0; +} + +code { + font-size: 95%; + background-color: var(--code-background); + padding: var(--code-padding); + margin: 0; + font-variant-ligatures: none; +} + +/* + The default Hugo Highlight. + See the usage here https://gohugo.io/content-management/syntax-highlighting/. + + For better customization enable classes in the project `config`: + ``` + [markup.highlight] + noClasses = false + ``` +*/ +.highlight { + position: relative; + + pre { + border-radius: $code-block-border-radius; + box-shadow: var(--code-block-box-shadow); + } + + // The first `div` that wraps `` or ``. + // When classes are enabled the `div` has the `chroma` class. + // Needed to make the code scrollable if the line numbers are enabled. + > div { + overflow-x: auto; + } + + code { + display: table; + width: 100%; + padding: $code-block-padding; + font-size: $code-block-font-size; + line-height: $code-block-line-height; + background-color: var(--code-block-background); + color: var(--code-block-text-color); + border-radius: unset; + + // Fixes iOS font sizing inside code blocks. + // Font size is affected while using flexbox for `` tag + // inside code on Safari/Chrome iOS. + text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + -moz-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + } + + // Makes highlighted line full-width. + .hl { + margin: 0 -#{$code-block-padding}; + padding: 0 $code-block-padding; + } + + // Hugo layout with numbered code lines. + // The first column is the numbers, the second is the code. + // The layout works if `{linenos=table} near the code backticks is specified. + table { + &.lntable { + width: 100%; + } + + tr { + td { + &:first-child { + user-select: none; + + pre { + overflow: hidden; + border-radius: $code-block-border-radius 0 0 $code-block-border-radius; + + code { + padding-right: 0; + padding-left: 16px; + + span { + // Aligns numbers with the highlighted code line. + display: flex; + } + } + } + } + + &:last-child { + // Prevents the first column from expanding arbitrarily. + width: 100%; + + pre { + border-radius: 0 $code-block-border-radius $code-block-border-radius 0; + + code { + padding-left: 0; + } + } + } + } + } + } +} + +.opaque-hl-lines { + .highlight { + code { + .hl { + background: none; + } + + .line:not(.hl) { + opacity: .3; + } + } + } +} + +.markdown { + .highlight { + margin-bottom: 40px; + } +} diff --git a/_hugo-theme/assets/scss/docs-common/code/_index.scss b/_hugo-theme/assets/scss/docs-common/code/_index.scss new file mode 100644 index 0000000..07ead30 --- /dev/null +++ b/_hugo-theme/assets/scss/docs-common/code/_index.scss @@ -0,0 +1,31 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import "code"; +@import "code-block"; +@import "code-tabs"; +@import "code-copy-icon"; +@import "code-theme-toggle"; diff --git a/_hugo-theme/assets/scss/docs.scss b/_hugo-theme/assets/scss/docs.scss new file mode 100644 index 0000000..4ab6660 --- /dev/null +++ b/_hugo-theme/assets/scss/docs.scss @@ -0,0 +1,42 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +@import "docs/base/colors"; +@import "docs/base/mixins"; + +@import "docs/modules/layout"; +@import "docs/modules/article-container"; +@import "docs/modules/article-text"; +@import "docs/modules/interactive-toc"; +@import "docs/modules/sidenav"; +@import "docs/modules/next-prev-nav"; +@import "docs/modules/diagram"; +@import "docs/modules/note-block"; +@import "docs/modules/docs-category-card"; +@import "docs/modules/book-card"; +@import "docs/modules/person-card"; + +@import "docs/pages/resources"; diff --git a/_hugo-theme/assets/scss/docs/base/_colors.scss b/_hugo-theme/assets/scss/docs/base/_colors.scss new file mode 100644 index 0000000..060782d --- /dev/null +++ b/_hugo-theme/assets/scss/docs/base/_colors.scss @@ -0,0 +1,48 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Brand Colors +$main-brand-color: #1a96de; +$second-brand-color: #116db4; +$body-light-gray-color: #f6f8fA; +$note-bg-color: #e0f2ff; +$warning-color: #deba32; + +// General Colors +$black: #2e2e2e; +$text-color: #3a3a3a; + +// Grays +$gray-100: rgba(black, .12); +$gray-200: rgba(black, .26); +$gray-300: rgba(black, .38); +$gray-500: rgba(black, .54); +$gray-600: rgba(black, .6); +$gray-700: rgba(black, .7); + +// Links +$link-color: $main-brand-color; +$link-hover-color: darken($link-color, 10%); diff --git a/_hugo-theme/assets/scss/docs/base/_mixins.scss b/_hugo-theme/assets/scss/docs/base/_mixins.scss new file mode 100644 index 0000000..061e30b --- /dev/null +++ b/_hugo-theme/assets/scss/docs/base/_mixins.scss @@ -0,0 +1,66 @@ +// Usage: @include transition(all .3s ease-in-out); +@mixin transition($args...) { + -webkit-transition: $args; + -moz-transition: $args; + -ms-transition: $args; + -o-transition: $args; + transition: $args; +} + +// Usage: @include box-shadow(0 10px 20px 0 rgba(black, .12)); +@mixin box-shadow($args...) { + -webkit-box-shadow: $args; + -moz-box-shadow: $args; + -o-box-shadow: $args; + box-shadow: $args; +} + +@mixin close-icon { + display: inline-block; + width: $icon-size--s; + height: $icon-size--s; + background: url('https://spine.io/img/x-black.svg') no-repeat center/cover; + opacity: .26; + @include transition(all .3s ease-in-out); +} + +// Ordered and unordered list styles. +// Usage: `@include list();` +@mixin list($item-line-height: 1.6) { + ol, ul { + margin: 0 0 32px 0; + line-height: $item-line-height; + + @media (max-width: $tablet) { + margin-bottom: 24px; + } + + li { + margin-left: 18px; + margin-top: .6em; + padding-left: 6px; // Adds additional space between bullet and text. + + ol, ul { + margin-bottom: 32px; + + li { + margin-top: .45em; + } + } + } + } + + ul { + list-style: disc; + + li { + ul { + list-style: circle; + } + } + } + + ol { + list-style: decimal; + } +} diff --git a/_hugo-theme/assets/scss/docs/modules/_article-container.scss b/_hugo-theme/assets/scss/docs/modules/_article-container.scss new file mode 100644 index 0000000..31a7aa8 --- /dev/null +++ b/_hugo-theme/assets/scss/docs/modules/_article-container.scss @@ -0,0 +1,88 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +$article-border-color: #e6ecf1; +$article-container-border: 1px solid $article-border-color; +$article-side-padding: 56px; +$article-container-padding: 32px $article-side-padding 40px; +$article-container-margin-bottom: 32px; +$article-container-border-radius: 3px; +$article-container-min-height: 460px; + +.article-container { + display: flex; + flex-direction: column; + background-color: white; + border: $article-container-border; + border-radius: $article-container-border-radius; + padding: $article-container-padding; + margin-bottom: $article-container-margin-bottom; + min-width: 0; // Fixes a bug when `pre` code breaks flex element. + min-height: $article-container-min-height; + + @media (max-width: $phone-xlarge) { + padding: 0; + border: none; + } + + // Full-width code block inside articles. + // Extends styles provided in `scss/docs-common/code/_index.scss`. + --code-block-padding: #{$article-side-padding}; + + @media (max-width: $phone-xlarge) { + --code-block-padding: 32px; + } + @media (max-width: $phone-medium) { + --code-block-padding: 20px; + } + + .highlight { + pre { + border-radius: 0; + margin-right: calc(var(--code-block-padding) * -1); + margin-left: calc(var(--code-block-padding) * -1); + + code { + padding-right: var(--code-block-padding); + padding-left: var(--code-block-padding); + } + } + } + + li { + .highlight { + pre { + border-radius: $code-block-border-radius; + margin-left: unset; + margin-right: unset; + + code { + padding: $code-block-padding; + } + } + } + } +} diff --git a/_hugo-theme/assets/scss/docs/modules/_article-text.scss b/_hugo-theme/assets/scss/docs/modules/_article-text.scss new file mode 100644 index 0000000..3f84e27 --- /dev/null +++ b/_hugo-theme/assets/scss/docs/modules/_article-text.scss @@ -0,0 +1,267 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Please be careful when renaming this class. +// It is used in the DocSearch configuration in the admin panel. +.article-text { + a:not(.anchor-icon) { + text-decoration: none; + color: $link-color; + font-weight: 400; + transition: all .3s ease-in-out; + + &:hover, + &:focus { + color: $link-hover-color; + text-decoration: underline; + } + + &.external-link { + white-space: nowrap; + + &:after { + content: '\2192'; + font-weight: 300; + width: 8px; + height: 8px; + overflow: hidden; + text-align: right; + line-height: 6px; + text-indent: -11px; + opacity: .6; + transform: rotate(-45deg); + transition: opacity .16s ease-in; + vertical-align: super; + font-size: smaller; + text-decoration: none; + display: inline-block; + } + + &:hover { + &:after { + color: $second-brand-color; + } + } + } + } + + ol, ul, li { + padding: 0; + } + + p { + margin-bottom: 16px; + } + + p, ol, ul { + font-family: $main-serif-font; + font-size: $article-font-size; + line-height: $article-line-height; + text-align: justify; + + @media (max-width: $tablet) { + font-size: $font-size--s; + } + + @media (max-width: $phone-medium) { + text-align: left; + } + } + + p + ul { + margin-top: -4px; + } + + .lead + h2 { + padding-top: 0; + } + + h1, h2, h3, h2 { + code { + font-size: inherit; + color: inherit; + } + } + + h1 + h2 { + padding-top: 0; + } + + ul + h2, + ol + h2 { + padding-top: 16px; + } + + h2 + h3 { + padding-top: 4px; + } + + h3 + h4 { + margin-top: 12px; + } + + ol + h3, + ul + h3 { + padding-top: 0; + } + + ol + h4, + ul + h4 { + margin-top: 0; + } + + img { + display: block; + width: 100%; + margin: 0 auto; + padding-bottom: 8px; + } + + .img-small { + img { + width: 70%; + } + } + + .img-caption { + font-family: $main-font; + font-size: 14px; + color: $gray-500; + margin-bottom: 32px; + } + + @include list($item-line-height: $article-line-height); + + // Section headlines + h1 { + font-size: $font-size--xxxl; + font-weight: 300; + color: rgba(black, .4); + line-height: 1.2; + padding-top: 16px; + margin-bottom: 32px; + + @media (max-width: $phone-xlarge) { + margin-bottom: 16px; + } + } + + h2 { + font-size: 1.8rem; + font-weight: 700; + color: $black; + line-height: 1.3; + padding-top: 32px; + margin-bottom: 12px; + + &.top { + padding-top: 8px; + } + } + + h3 { + font-size: 1.25rem; + font-weight: 700; + color: $black; + line-height: 1.4; + margin-bottom: 8px; + padding-top: 24px; + } + + h4 { + font-size: $font-size--s; + font-weight: 700; + color: $black; + margin: 32px 0 8px; + } + + h5 { + font-size: $font-size--s; + font-weight: 300; + color: $black; + } + + h6 { + font-size: .9rem; + font-weight: 500; + color: $black; + } + + .highlight { + margin: 8px 0 40px; + } + + .date { + font-family: $main-font; + font-size: 14px; + color: $gray-500; + } + + .lang { + font-size: 14px; + color: $gray-300; + } + + .coming-soon { + color: $gray-200; + font-weight: 500; + padding-bottom: 24px; + margin: 0; + } + + strong { + font-weight: 700; + } + + em { + font-style: italic; + } + + blockquote { + border-left: 2px solid #eeeeee; + padding: 0 24px 0 10px; + margin: 24px 0 32px; + + p { + position: relative; + padding-left: 32px; + font-size: 22px; + line-height: 32px; + font-style: italic; + font-weight: 300; + color: rgba($text-color, .64); + + &:before { + content: ''; + position: absolute; + left: 0; + width: $icon-size--s; + height: $icon-size--s; + background: url('img/icons/quote.svg') no-repeat center/cover; + } + } + } +} diff --git a/_hugo-theme/assets/scss/docs/modules/_book-card.scss b/_hugo-theme/assets/scss/docs/modules/_book-card.scss new file mode 100644 index 0000000..18aa5bf --- /dev/null +++ b/_hugo-theme/assets/scss/docs/modules/_book-card.scss @@ -0,0 +1,123 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.book-card { + position: relative; + padding-bottom: 32px; + + @media (min-width: $phone-large) { + min-height: 240px; + padding-bottom: 48px; + } + + $book-size: 142px; + $book-size-mobile: 60px; + $book-shadow: + 0 1px 0 0 #d0d0d0, + 0 10px 0 -4px #dedede, + 0 11px 0 -4px #d0d0d0, + 0 11px 20px -4px rgba(black, .16); + + .book { + position: absolute; + width: $book-size; + box-shadow: $book-shadow; + + &:after { + content: ''; + position: absolute; + display: block; + width: 1px; + height: 6px; + background: #d0d0d0; + bottom: -7px; + left: 2px; + float: left; + transform: skewX(40deg); + } + + @media (max-width: $phone-large) { + width: $book-size-mobile; + } + + img { + padding: 0; + } + } + + .book-info { + padding-left: $book-size + 32px; + + @media (max-width: $phone-large) { + padding-left: $book-size-mobile + 20px; + } + + .book-title { + white-space: normal; + + &:after { + display: none; + } + + &:hover { + text-decoration: none; + + h3 { + color: $link-color; + } + } + + .book-subtitle { + font-family: $main-font; + font-size: 15px; + color: $text-color; + margin-top: -4px; + margin-bottom: 8px; + } + } + + .author { + font-size: 15px; + color: $gray-500; + margin-bottom: 8px; + } + + .description { + @media (max-width: $tablet) { + text-align: left; + } + } + + h3 { + padding-top: 4px; + margin-bottom: 6px; + + @media (max-width: $phone-large) { + padding-top: 0; + } + } + } +} diff --git a/_hugo-theme/assets/scss/docs/modules/_diagram.scss b/_hugo-theme/assets/scss/docs/modules/_diagram.scss new file mode 100644 index 0000000..9668f0a --- /dev/null +++ b/_hugo-theme/assets/scss/docs/modules/_diagram.scss @@ -0,0 +1,114 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.diagram-box { + margin: 24px 0 32px; +} + +// The diagram visibility controls by `js/docs/architecture-diagram.js`. +#spine-architecture-diagram { + visibility: hidden; +} + +.architecture-link { + cursor: pointer; + color: $link-color; + border-bottom:1px dotted $link-color; + + &:hover { + color: $link-hover-color; + } +} + +.full-screen-preview { + font-family: $main-font; + + .preview-header { + padding: 24px 24px 16px; + border-bottom: 1px solid rgba(0, 0, 0, .12); + + .preview-title { + font-size: 1.25rem; + font-weight: 700; + line-height: 1.4; + color: $black; + padding: 0; + margin: 0; + } + + .preview-subtitle { + font-size: 15px; + color: $text-color; + line-height: 1.6; + margin: 8px 0 16px; + max-width: 500px; + } + + .close-btn-wrapper { + float: right; + + .close-btn { + display: block; + cursor: pointer; + line-height: 0; + padding: 1rem; + margin: -14px -1rem -1rem auto; // `-14px` is used to align the icon with the title text. + + .close-icon { + @include close-icon; + } + + &:hover { + .close-icon { + opacity: .87; + } + } + } + } + } + + .preview-body { + padding: 24px 24px 56px; + + svg { + display: block; + margin: 0 auto; + max-width: 1424px; + } + } +} + +p.full-screen-link { + margin-bottom: 24px; + + i { + margin-right: 8px; + } + + span { + font-size: 15px; + } +} diff --git a/_hugo-theme/assets/scss/docs/modules/_docs-category-card.scss b/_hugo-theme/assets/scss/docs/modules/_docs-category-card.scss new file mode 100644 index 0000000..b5b15d4 --- /dev/null +++ b/_hugo-theme/assets/scss/docs/modules/_docs-category-card.scss @@ -0,0 +1,98 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.docs-card-container { + display: grid; + grid-template-columns: repeat(2, minmax(200px, 1fr)); + gap: 24px; + margin-bottom: 24px; + + @media (max-width: $phone-xlarge) { + grid-template-columns: 1fr; + } + + a:hover { + text-decoration: none; + } +} + +.docs-category-card { + $card-padding: 20px; + $card-border-radius: 6px; + $card-shadow: + 0 -1px 1px 0 rgba(0, 0, 0, .07), + 0 2px 4px 0 rgba(35, 37, 38, .12); + $card-hover-shadow: 0 6px 12px rgba(0, 0, 0, .12); + + display: flex; + padding: $card-padding; + box-shadow: $card-shadow; + border-radius: $card-border-radius; + + i { + font-size: 24px; + margin-right: 20px; + color: $main-brand-color; + } + + &:hover { + text-decoration: none; + color: inherit; + box-shadow: $card-hover-shadow; + + i { + color: $main-brand-color; + } + + .card-content { + .title { + color: $link-color; + } + } + } + + .card-content { + .title, + .description { + font-family: $main-font; + color: $text-color; + text-align: left; + line-height: 1.5; + } + + .title { + font-weight: 700; + font-size: 16px; + margin-bottom: 4px; + } + + .description { + font-weight: 400; + font-size: 14px; + margin: 0; + } + } +} diff --git a/_hugo-theme/assets/scss/docs/modules/_interactive-toc.scss b/_hugo-theme/assets/scss/docs/modules/_interactive-toc.scss new file mode 100644 index 0000000..ea47ecf --- /dev/null +++ b/_hugo-theme/assets/scss/docs/modules/_interactive-toc.scss @@ -0,0 +1,98 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* +The TOC can be with the left indicator line or without it. +Manages by adding the corresponding class. +*/ + +.interactive-toc { + $toc-item-font-size: 12px; + $toc-item-color: $gray-700; + $toc-item-line-height: 1.5; + $toc-item-active-color: $main-brand-color; + $toc-item-bottom-space: 12px; + $toc-indicator-width: 1px; + $toc-indicator-line-color: rgba(0, 0, 0, .12); + $toc-indicator-color: $main-brand-color; + + #TableOfContents { + margin-bottom: 0; + padding-left: 12px; + + ul { + list-style: none; + margin-bottom: $toc-item-bottom-space; + + li { + font-size: $toc-item-font-size; + margin-bottom: $toc-item-bottom-space; + line-height: $toc-item-line-height; + + a { + text-decoration: none; + color: $toc-item-color; + font-weight: 400; + padding-right: 6px; + + &:hover { + color: $toc-item-active-color; + } + + &.current { + color: $toc-item-active-color; + font-weight: 600; + } + } + + ul { + margin: $toc-item-bottom-space 0 0 $toc-item-bottom-space; + } + } + } + } + + .toc-indicator { + display: none; + } + + &.with-indicator-line { + position: relative; + + #TableOfContents { + border-left: $toc-indicator-width solid $toc-indicator-line-color; + padding-left: 16px; + } + + .toc-indicator { + position: absolute; + left: 0; + width: $toc-indicator-width; + background: $toc-indicator-color; + transition: top .3s ease; + } + } +} diff --git a/_hugo-theme/assets/scss/docs/modules/_layout.scss b/_hugo-theme/assets/scss/docs/modules/_layout.scss new file mode 100644 index 0000000..87fc775 --- /dev/null +++ b/_hugo-theme/assets/scss/docs/modules/_layout.scss @@ -0,0 +1,116 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +$doc-sidenav-desktop-width: 200px; +$doc-sidenav-tablet-width: 200px; +$doc-toc-width: 220px; +$doc-sidenav-background: $gray-100; + +.docs { + background-color: $body-light-gray-color; + + @media (max-width: $phone-xlarge) { + background-color: white; + } + + .page-content { + display: flex; + justify-content: center; + flex: 1 1 0; + padding: 0; + margin-top: 0; + + &.with-colored-sidenav { + @include breakpoint-min($doc-sidenav-mobile-breakpoint) { + background: linear-gradient(90deg, $doc-sidenav-background 0%, white 50%); + } + + .content-col { + background-color: white; + } + } + } + + .content-holder { + width: 100%; + } + + .content-columns { + padding: 0 15px; + + @media (max-width: $doc-sidenav-mobile-breakpoint) { + padding: 0; + } + + .doc-sidenav-col, + .toc-col { + padding: 24px 0 24px; + } + + .content-col { + display: flex; + flex-direction: column; + padding: 24px 15px 48px; + + @include breakpoint($doc-sidenav-mobile-breakpoint) { + padding: 16px 0 48px; + } + } + + .article-container { + flex-grow: 1; + } + + .sticky-col { + position: sticky; + align-self: start; + top: $header-height; + } + } + + .three-column { + position: relative; + display: grid; + grid-template-columns: $doc-sidenav-desktop-width minmax(0, 1fr) $doc-toc-width; + height: 100%; + + @include breakpoint(desktop) { + grid-template-columns: $doc-sidenav-tablet-width minmax(0, 1fr); + + .toc-col { + display: none; + } + } + + @include breakpoint($doc-sidenav-mobile-breakpoint) { + display: block; + + .doc-sidenav-col { + display: none; + } + } + } +} diff --git a/_hugo-theme/assets/scss/docs/modules/_next-prev-nav.scss b/_hugo-theme/assets/scss/docs/modules/_next-prev-nav.scss new file mode 100644 index 0000000..0d59958 --- /dev/null +++ b/_hugo-theme/assets/scss/docs/modules/_next-prev-nav.scss @@ -0,0 +1,84 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.next-prev-nav { + $space-between: 16px; + $label-offset: 24px; + $font-family: $main-font; + $icon-offset: 8px; + + display: flex; + padding: 32px 0 16px; + margin-top: auto; + + .item { + flex: 1 1 auto; + width: 50%; + margin: 0; + padding: 0; + } + + .previous { + padding-right: $space-between/2; + } + + .next { + padding-left: $space-between/2; + text-align: right; + } + + .arrow-link { + display: flex; + align-items: center; + + &:after, + &:before { + content: ''; + display: none; + border: solid $main-brand-color; + border-width: 0 2px 2px 0; + padding: 3px; + } + + &.prev { + &:before { + display: block; + transform: rotate(135deg); + margin-right: $icon-offset; + } + } + + &.next { + justify-content: flex-end; + + &:after { + display: block; + transform: rotate(-45deg); + margin-left: $icon-offset; + } + } + } +} diff --git a/_hugo-theme/assets/scss/docs/modules/_note-block.scss b/_hugo-theme/assets/scss/docs/modules/_note-block.scss new file mode 100644 index 0000000..8aa4949 --- /dev/null +++ b/_hugo-theme/assets/scss/docs/modules/_note-block.scss @@ -0,0 +1,96 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.note-block { + padding: 12px 24px 13px; + color: $black; + border-radius: $border-radius-s; + margin-bottom: 24px; + + &.note { + background-color: $note-bg-color; + border-left: 4px solid $main-brand-color; + } + + &.warning { + background-color: #fffde6; + border-left: 4px solid $warning-color; + } + + &.lead { + padding: 8px 0 0 0; + margin-bottom: 32px; + + p { + font-family: $main-font; + font-size: 18px; + font-weight: 300; + letter-spacing: .2px; + } + } + + code { + background-color: transparent; + padding: 0; + } + + p:last-child { + margin-bottom: 0; + } +} + +/* TODO:2025-12-01:julia.evseeva: Delete the following styles after migrating content. */ +.lead { + font-family: $main-font; + font-size: 18px; + font-weight: 300; + letter-spacing: .2px; + padding-top: 8px; + margin-bottom: 32px; + } + +.note, +.warning { + padding: 12px 24px 13px; + color: $black; + border-radius: $border-radius-s; + margin-bottom: 24px; + + code { + background-color: transparent; + padding: 0; + } +} + +.note { + background-color: $note-bg-color; + border-left: 4px solid $main-brand-color; +} + +.warning { + background-color: #fffde6; + border-left: 4px solid $warning-color; +} diff --git a/_hugo-theme/assets/scss/docs/modules/_person-card.scss b/_hugo-theme/assets/scss/docs/modules/_person-card.scss new file mode 100644 index 0000000..b0b0271 --- /dev/null +++ b/_hugo-theme/assets/scss/docs/modules/_person-card.scss @@ -0,0 +1,83 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.person-card { + $avatar-size: 100px; + $avatar-size-mobile: 60px; + + position: relative; + padding-bottom: 40px; + + .avatar { + position: absolute; + padding: 0; + width: $avatar-size; + height: $avatar-size; + border-radius: 50%; + + @media (max-width: $phone-large) { + width: $avatar-size-mobile; + height: $avatar-size-mobile; + } + } + + .person-info { + padding-left: $avatar-size + 20px; + + @media (max-width: $phone-large) { + padding-left: $avatar-size-mobile + 20px; + } + + .social-networks { + padding-bottom: 14px; + + a { + padding-right: 16px; + + &:after { + display: none; + } + + &:hover { + text-decoration: none; + + i { + color: $gray-500; + } + } + } + + i { + font-size: 18px; + color: $gray-200; + } + } + + h3 { + padding-top: 4px; + } + } +} diff --git a/_hugo-theme/assets/scss/docs/modules/_sidenav.scss b/_hugo-theme/assets/scss/docs/modules/_sidenav.scss new file mode 100755 index 0000000..54188db --- /dev/null +++ b/_hugo-theme/assets/scss/docs/modules/_sidenav.scss @@ -0,0 +1,250 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +$sidenav-link-top-level-font-size: 14px; +$sidenav-link-font-size: 13px; +$sidenav-link-color: rgba(0, 0, 0, .54); +$sidenav-link-color-active: $black; +$sidenav-link-chevron-border-size: 1px solid rgba(0, 0, 0, .4); +$sidenav-link-chevron-border-size-active: 1px solid rgba(0, 0, 0, .7); +$sidenav-link-chevron-size: 6px; +$sidenav-first-level-left-padding: 24px; +$sidenav-second-level-left-padding: calc(#{$sidenav-first-level-left-padding} + 16px); +$sidenav-third-level-left-padding: calc(#{$sidenav-second-level-left-padding} + 16px); +$sticky-docs-sidenav-width: $doc-sidenav-desktop-width + $sidenav-first-level-left-padding; +$divider-color: rgba(0, 0, 0, .08); + +$sidenav-holder-padding: 32px 24px 32px 16px; +$sidenav-title-left-padding: 22px; + +.doc-sidenav { + margin-left: -$sidenav-first-level-left-padding; + width: $sticky-docs-sidenav-width; + list-style: none; + + @media(max-width: $tablet-large){ + margin: 0; + width: 100%; + max-height: none !important; // Unsets calculated max-height for the sticky element on mobile. + } + + li { + list-style: none; + line-height: 22px; + } + + .sidenav-link { + position: relative; + display: block; + text-decoration: none; + font-size: $sidenav-link-top-level-font-size; + padding: 8px $sidenav-first-level-left-padding; + color: $sidenav-link-color; + font-weight: 400; + cursor: pointer; + + @media (max-width: $tablet-large) { + padding: 12px $sidenav-first-level-left-padding; + } + + // Tree title with chevron. + &.tree-title { + color: $sidenav-link-color-active; + + &:before { + content: ''; + position: absolute; + display: inline-block; + border-right: $sidenav-link-chevron-border-size-active; + border-bottom: $sidenav-link-chevron-border-size-active; + width: $sidenav-link-chevron-size; + height: $sidenav-link-chevron-size; + top: 14px; + left: 8px; + transform: rotate(45deg); + transition: all .3s ease-in-out; + + @media (max-width: $tablet-large) { + top: 18px; + } + } + + &.collapsed { + color: $sidenav-link-color; + + &:before { + border-right: $sidenav-link-chevron-border-size; + border-bottom: $sidenav-link-chevron-border-size; + top: 15px; + transform: rotate(-45deg); + + @media (max-width: $tablet-large) { + top: 19px; + } + } + } + } + + &:hover { + background-color: rgba(0, 0, 0, .03); + text-decoration: none; + border-radius: $border-radius-s; + } + + &.active { + color: $sidenav-link-color-active; + font-weight: 600; + } + } + + .subnav { + .sidenav-link { + font-size: $sidenav-link-font-size; + padding-left: $sidenav-second-level-left-padding; + + // Tree title with chevron + &.tree-title { + &:before { + left: calc(#{$sidenav-first-level-left-padding} - 3px); + } + } + } + + .subnav { + position: relative; + + // Side nav vertical progress bar + &:before { + content: ''; + position: absolute; + background: $divider-color; + display: block; + left: $sidenav-second-level-left-padding; + top: 13px; + bottom: 13px; + width: 2px; + } + + .sidenav-link { + padding-left: $sidenav-third-level-left-padding; + + &.active { + &:before { + content: ''; + position: absolute; + background: rgba(0, 0, 0, .6); + display: block; + width: 2px; + height: 20px; + top: 9px; + left: $sidenav-second-level-left-padding; + } + } + } + } + } +} + +.mobile-sidenav-header { + display: none; + + @media(max-width: $doc-sidenav-mobile-breakpoint) { + display: flex; + justify-content: flex-end; + + .icon-wrapper { + position: fixed; + display: flex; + align-items: center; + justify-content: center; + top: 16px; + right: 16px; + width: 48px; + height: 48px; + background-color: rgba(255, 255, 255, .9); + border-radius: 50%; + cursor: pointer; + transition: background-color .2s ease-in-out; + z-index: 1; + + &:hover { + background-color: rgba(0, 0, 0, .03); + } + + .close-icon { + @include close-icon; + } + } + } +} + +.mobile-sidenav-holder { + @media(max-width: $doc-sidenav-mobile-breakpoint) { + display: none; + position: fixed !important; + background-color: white; + top: 0 !important; + left: 0; + width: 100%; + height: 100vh; + padding: $sidenav-holder-padding !important; + overflow-x: auto; + transition: all .4s ease-in-out; + z-index: map_get($z-index, 'side-nav-mobile'); + } +} + +.mobile-sidenav-opened { + @media(max-width: $doc-sidenav-mobile-breakpoint) { + overflow: hidden; + } + + .mobile-sidenav-holder { + display: block !important; + } +} + +#mobile-sidenav-toggle { + display: none; + + @media(max-width: $doc-sidenav-mobile-breakpoint) { + display: block; + padding: 0 15px; + cursor: pointer; + color: $main-brand-color; + font-size: 15px; + margin: 24px 0 8px; + + @media (max-width: $phone-xlarge) { + padding: 0; + } + + i { + margin-right: 8px; + font-size: 16px; + } + } +} diff --git a/_hugo-theme/assets/scss/docs/pages/_resources.scss b/_hugo-theme/assets/scss/docs/pages/_resources.scss new file mode 100644 index 0000000..9f6f48a --- /dev/null +++ b/_hugo-theme/assets/scss/docs/pages/_resources.scss @@ -0,0 +1,35 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +.resources { + h1 { + margin-bottom: 6px; + } + + h1 + p { + margin-bottom: 48px; + } +} diff --git a/_hugo-theme/assets/scss/fonts/_index.scss b/_hugo-theme/assets/scss/fonts/_index.scss index a86af40..44600bb 100644 --- a/_hugo-theme/assets/scss/fonts/_index.scss +++ b/_hugo-theme/assets/scss/fonts/_index.scss @@ -24,6 +24,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +// Common theme styles from the `TeamDev-Ltd/site-commons`. +@import "../fonts/icon-font"; + @import "roboto"; @import "pt-serif"; diff --git a/_hugo-theme/config/_default/hugo.toml b/_hugo-theme/config/_default/hugo.toml new file mode 100644 index 0000000..8648819 --- /dev/null +++ b/_hugo-theme/config/_default/hugo.toml @@ -0,0 +1,6 @@ +[params] + defaultCodeTheme = 'dark' + +# The third-party libraries from the `site-commons`. +[params.libs.js_cookie] + enabled = true diff --git a/_hugo-theme/content/docs/1/_index.md b/_hugo-theme/content/docs/1/_index.md new file mode 100644 index 0000000..6fcdd2e --- /dev/null +++ b/_hugo-theme/content/docs/1/_index.md @@ -0,0 +1,37 @@ +--- +title: Documentation +headline: Documentation +--- + +# Welcome + +{{% note-block class="lead" %}} +Welcome to the Spine developer documentation. This page gives +the overview of the documentation sections. +{{% /note-block %}} + +## [Quick Start](docs/quick-start/) +In this section you can learn what it's like to develop with Spine by going +through the code of the [Hello World]({{% get-site-data "spine.examples" %}}/hello/) +example. + +## [Introduction](docs/introduction/) +This section gives an overview of the development process, the architecture of +the Spine-based application, information on DDD concepts implemented by the +framework and how framework users deal with them. + +## [Guides](docs/guides/validation) +This section provides detailed instructions on the framework use. + +## [Client Libraries](docs/client-libs/) +This section provides language-specific guides for building client-side applications. + +## [API Reference](docs/reference/) +This sections provides links to the generated documentation. + +## [Examples](docs/examples/) +This page is the entry point for learning from the code of +the [example applications]({{% get-site-data "spine.examples" %}}). + +## [DDD Resources](docs/resources/) +A brief selection of learning materials we recommend to the colleagues in DDD. diff --git a/_hugo-theme/content/docs/1/introduction/_index.md b/_hugo-theme/content/docs/1/introduction/_index.md new file mode 100644 index 0000000..7eba104 --- /dev/null +++ b/_hugo-theme/content/docs/1/introduction/_index.md @@ -0,0 +1,256 @@ +--- +title: Development Process +headline: Documentation +--- + +# Development Process + +{{% note-block class="lead" %}} +Building a solution based on Spine Event Engine framework is an iterative process +which consists of the stages described in this document. +{{% /note-block %}} + +## Getting domain knowledge + +The purpose of this step is to find out what we're going to build and why. +Consider using [EventStorming](https://eventstorming.com) or another domain discovery +approach for grasping the knowledge from the experts. + +Most likely that the solution would have several [Bounded Contexts](docs/introduction/concepts#bounded-context). +For each context developers need to define: + * Signals + - [Events](docs/introduction/concepts#event) + - [Commands](docs/introduction/concepts#command) + - [Rejections](docs/introduction/concepts#rejection) + * Entities + - [Aggregates](docs/introduction/concepts#aggregate) + - [Process Managers](docs/introduction/concepts#process-manager) + - [Projections](docs/introduction/concepts#projection). + +It is likely that some of the bits of this picture would change during the process. +But the whole team, including domain experts, need to have complete understanding of how the +business works to avoid “surprises” down the road. + +We return to learning the domain when we discover inconsistencies in the model, +or we need more information about how the business works, or the business wants to develop further +and we need to update the model. + +Once we got enough domain knowledge we proceed to the implementation. + +## Implementing a Bounded Context + +At this stage we select one of the Bounded Contexts for the implementation. +Each context is developed separately. In this sense it can be seen as a microservice. +It would be natural to start implementing the context which initiates the business flow. + +### Defining data types + +Implementation starts from defining data types of the selected context as Protobuf messages. + +The first step is to define entity [IDs](docs/introduction/concepts#identifier). For example: +```proto +// The identifier for a task. +message TaskId { + string uuid = 1; +} +``` + +Then commands, events, rejections are defined: +```proto +// A command to create a new task. +message CreateTask { + TaskId id = 1; + string name = 2 [(required) = true]; + string description = 3; +} +``` + +```proto +// A new task has been created. +message TaskCreated { + TaskId task = 1; + string name = 2 [(required) = true]; + string description = 3; + UserId who_created = 4 [(required) = true]; +} +``` + +Then we define states of entities. + +```proto +message Task { + option (entity).kind = AGGREGATE; + TaskId id = 1; + string name = 2 [(required) = true]; + string description = 3; + UserId owner = 4 [(required) = true]; + DeveloperId assignee = 5; +} +``` + +[Value Objects](docs/introduction/concepts#value-objects) are added when they +are needed to describe entities or messages like commands or events. + +### Adding business logic + +The business logic of a Bounded Context is based on [Entities](docs/introduction#entities). +They handle messages updating the state in response. Entities like `Aggregate`s and +`ProcessManager`s can generate events. `ProcessManager`s can also generate new commands. +`Projection`s only consume events. + +Updating the state of the domain model in response to messages and generating new messages is +the “life” of the domain model. Messages are delivered to entities by [Repositories](docs/introduction#repositories). + +#### Entities + +During this step we create entity classes and add message handling methods to them. +Code snippets below show `Aggregate` and `Projection` classes with their handler methods. + +```java +final class TaskAggregate + extends Aggregate { + + @Assign + TaskCreated handle(CreateTask cmd, CommandContext ctx) { + return TaskCreated + .newBuilder() + .setTask(cmd.getId()) + .setName(cmd.getName()) + .setDescription(cmd.getDescription()) + .setWhoCreated(ctx.getActor()) + .vBuild(); + } + + @Apply + void event(TaskCreated e) { + builder().setName(e.getName()) + .setDescription(e.getDescription()) + .setOwner(e.getWhoCreated()); + } +} +``` + +```java +final class TaskItemProjection + extends Projection { + + @Subscribe + void on(TaskCreated e) { + builder().setTask(e.getTask()) + .setName(e.getName()) + } + + @Subscribe + void on(TaskCompleted e, EventContext ctx) { + builder().setWhenDone(ctx.getTimestamp()); + } +} +``` + +#### Repositories +The framework provides default implementations for repositories. +A custom `Repository` class may be needed for: + * Dispatching messages to entities in a non-standard way. + By default, a command is dispatched using the first field of the command message + as an ID of the target entity. + An event is dispatched by the ID of the entity which emitted the event. + * Domain-specific operations on entities of this kind. + +Repositories are added to the Bounded Context they belong when it is created: + +```java +BoundedContext tasksContext = BoundedContext.multiTenant("Tasks") + .add(TaskAggregate.class) // use default repository impl. + .add(new TaskItemProjectionRepository()) + .build(); +``` + +This wires repositories into the message delivery mechanism of the corresponding +[Buses](docs/introduction/concepts#message-buses). + +#### Testing +Implementation of the Bounded Context is tested using the messaging paradigm. +The following code snippet asserts that handling a command `CreateTask` produces one +`TaskCreated` event with expected arguments. + +```java +// Given +BlackBoxBoundedContext context = BlackBoxBoundedContext.from(tasksContext); + +// When +context.receivesCommand(createTask()); + +// Then +TaskCreated expected = TaskCreated.newBuilder() + .setTask(id) + .setName(name) + .build(); + +EventSubject assertEvents = + context.assertEvents() + .withType(TaskCreated.class) + +assertEvents.hasSize(1); +assertEvents.message(0) + .comparingExpectedFieldsOnly() + .isEqualTo(expected); +``` + +Modification of entities is also tested. The following code snippet asserts that the state +of the `TaskAggregate` was also updated with expected arguments. + +```java +EntitySubject assertEntity = + context.assertEntityWithState(Task.class, id); +Task expectedState = Task.newBuilder() + .setId(id) + .setName(name) + .build(); +assertEntity.hasStateThat() + .comparingExpectedFieldsOnly() + .isEqualTo(expectedState); +``` + +## Deployment + +### Configuring Server Environment + +For information on configuring server environment of a Spine-based application, please +see the reference documentation of the [`ServerEnvironment`]({{% get-site-data "spine.core_api_doc" %}}/server/server/io.spine.server/-server-environment) +class. + +### Assembling Application + +The server-side application is composed with its Bounded Contexts. + +```java +Server server = Server.atPort(portNumber) + .add(tasksContext) + .add(usersContext) + .add(commentsContext) + .build(); +server.start(); +``` + +This exposes [`CommandService`](docs/introduction/concepts#command-service), +[`QueryService`](docs/introduction/concepts#query-service), and +[`SubscriptionService`](docs/introduction/concepts#subscription-service) to client-side connections. + +## Repeating the cycle + +The stages described above are repeated as another Bounded Context is added to the implementation, +or as some changes or extensions to the existing contexts are required. + +## Client application development + +Development of client applications may start after the [data types are defined](docs/introduction#defining-data-types). +Once this is done, developers run the Spine Model Compiler to generate the code for all supported +client platforms. + +Since entity classes like `Projection` use composition with state types, you don't have to deal +with DTOs. You can start writing the code which subscribes or queries these types right after +they are defied in the `.proto` files, and the Model Compiler finishes its job. +Client applications can also subscribe to events generated by Bounded Contexts at the backend. + +For more information on the client-side development, please refer to +the [Client Libraries](docs/client-libs/) section. diff --git a/_hugo-theme/content/docs/1/introduction/architecture.md b/_hugo-theme/content/docs/1/introduction/architecture.md new file mode 100644 index 0000000..fdff314 --- /dev/null +++ b/_hugo-theme/content/docs/1/introduction/architecture.md @@ -0,0 +1,28 @@ +--- +title: Architecture +headline: Documentation +customjs: js/docs/architecture-diagram.js +--- + +# Application Architecture + +A Spine-based application consists of several Bounded Contexts. Client applications interact +with the server-side via `CommandService`, `QueryService`, and `SubscriptionService`. + +The diagram below shows all server-side components +of a cloud application. When developing with Spine, you will be interacting +with only some of them, which +are not shaded on the diagram. The rest is handled by the framework. + +Click on a component to navigate to its definition from the +[Concepts](docs/introduction/concepts/) page. + +
+ +{{< read-relative-asset "diagrams/spine-architecture-diagram.svg" >}} +
diff --git a/_hugo-theme/content/docs/1/introduction/diagrams/_index.md b/_hugo-theme/content/docs/1/introduction/diagrams/_index.md new file mode 100644 index 0000000..d8bc4b5 --- /dev/null +++ b/_hugo-theme/content/docs/1/introduction/diagrams/_index.md @@ -0,0 +1,4 @@ +--- +_build: + render: false +--- diff --git a/_hugo-theme/content/docs/1/introduction/diagrams/spine-architecture-diagram-full-screen.html b/_hugo-theme/content/docs/1/introduction/diagrams/spine-architecture-diagram-full-screen.html new file mode 100644 index 0000000..c61ba75 --- /dev/null +++ b/_hugo-theme/content/docs/1/introduction/diagrams/spine-architecture-diagram-full-screen.html @@ -0,0 +1,26 @@ +--- +title: Application Architecture +layout: full-screen +customjs: js/docs/architecture-diagram.js +--- + +
+
+
+ + + +
+
+

Application Architecture

+

This diagram shows + all server-side components + of a cloud application. When developing with Spine, you will be interacting with + some of them.

+
+
+
+ {{< read-relative-asset "spine-architecture-diagram.svg" >}} +
+
diff --git a/_hugo-theme/content/docs/1/introduction/diagrams/spine-architecture-diagram.svg b/_hugo-theme/content/docs/1/introduction/diagrams/spine-architecture-diagram.svg new file mode 100644 index 0000000..ffebcf3 --- /dev/null +++ b/_hugo-theme/content/docs/1/introduction/diagrams/spine-architecture-diagram.svg @@ -0,0 +1,576 @@ + + diagram-content + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bounded Context + + + + + System Context + + + System Context + + + + + + + + + + + + + + + + + + + + + + Aggregate + Repository + + + + + + + + + + + + + + + + + + + + Aggregate + + + + + Events + + + + + + + + + + + + + + + + + + + + + Projection + Repository + + + + + + + + + + + + + + + + + + + + Projection + + + + + + + + + + + + + + + + + + + + Process + Manager + Repository + + + + + + + + + + + + + + + + + + + + Process + Manager + + + + + + Event Bus + + + + + + Command Servic + e + + + + + + Query Sevic + e + + + + + + Subscription Servic + e + + + + + + Stand + + + + + + Command + Dispatche + r + + + + + + Aggregate Mirro + r + + + + + + + Event + Stor + e + + + + + + + Command + Stor + e + + + + + Aggregate States + + + + + + Integration + Events + + + + + + Queries + + + + + + Results + + + + + + Subscribe + + + + + + Updates + + + + + + Acks + + + + + Aggregate States + + + + + Client API + + + + + + Command Bus + + + + + + + + + + + + + + + + + Commands + + + + + + + + Write-side + + + Read-side + + + Cloud Application + + + Client Applications + + + + + + + + + + + + + + + + + + + + + + diff --git a/_hugo-theme/content/docs/1/resources/_index.md b/_hugo-theme/content/docs/1/resources/_index.md new file mode 100644 index 0000000..a8e69b1 --- /dev/null +++ b/_hugo-theme/content/docs/1/resources/_index.md @@ -0,0 +1,50 @@ +--- +title: Resources +headline: DDD Resources +--- + +{{< docs-card-container >}} + +{{< docs-category-card + icon="fas fa-book" + title="Books" + url="docs/resources/books/" >}} +The concepts and practical guidance. +{{< /docs-category-card >}} + +{{< docs-category-card + icon="far fa-user-friends" + title="People" + url="docs/resources/people/" >}} +The creators and drivers of the DDD ideas. +{{< /docs-category-card >}} + +{{< docs-category-card + icon="far fa-comment-lines" + title="Blogs" + url="docs/resources/blogs/" >}} +The ideas unfolding in real time. +{{< /docs-category-card >}} + +{{< docs-category-card + icon="far fa-window" + title="Sites" + url="docs/resources/sites/" >}} +Learning hubs. +{{< /docs-category-card >}} + +{{< docs-category-card + icon="fas fa-users" + title="Communities" + url="docs/resources/communities/" >}} +Places to discuss DDD with other practitioners. +{{< /docs-category-card >}} + +{{< docs-category-card + icon="far fa-code" + title="Libraries and Frameworks" + url="docs/resources/libraries/" >}} +Other tools that help with DDD in code. +{{< /docs-category-card >}} + +{{< /docs-card-container >}} diff --git a/_hugo-theme/content/docs/1/resources/books.md b/_hugo-theme/content/docs/1/resources/books.md new file mode 100644 index 0000000..881a9b8 --- /dev/null +++ b/_hugo-theme/content/docs/1/resources/books.md @@ -0,0 +1,61 @@ +--- +title: Books +headline: DDD Resources +bodyclass: docs resources +--- + +# Books + +{{% note-block class="lead" %}} +Key works to get familiar with the approach. +{{% /note-block %}} + +{{< book-card + image="ddd-design.png" + title="Domain-Driven Design" + subtitle="Tackling Complexity in the Heart of Software" + author="Eric Evans" + book_url="https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215" >}} +The Big Blue Book which lay the basics of Domain-Driven Design methodology. +It provides a broad framework for making design decisions and a vocabulary for +discussing domain design. +{{< /book-card >}} + +{{< book-card + image="ddd-design-reference.png" + title="Domain-Driven Design Reference" + author="Eric Evans" + book_url="https://www.amazon.com/Domain-Driven-Design-Reference-Definitions-Summaries/dp/1457501198" >}} +This book provides a brief overview of the DDD methodology. +It also defines the terms, which were coined in this topic since 2004. +{{< /book-card >}} + +{{< book-card + image="implementing-ddd.png" + title="Implementing Domain-Driven Design" + author="Vaughn Vernon" + book_url="https://www.informit.com/store/implementing-domain-driven-design-9780133039894" >}} +The Big Red Book provides practical guidance on how to apply DDD. Building on +Eric Evans’ seminal book, Domain-Driven Design, the author presents practical +DDD techniques through examples from familiar domains. +{{< /book-card >}} + +{{< book-card + image="ddd-distilled.png" + title="Domain-Driven Design Distilled" + author="Vaughn Vernon" + book_url="https://www.informit.com/store/domain-driven-design-distilled-9780134434988" >}} +If you are new to Domain-Driven Design, this book and the Domain-Driven Design +Reference by Eric Evans are the best way to get into the topic. +{{< /book-card >}} + +{{< book-card + image="event-storming.png" + title="Introducing EventStorming" + subtitle="An act of deliberate collective learning" + author="Alberto Brandolini" + book_url="https://www.eventstorming.com/book/" >}} +The deepest tutorial and explanation about EventStorming, straight from the +inventor. It provides guidance on leveraging the potential of this collaborative +brainstorming technique used to identify domain events. +{{< /book-card >}} diff --git a/_hugo-theme/content/docs/1/resources/people.md b/_hugo-theme/content/docs/1/resources/people.md new file mode 100644 index 0000000..897bda7 --- /dev/null +++ b/_hugo-theme/content/docs/1/resources/people.md @@ -0,0 +1,58 @@ +--- +title: People +headline: DDD Resources +bodyclass: docs resources +--- + +# People + +{{% note-block class="lead" %}} +The creators and drivers of the DDD ideas. +{{% /note-block %}} + +{{< person-card + photo="eric-evans.png" + name="Eric Evans" + socials=`[ + {"url":"https://domainlanguage.com/", "icon":"far fa-globe"}, + {"url":"https://twitter.com/ericevans0", "icon":"fab fa-twitter"} + ]`>}} +The author of the DDD methodology. Domain linguist. The author +of “Domain-Driven Design: Tackling Complexity in Software”. +{{< /person-card >}} + +{{< person-card + photo="vaughn-vernon.png" + name="Vaughn Vernon" + socials=`[ + {"url":"https://github.com/VaughnVernon", "icon":"fab fa-github"}, + {"url":"https://twitter.com/VaughnVernon", "icon":"fab fa-twitter"} + ]`>}} +Domain Model Whisperer. The author of “Implementing Domain-Driven Design” +and “Domain-Driven Design Distilled”. Founder of [Vlingo Platform](https://vlingo.io/). +{{< /person-card >}} + +{{< person-card + photo="greg-young.png" + name="Greg Young" + socials=`[ + {"url":"https://github.com/gregoryyoung", "icon":"fab fa-github"}, + {"url":"https://twitter.com/gregyoung", "icon":"fab fa-twitter"} + ]`>}} +Creator of CQRS and the driver of Event Sourcing. +Founder of the [Event Store](https://eventstore.com/). +{{< /person-card >}} + +{{< person-card + photo="alberto-brandolini.png" + name="Alberto Brandolini" + socials=`[ + {"url":"https://github.com/ziobrando", "icon":"fab fa-github"}, + {"url":"https://twitter.com/ziobrando", "icon":"fab fa-twitter"} + ]`>}} +The inventor of #EventStorming. Practicing engineer and a coach. The author of +Introducing “EventStorming – An act of deliberate collective learning”. +{{< /person-card >}} + +And [many more](https://dddeurope.com/2020/speakers/) advancing the approach +every day. diff --git a/_hugo-theme/content/docs/_index.md b/_hugo-theme/content/docs/_index.md new file mode 100644 index 0000000..d8bc4b5 --- /dev/null +++ b/_hugo-theme/content/docs/_index.md @@ -0,0 +1,4 @@ +--- +_build: + render: false +--- diff --git a/_hugo-theme/data/docs/1/sidenav.yml b/_hugo-theme/data/docs/1/sidenav.yml new file mode 100644 index 0000000..e9cd308 --- /dev/null +++ b/_hugo-theme/data/docs/1/sidenav.yml @@ -0,0 +1,75 @@ +- page: Overview + file_path: "" +- page: Quick Start + file_path: quick-start + +- page: Introduction + key: introduction + children: + - page: Development Process + file_path: introduction + - page: Rules + file_path: introduction/rules + - page: Architecture + file_path: introduction/architecture + - page: Project Structure + file_path: introduction/project-structure + - page: Concepts + file_path: introduction/concepts + - page: Naming Conventions + file_path: introduction/naming-conventions + +- page: Guides + key: guides + children: + - page: Starting a new project + file_path: guides/start-new-project + - page: Gradle configuration + file_path: guides/gradle + - page: Validation + file_path: guides/validation + - page: Working with Rejections + file_path: guides/rejections + - page: Integration with a third party + file_path: guides/integration + - page: Related Guides + key: related-guides + children: + - page: Protocol Buffers + url: https://developers.google.com/protocol-buffers/docs/overview + - page: gRPC + url: https://grpc.io/docs/guides/index.html + +- page: Client Libraries + key: client-libs + children: + - page: Java + file_path: client-libs + - page: JavaScript + file_path: client-libs/js + - page: Dart + file_path: client-libs/dart + +- page: API Reference + file_path: reference + +- page: Examples + file_path: examples + +- page: DDD Resources + key: resources + children: + - page: Overview + file_path: resources/ + - page: Books + file_path: resources/books + - page: People + file_path: resources/people + - page: Blogs + file_path: resources/blogs + - page: Sites + file_path: resources/sites + - page: Communities + file_path: resources/communities + - page: Libraries and Frameworks + file_path: resources/libraries diff --git a/_hugo-theme/data/spine.yml b/_hugo-theme/data/spine.yml new file mode 100644 index 0000000..3fcff15 --- /dev/null +++ b/_hugo-theme/data/spine.yml @@ -0,0 +1,18 @@ +examples: https://github.com/spine-examples + +site_repo: https://github.com/SpineEventEngine/SpineEventEngine.github.io +core_jvm_repo: https://github.com/SpineEventEngine/core-jvm +base_libraries_repo: https://github.com/SpineEventEngine/base-libraries +web_repo: https://github.com/SpineEventEngine/web +gcloud_java_repo: https://github.com/SpineEventEngine/gcloud-java +money_repo: https://github.com/SpineEventEngine/money +dart_repo: https://github.com/SpineEventEngine/dart +bootstrap_repo: https://github.com/SpineEventEngine/bootstrap +jdbc_storage_repo: https://github.com/SpineEventEngine/jdbc-storage +time_repo: https://github.com/SpineEventEngine/time + +base_api_doc: https://spine.io/base-libraries/dokka-reference +core_api_doc: https://spine.io/core-jvm/dokka-reference +dart_api_doc: https://spine.io/dart/reference +js_api_doc: https://spine.io/web/reference/client-js +web_api_doc: https://spine.io/web/dokka-reference diff --git a/_hugo-theme/data/versions.yml b/_hugo-theme/data/versions.yml new file mode 100644 index 0000000..3fd5606 --- /dev/null +++ b/_hugo-theme/data/versions.yml @@ -0,0 +1,13 @@ +- short: "1" + full: 1.9.0 + path: docs + is_main: true + switcher: + visible: false + item_visible: false +- short: "2" + full: 2.0.0 + path: docs/2 + switcher: + visible: false + item_visible: false diff --git a/_hugo-theme/layouts/_markup/render-heading.html b/_hugo-theme/layouts/_markup/render-heading.html new file mode 100644 index 0000000..542d5db --- /dev/null +++ b/_hugo-theme/layouts/_markup/render-heading.html @@ -0,0 +1,9 @@ + +{{ .Text | safeHTML }} +{{- if ne .Level 1 -}} +{{- $href := printf "href=#%s" .Anchor -}} +  + +{{- end -}} + diff --git a/_hugo-theme/layouts/_markup/render-image.html b/_hugo-theme/layouts/_markup/render-image.html new file mode 100644 index 0000000..618a43d --- /dev/null +++ b/_hugo-theme/layouts/_markup/render-image.html @@ -0,0 +1,5 @@ +{{ . }} +{{- /* Strip trailing newline. */ -}} diff --git a/_hugo-theme/layouts/_markup/render-link.html b/_hugo-theme/layouts/_markup/render-link.html new file mode 100644 index 0000000..ecf4176 --- /dev/null +++ b/_hugo-theme/layouts/_markup/render-link.html @@ -0,0 +1,25 @@ +{{- $link := .Destination }} +{{- $isMailto := strings.HasPrefix $link "mailto:" -}} +{{- $isAbsolute := strings.HasPrefix $link "http" -}} +{{- $isSamePageAnchor := strings.HasPrefix $link "#" -}} + +{{- $skipNofollow := partial "functions/whitelist-checker.html" $link -}} +{{- $isExternalLink := partial "functions/is-external-link.html" $link -}} + +{{- if or $isAbsolute $isSamePageAnchor -}} + {{- $link = $link | safeURL -}} +{{- else if (not $isMailto) }} + {{- $link = partial "functions/get-doc-link.html" (dict + "link" $link + "page" .Page + ) -}} +{{- end -}} + +{{ .Text | safeHTML }} +{{- /* Strip trailing newline. */ -}} diff --git a/_hugo-theme/layouts/_partials/docs/components/bottom-nav/functions/get-page.html b/_hugo-theme/layouts/_partials/docs/components/bottom-nav/functions/get-page.html new file mode 100644 index 0000000..ae2d743 --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/components/bottom-nav/functions/get-page.html @@ -0,0 +1,41 @@ + + +{{ $page := .page_context }} +{{ $item := .item_context }} + +{{ $currentVersion := partial "functions/get-doc-version.html" $page }} +{{ $filePath := printf "docs/%s/%s" $currentVersion.short $item.file_path }} +{{ $pageURL := "" }} +{{ $pageTitle := $item.page }} + +{{ with site.GetPage $filePath }} + {{ $pageURL = .RelPermalink }} +{{ end }} + +{{ $pageItem := dict "url" $pageURL "title" $pageTitle }} + +{{ return $pageItem }} diff --git a/_hugo-theme/layouts/_partials/docs/components/bottom-nav/functions/get-pages.html b/_hugo-theme/layouts/_partials/docs/components/bottom-nav/functions/get-pages.html new file mode 100644 index 0000000..072d123 --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/components/bottom-nav/functions/get-pages.html @@ -0,0 +1,68 @@ + + + + +{{ $root := .context }} +{{ $sidenav := .sidenav }} +{{ $currentURL := .current_url }} + +{{ $root.Scratch.Set "bottomNavPages" (slice) }} +{{ $root.Scratch.Set "bottomNavCurrentIndex" -1 }} + +{{ range $sidenav }} + {{ template "get-bottom-nav-pages" (dict "root" $root "node" .) }} +{{ end }} + +{{ define "get-bottom-nav-pages" }} + {{ $root := .root }} + {{ $node := .node }} + {{ with $node.children }} + {{ range . }} + {{ template "get-bottom-nav-pages" (dict "root" $root "node" .) }} + {{ end }} + {{ else }} + {{ if or $node.file_path (eq $node.file_path "") }} + {{ $page := partial "docs/components/bottom-nav/functions/get-page.html" (dict + "page_context" $root + "item_context" $node + ) }} + {{ if $page.url }} + {{ $root.Scratch.Add "bottomNavPages" (slice $page) }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} + +{{ $pages := $root.Scratch.Get "bottomNavPages" }} + +{{ range $i, $page := $pages }} + {{ if in $currentURL $page.url }} + {{ $root.Scratch.Set "bottomNavCurrentIndex" $i }} + {{ end }} +{{ end }} diff --git a/_hugo-theme/layouts/_partials/docs/components/bottom-nav/next-prev-nav.html b/_hugo-theme/layouts/_partials/docs/components/bottom-nav/next-prev-nav.html new file mode 100644 index 0000000..9315cc4 --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/components/bottom-nav/next-prev-nav.html @@ -0,0 +1,64 @@ + + +{{ $currentURL := .RelPermalink }} +{{ $currentVersion := partial "functions/get-doc-version.html" . }} +{{ $versionData := index site.Data.docs $currentVersion.short }} + +{{ if $versionData }} + {{ $sidenav := $versionData.sidenav }} + {{ if $sidenav }} + {{ partial "docs/components/bottom-nav/functions/get-pages" (dict + "context" . + "sidenav" $sidenav + "current_url" $currentURL + ) }} + {{ $pages := .Scratch.Get "bottomNavPages" }} + {{ $index := .Scratch.Get "bottomNavCurrentIndex" }} + + {{ end }} + {{ .Scratch.Delete "bottomNavPages" }} + {{ .Scratch.Delete "bottomNavCurrentIndex" }} +{{ end }} diff --git a/_hugo-theme/layouts/_partials/docs/components/content-layout/three-column.html b/_hugo-theme/layouts/_partials/docs/components/content-layout/three-column.html new file mode 100644 index 0000000..cd3b16a --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/components/content-layout/three-column.html @@ -0,0 +1,50 @@ + + +
+
+
+ {{ partial "docs/components/sidenav/mobile-toggle.html" }} +
+ {{ partial "docs/components/sidenav/sidenav.html" . }} +
+
+
+ {{ .Content }} + {{ partial "docs/components/bottom-nav/next-prev-nav.html" . }} +
+
+
+
+
+
+ {{ .TableOfContents }} +
+
+
+
+
+
diff --git a/_hugo-theme/layouts/_partials/docs/components/sidenav/category.html b/_hugo-theme/layouts/_partials/docs/components/sidenav/category.html new file mode 100644 index 0000000..a4b1d25 --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/components/sidenav/category.html @@ -0,0 +1,51 @@ + + +{{ $page := .page_context }} +{{ $item := .item_context }} + +{{ $currentCategory := partial "functions/get-doc-category.html" $page }} +{{ $categoryKey := $item.key }} +{{ $id := print $categoryKey "-category" }} +{{ $isActive := eq $currentCategory $categoryKey }} + +
  • + + {{ $item.page }} + + +
  • diff --git a/_hugo-theme/layouts/_partials/docs/components/sidenav/mobile-header.html b/_hugo-theme/layouts/_partials/docs/components/sidenav/mobile-header.html new file mode 100644 index 0000000..5f7a6b5 --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/components/sidenav/mobile-header.html @@ -0,0 +1,31 @@ + + +
    +
    + +
    +
    diff --git a/_hugo-theme/layouts/_partials/docs/components/sidenav/mobile-toggle.html b/_hugo-theme/layouts/_partials/docs/components/sidenav/mobile-toggle.html new file mode 100644 index 0000000..eb9053f --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/components/sidenav/mobile-toggle.html @@ -0,0 +1,30 @@ + + +
    + + Contents +
    diff --git a/_hugo-theme/layouts/_partials/docs/components/sidenav/page.html b/_hugo-theme/layouts/_partials/docs/components/sidenav/page.html new file mode 100644 index 0000000..5b4dcf6 --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/components/sidenav/page.html @@ -0,0 +1,64 @@ + + +{{ $page := .page_context }} +{{ $item := .item_context }} + +{{ $currentURL := $page.RelPermalink }} +{{ $currentVersion := partial "functions/get-doc-version.html" $page }} + +{{ if or $item.file_path (eq $item.file_path "") }} + {{ $filePath := printf "docs/%s/%s" $currentVersion.short $item.file_path }} + {{ with site.GetPage $filePath }} +
  • + {{ $pageURL := .RelPermalink }} + {{ $isActive := eq $currentURL $pageURL }} + + {{ $item.page }} + +
  • + {{ end }} +{{ else if $item.url }} +
  • + {{ $pageURL := $item.url }} + {{ $isExternalLink := partial "functions/is-external-link.html" $pageURL }} + {{ if $isExternalLink }} + + {{ $item.page }} + + {{ else}} + {{ $isActive := eq $currentURL $pageURL }} + + {{ $item.page }} + + {{ end }} +
  • +{{ end }} diff --git a/_hugo-theme/layouts/_partials/docs/components/sidenav/section.html b/_hugo-theme/layouts/_partials/docs/components/sidenav/section.html new file mode 100644 index 0000000..8f0006d --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/components/sidenav/section.html @@ -0,0 +1,58 @@ + + +{{ $page := .page_context }} +{{ $item := .item_context }} + +{{ $currentSection := partial "functions/get-doc-section.html" $page }} +{{ $sectionKey := $item.key }} +{{ $id := print $sectionKey "-section" }} +{{ $isActive := eq $currentSection $sectionKey }} + +
  • + + {{ $item.page }} + + +
  • diff --git a/_hugo-theme/layouts/_partials/docs/components/sidenav/sidenav.html b/_hugo-theme/layouts/_partials/docs/components/sidenav/sidenav.html new file mode 100644 index 0000000..cad9fdb --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/components/sidenav/sidenav.html @@ -0,0 +1,51 @@ + + +{{ $page := . }} +{{ $currentURL := .RelPermalink }} +{{ $currentVersion := partial "functions/get-doc-version.html" $page }} +{{ $sidenavData := index site.Data.docs $currentVersion.short }} + +{{ if $sidenavData }} + {{ if $sidenavData.sidenav }} + {{ partial "docs/components/sidenav/mobile-header.html" . }} +
      + {{ range $sidenavData.sidenav }} + {{ if .children }} + {{ partial "docs/components/sidenav/section.html" (dict + "page_context" $page + "item_context" . + ) }} + {{ else }} + {{ partial "docs/components/sidenav/page.html" (dict + "page_context" $page + "item_context" . + ) }} + {{ end }} + {{ end }} +
    + {{ end }} +{{ end }} diff --git a/_hugo-theme/layouts/_partials/docs/head/code-theme.html b/_hugo-theme/layouts/_partials/docs/head/code-theme.html new file mode 100644 index 0000000..f61cd31 --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/head/code-theme.html @@ -0,0 +1,38 @@ + + + +{{ $lightTheme := "code-theme/light.css" }} +{{ $darkTheme := "code-theme/dark.css" }} +{{ $defaultCodeTheme := $darkTheme }} +{{ if eq site.Params.defaultCodeTheme "light" }} + {{ $defaultCodeTheme = $lightTheme }} +{{ end }} + diff --git a/_hugo-theme/layouts/_partials/docs/head/icon-font.html b/_hugo-theme/layouts/_partials/docs/head/icon-font.html new file mode 100644 index 0000000..a01cd0c --- /dev/null +++ b/_hugo-theme/layouts/_partials/docs/head/icon-font.html @@ -0,0 +1,27 @@ + + + diff --git a/_hugo-theme/layouts/_partials/functions/get-body-class.html b/_hugo-theme/layouts/_partials/functions/get-body-class.html new file mode 100644 index 0000000..51b8b65 --- /dev/null +++ b/_hugo-theme/layouts/_partials/functions/get-body-class.html @@ -0,0 +1,53 @@ + + + + +{{ if eq .Kind "home" }} + {{ .Scratch.Set "bodyClass" "home" }} +{{ else if eq .Kind "404" }} + {{ .Scratch.Set "bodyClass" "error-pages" }} +{{ else if eq .Kind "page" }} + {{ if in .Type "/" }} + {{ $type := replace .Type "/" " " }} + {{ .Scratch.Set "bodyClass" (print " " $type) }} + {{ else }} + {{ .Scratch.Set "bodyClass" (print " " .Type) }} + {{ end }} +{{ else }} + {{ $type := replace .Type "/" " " }} + {{ .Scratch.Set "bodyClass" $type }} +{{ end }} + +{{ $bodyClass := .Scratch.Get "bodyClass" }} + +{{ with .Params.bodyclass }} + {{ $bodyClass = . }} +{{ end }} + +{{ return $bodyClass }} diff --git a/_hugo-theme/layouts/_partials/functions/get-doc-category.html b/_hugo-theme/layouts/_partials/functions/get-doc-category.html new file mode 100644 index 0000000..cee4bc2 --- /dev/null +++ b/_hugo-theme/layouts/_partials/functions/get-doc-category.html @@ -0,0 +1,39 @@ + + + + +{{ $filePath := "" }} +{{ if $.File }} + {{ $filePath = .File.Path }} +{{ end }} +{{ $pathDir := path.Dir $filePath }} +{{ $pathBase := path.Base $pathDir }} +{{ return $pathBase }} diff --git a/_hugo-theme/layouts/_partials/functions/get-doc-link.html b/_hugo-theme/layouts/_partials/functions/get-doc-link.html new file mode 100644 index 0000000..61bb6f9 --- /dev/null +++ b/_hugo-theme/layouts/_partials/functions/get-doc-link.html @@ -0,0 +1,47 @@ + + + + +{{ $link := .link }} +{{ $pageContext := .page }} + +{{ $currentVersion := partial "functions/get-doc-version.html" $pageContext }} +{{ if and (findRE `^/?docs/[^0-9][^ ]*` $link) (not (findRE `^/?docs/[0-9]+(/|$)` $link)) }} + {{ $link = replaceRE "docs" $currentVersion.path $link }} +{{ end -}} + +{{ $link = $link | relURL }} +{{ return $link }} diff --git a/_hugo-theme/layouts/_partials/functions/get-doc-section.html b/_hugo-theme/layouts/_partials/functions/get-doc-section.html new file mode 100644 index 0000000..842edac --- /dev/null +++ b/_hugo-theme/layouts/_partials/functions/get-doc-section.html @@ -0,0 +1,39 @@ + + + + +{{ $segments := slice }} +{{ if $.File }} + {{ $segments = split .File.Path "/" }} +{{ end }} +{{ $section := index $segments 2 }} +{{ return $section }} diff --git a/_hugo-theme/layouts/_partials/functions/get-doc-version.html b/_hugo-theme/layouts/_partials/functions/get-doc-version.html new file mode 100644 index 0000000..48ce201 --- /dev/null +++ b/_hugo-theme/layouts/_partials/functions/get-doc-version.html @@ -0,0 +1,51 @@ + + + + +{{ $versions := site.Data.versions }} +{{ $mainVersion := index (where $versions "is_main" true) 0 }} +{{ $currentPath := "" }} +{{ with $.Page.File }} + {{ $currentPath = .Path }} +{{ end }} +{{ $currentVersion := "" }} +{{ range $versions }} + {{ if in $currentPath (printf "docs/%s/" .short) }} + {{ $currentVersion = . }} + {{ end }} +{{ end }} +{{ if not $currentVersion }} + {{ $currentVersion = $mainVersion }} +{{ end }} +{{ return $currentVersion }} diff --git a/_hugo-theme/layouts/_partials/functions/get-full-version-name.html b/_hugo-theme/layouts/_partials/functions/get-full-version-name.html new file mode 100644 index 0000000..ae750e5 --- /dev/null +++ b/_hugo-theme/layouts/_partials/functions/get-full-version-name.html @@ -0,0 +1,40 @@ + + + +{{ $currentVersion := . }} +{{ $fullName := "" }} +{{ if $currentVersion.full_i18n_key }} + {{ $fullName = i18n $currentVersion.full_i18n_key }} +{{ else }} + {{ $fullName = $currentVersion.full }} +{{ end }} +{{ return $fullName }} diff --git a/_hugo-theme/layouts/_partials/functions/get-sidenav-title.html b/_hugo-theme/layouts/_partials/functions/get-sidenav-title.html new file mode 100644 index 0000000..50c0491 --- /dev/null +++ b/_hugo-theme/layouts/_partials/functions/get-sidenav-title.html @@ -0,0 +1,40 @@ + + + + +{{ $sidenavTitle := "" }} +{{ if .Params.sidenav_title }} + {{ $sidenavTitle = .Params.sidenav_title }} +{{ else if .Params.Title }} + {{ $sidenavTitle = .Params.Title }} +{{ else }} + {{ $sidenavTitle = "No sidenav_title parameter" }} +{{ end }} +{{ return $sidenavTitle }} diff --git a/_hugo-theme/layouts/_partials/functions/is-external-link.html b/_hugo-theme/layouts/_partials/functions/is-external-link.html new file mode 100644 index 0000000..0a290e2 --- /dev/null +++ b/_hugo-theme/layouts/_partials/functions/is-external-link.html @@ -0,0 +1,32 @@ + + + + +{{ $link := . }} + +{{ $isExternalLink := strings.HasPrefix $link "http" }} +{{ return $isExternalLink }} diff --git a/_hugo-theme/layouts/_partials/scripts/body/baseurl.html b/_hugo-theme/layouts/_partials/scripts/body/baseurl.html new file mode 100644 index 0000000..c9be212 --- /dev/null +++ b/_hugo-theme/layouts/_partials/scripts/body/baseurl.html @@ -0,0 +1,36 @@ + + + + diff --git a/_hugo-theme/layouts/_partials/scripts/head/jquery.html b/_hugo-theme/layouts/_partials/scripts/head/jquery.html new file mode 100644 index 0000000..5bfb2d5 --- /dev/null +++ b/_hugo-theme/layouts/_partials/scripts/head/jquery.html @@ -0,0 +1,4 @@ + diff --git a/_hugo-theme/layouts/_shortcodes/book-card.html b/_hugo-theme/layouts/_shortcodes/book-card.html new file mode 100644 index 0000000..66653a8 --- /dev/null +++ b/_hugo-theme/layouts/_shortcodes/book-card.html @@ -0,0 +1,44 @@ +{{- /* +A component that displays the clickable book card. + +Parameters: + * `image`. The book cover image name. The image should be placed inside `static`. + * `title`. The book title. + * `subtitle`. An optional book subtitle. + * `author`. The book author. + * `book_url`. The URL on a store. +*/ -}} + +{{ $image := .Get "image" }} +{{ $title := .Get "title" }} +{{ $subtitle := .Get "subtitle" }} +{{ $author := .Get "author" }} +{{ $bookURL := .Get "book_url" }} + +{{ $image = print "img/docs/resources/books/" $image }} + +
    + + {{ $title }} book + +
    + +

    {{ $title | markdownify }}

    + {{ with $subtitle }} +

    {{ . | markdownify }}

    + {{ end }} +
    +

    by {{ $author | markdownify }}

    +

    {{ .Inner | markdownify }}

    +
    +
    + +{{- /* Strip trailing newline. */ -}} diff --git a/_hugo-theme/layouts/_shortcodes/docs-card-container.html b/_hugo-theme/layouts/_shortcodes/docs-card-container.html new file mode 100644 index 0000000..ffb48f4 --- /dev/null +++ b/_hugo-theme/layouts/_shortcodes/docs-card-container.html @@ -0,0 +1,10 @@ +{{- /* +A container for `docs-category-card.html` items that displays them +in a two-column grid layout. +*/ -}} + +
    + {{ .Inner }} +
    + +{{- /* Strip trailing newline. */ -}} diff --git a/_hugo-theme/layouts/_shortcodes/docs-category-card.html b/_hugo-theme/layouts/_shortcodes/docs-category-card.html new file mode 100644 index 0000000..7382579 --- /dev/null +++ b/_hugo-theme/layouts/_shortcodes/docs-category-card.html @@ -0,0 +1,33 @@ +{{- /* +A component that displays a clickable category card. + +Parameters: + * `icon`. The icon class. + * `title`. The title of the card. + * `url`. The card destination URL. + * `badges`. The list of badges to be shown near the title. + * `class`. An optional class for extending the styles of a specific card. +*/ -}} + +{{ $icon := .Get "icon" }} +{{ $title := .Get "title" }} +{{ $url := .Get "url" }} +{{ $class := .Get "class" }} + +{{ $url = partial "functions/get-doc-link.html" (dict + "link" $url + "page" .Page +) }} + + + +
    +

    + {{ $title | markdownify }} +

    +

    {{ .Inner | markdownify }}

    +
    +
    + +{{- /* Strip trailing newline. */ -}} diff --git a/_hugo-theme/layouts/_shortcodes/highlight.html b/_hugo-theme/layouts/_shortcodes/highlight.html new file mode 100644 index 0000000..2930bab --- /dev/null +++ b/_hugo-theme/layouts/_shortcodes/highlight.html @@ -0,0 +1,39 @@ +{{- /* +This template extends the Hugo Highlight shortcode with an optional header +that is available if the `file` parameter is provided. Otherwise, renders +the simple code block without layout changes. + +Parameters: + * `lang`. The language of the code block. + * `params`. Optional standard Hugo highlighting parameters as a string. + * `file`. An optional name of the code file to display on the code header panel. +*/ -}} + +{{ $lang := .Get "lang" }} +{{ $params := .Get "params" }} +{{ $file := .Get "file" }} + + +{{ $code := "" }} +{{ if $params }} + {{ $code = highlight (trim .InnerDeindent "\n\r") $lang $params }} +{{ else }} + {{ $code = highlight (trim .InnerDeindent "\n\r") $lang "" }} +{{ end }} + +{{ if $file }} +
    +
    +
    + {{ $file }} +
    +
    +
    + {{ $code }} +
    +
    +{{ else }} + {{ $code }} +{{ end }} + +{{- /* Strip trailing newline. */ -}} diff --git a/_hugo-theme/layouts/_shortcodes/note-block.html b/_hugo-theme/layouts/_shortcodes/note-block.html new file mode 100644 index 0000000..02ee41d --- /dev/null +++ b/_hugo-theme/layouts/_shortcodes/note-block.html @@ -0,0 +1,9 @@ +{{- /* +Renders a content as a note block. +*/ -}} + +
    + {{ .Inner }} +
    + +{{- /* Strip trailing newline. */ -}} diff --git a/_hugo-theme/layouts/_shortcodes/person-card.html b/_hugo-theme/layouts/_shortcodes/person-card.html new file mode 100644 index 0000000..5e35809 --- /dev/null +++ b/_hugo-theme/layouts/_shortcodes/person-card.html @@ -0,0 +1,33 @@ +{{- /* +A component that displays the information about a person. + +Parameters: + * `photo`. The person photo. The photo should be placed inside `static`. + * `name`. The person name. + * `socials`. An array with social icons `[{"url": "", "icon": ""}]`. +*/ -}} + +{{ $photo := .Get "photo" }} +{{ $name := .Get "name" }} +{{ $socials := .Get "socials" | transform.Unmarshal }} + +{{ $photo = print "img/docs/resources/people/" $photo }} + +
    + {{ $name }} photo +
    +

    {{ $name }}

    + +

    {{ .Inner | markdownify }}

    +
    +
    + +{{- /* Strip trailing newline. */ -}} diff --git a/_hugo-theme/layouts/_shortcodes/read-relative-asset.html b/_hugo-theme/layouts/_shortcodes/read-relative-asset.html new file mode 100644 index 0000000..f274e0e --- /dev/null +++ b/_hugo-theme/layouts/_shortcodes/read-relative-asset.html @@ -0,0 +1,13 @@ +{{- /* +Embeds an asset with the relative URL directly inline. + +Useful for SVG diagrams that need to remain interactive +instead of being rendered as static images. +*/ -}} + +{{- $file := .Get 0 -}} +{{- $dir := .Page.File.Dir -}} +{{- $file = print "content/" $dir $file -}} +{{- readFile $file | safeHTML -}} + +{{- /* Strip trailing newline. */ -}} diff --git a/_hugo-theme/layouts/docs/full-screen.html b/_hugo-theme/layouts/docs/full-screen.html new file mode 100644 index 0000000..bf703c8 --- /dev/null +++ b/_hugo-theme/layouts/docs/full-screen.html @@ -0,0 +1,3 @@ +{{ define "main" }} + {{ .Content }} +{{ end }} diff --git a/_hugo-theme/layouts/docs/section.html b/_hugo-theme/layouts/docs/section.html new file mode 100644 index 0000000..98b61ac --- /dev/null +++ b/_hugo-theme/layouts/docs/section.html @@ -0,0 +1,3 @@ +{{ define "main" }} + {{ partial "docs/components/content-layout/three-column.html" . }} +{{ end }} diff --git a/_hugo-theme/layouts/docs/single.html b/_hugo-theme/layouts/docs/single.html new file mode 100644 index 0000000..98b61ac --- /dev/null +++ b/_hugo-theme/layouts/docs/single.html @@ -0,0 +1,3 @@ +{{ define "main" }} + {{ partial "docs/components/content-layout/three-column.html" . }} +{{ end }} diff --git a/_hugo-theme/static/img/docs/resources/books/ddd-design-reference.png b/_hugo-theme/static/img/docs/resources/books/ddd-design-reference.png new file mode 100644 index 0000000..8ef606d Binary files /dev/null and b/_hugo-theme/static/img/docs/resources/books/ddd-design-reference.png differ diff --git a/_hugo-theme/static/img/docs/resources/books/ddd-design.png b/_hugo-theme/static/img/docs/resources/books/ddd-design.png new file mode 100644 index 0000000..e0fcc5f Binary files /dev/null and b/_hugo-theme/static/img/docs/resources/books/ddd-design.png differ diff --git a/_hugo-theme/static/img/docs/resources/books/ddd-distilled.png b/_hugo-theme/static/img/docs/resources/books/ddd-distilled.png new file mode 100644 index 0000000..9d68cc9 Binary files /dev/null and b/_hugo-theme/static/img/docs/resources/books/ddd-distilled.png differ diff --git a/_hugo-theme/static/img/docs/resources/books/event-storming.png b/_hugo-theme/static/img/docs/resources/books/event-storming.png new file mode 100644 index 0000000..663d650 Binary files /dev/null and b/_hugo-theme/static/img/docs/resources/books/event-storming.png differ diff --git a/_hugo-theme/static/img/docs/resources/books/implementing-ddd.png b/_hugo-theme/static/img/docs/resources/books/implementing-ddd.png new file mode 100644 index 0000000..6c4e943 Binary files /dev/null and b/_hugo-theme/static/img/docs/resources/books/implementing-ddd.png differ diff --git a/_hugo-theme/static/img/docs/resources/people/alberto-brandolini.png b/_hugo-theme/static/img/docs/resources/people/alberto-brandolini.png new file mode 100644 index 0000000..eb65fd8 Binary files /dev/null and b/_hugo-theme/static/img/docs/resources/people/alberto-brandolini.png differ diff --git a/_hugo-theme/static/img/docs/resources/people/eric-evans.png b/_hugo-theme/static/img/docs/resources/people/eric-evans.png new file mode 100644 index 0000000..b6e54c2 Binary files /dev/null and b/_hugo-theme/static/img/docs/resources/people/eric-evans.png differ diff --git a/_hugo-theme/static/img/docs/resources/people/greg-young.png b/_hugo-theme/static/img/docs/resources/people/greg-young.png new file mode 100644 index 0000000..affdbde Binary files /dev/null and b/_hugo-theme/static/img/docs/resources/people/greg-young.png differ diff --git a/_hugo-theme/static/img/docs/resources/people/vaughn-vernon.png b/_hugo-theme/static/img/docs/resources/people/vaughn-vernon.png new file mode 100644 index 0000000..1eb2b51 Binary files /dev/null and b/_hugo-theme/static/img/docs/resources/people/vaughn-vernon.png differ diff --git a/_sass/common/_mixins.scss b/_sass/common/_mixins.scss index 061e30b..c5eb100 100644 --- a/_sass/common/_mixins.scss +++ b/_sass/common/_mixins.scss @@ -1,3 +1,30 @@ +/*! + * Copyright 2025, TeamDev. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + // Usage: @include transition(all .3s ease-in-out); @mixin transition($args...) { -webkit-transition: $args; @@ -21,7 +48,7 @@ height: $icon-size--s; background: url('https://spine.io/img/x-black.svg') no-repeat center/cover; opacity: .26; - @include transition(all .3s ease-in-out); + transition: all .3s ease-in-out; } // Ordered and unordered list styles.