Migrate docudjeex to Docus v4 with EN/FR content

This commit is contained in:
Djeex
2026-08-30 16:41:37 +02:00
commit c51fcd5df6
241 changed files with 41143 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
export default defineAppConfig({
docus: {
locale: 'en',
colorMode: 'dark',
},
navigation: {
sub: 'header',
},
header: {
title: 'Docudjeex',
logo: {
light: '/img/logo.svg',
dark: '/img/logo.svg',
alt: 'Docudjeex',
},
},
socials: {
gitea: 'https://git.djeex.fr/Djeex/docudjeex',
},
github: {
url: 'https://github.com/Djeex/docudjeex',
},
ui: {
colors: {
primary: 'cyan',
neutral: 'zinc',
},
prose: {
card: {
slots: {
base: 'bg-[rgba(12,13,12,0.8)] border-[#121110]',
},
},
pre: {
slots: {
base: 'bg-[#121110] border-[#201e1b] rounded-lg',
header: 'bg-[#121110] border-[#201e1b]',
},
},
},
header: {
slots: {
root: 'bg-[rgba(12,13,12,0.8)] backdrop-blur-[20px] backdrop-saturate-200 border-b border-default h-(--ui-header-height) sticky top-0 z-50',
},
},
contentSearchButton: {
slots: {
base: 'bg-[rgba(12,13,12,0.8)] hover:bg-[rgba(18,17,16,0.9)] border border-[#121110]',
},
},
contentSurround: {
slots: {
link: 'bg-[rgba(12,13,12,0.8)] border-[#121110] hover:bg-primary/10 hover:border-primary',
linkLeading: 'bg-[rgba(12,13,12,0.8)] ring-1 ring-[var(--ui-text-highlighted)]/50 group-hover:bg-primary/10 group-hover:ring-primary/50',
},
},
kbd: {
compoundVariants: [
{
color: 'neutral',
variant: 'subtle',
class: 'ring-[#121110] bg-[rgba(12,13,12,0.8)] text-default',
},
],
},
},
})
+28
View File
@@ -0,0 +1,28 @@
/* Restore the old site's near-black dark background (#0B0A0A) instead of
Nuxt UI's default zinc-900 */
.dark {
--ui-bg: #0B0A0A;
/* Same border color used on cards, applied sitewide (header, separators,
the horizontal nav menu row, etc.) for a consistent look */
--ui-border: #121110;
}
/* Old site's container was 1280px with 24px padding each side (1232px of
actual content). Nuxt UI's container uses a bigger lg:px-8 (32px) padding,
so the max-width is bumped to 81rem (1296px) to land on the same 1232px
content width rather than reproducing the outer 1280px figure verbatim. */
:root {
--ui-container: 81rem;
}
/* Docus hardcodes --ui-header-height to 112px (64px header + 48px sub-nav
bar) whenever navigation.sub is 'header', regardless of what's actually
in that bar. Our horizontal menu now lives in the main header row itself
(AppHeaderCenter.vue) and the sub-nav bar (AppHeaderBottom.vue) is empty,
so the header is back to a single 64px row. */
@media (min-width: 1024px) {
.docus-sub-header {
--ui-header-height: 4rem !important;
}
}
+141
View File
@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 1000 1000">
<!-- Generator: Adobe Illustrator 30.7.0, SVG Export Plug-In . SVG Version: 2.1.4 Build 114) -->
<defs>
<style>
.st0 {
fill: url(#Dégradé_sans_nom_5);
}
.st1 {
fill: url(#Dégradé_sans_nom_264);
stroke: url(#Dégradé_sans_nom_334);
}
.st1, .st2, .st3, .st4, .st5, .st6, .st7, .st8, .st9, .st10, .st11, .st12 {
stroke-miterlimit: 10;
}
.st2 {
fill: url(#Dégradé_sans_nom_262);
stroke: url(#Dégradé_sans_nom_332);
}
.st3 {
fill: url(#Dégradé_sans_nom_269);
stroke: url(#Dégradé_sans_nom_339);
}
.st4 {
fill: url(#Dégradé_sans_nom_263);
stroke: url(#Dégradé_sans_nom_333);
}
.st5 {
fill: url(#Dégradé_sans_nom_265);
stroke: url(#Dégradé_sans_nom_335);
}
.st6 {
fill: url(#Dégradé_sans_nom_268);
stroke: url(#Dégradé_sans_nom_338);
}
.st7 {
fill: url(#Dégradé_sans_nom_261);
stroke: url(#Dégradé_sans_nom_331);
}
.st8 {
fill: url(#Dégradé_sans_nom_266);
stroke: url(#Dégradé_sans_nom_336);
}
.st9 {
fill: url(#Dégradé_sans_nom_267);
stroke: url(#Dégradé_sans_nom_337);
}
.st10 {
fill: url(#Dégradé_sans_nom_26);
stroke: url(#Dégradé_sans_nom_33);
}
.st11 {
fill: url(#Dégradé_sans_nom_2610);
stroke: url(#Dégradé_sans_nom_3310);
}
.st12 {
fill: url(#Dégradé_sans_nom_2611);
stroke: url(#Dégradé_sans_nom_3311);
}
.st13 {
fill: #fff;
}
.st14 {
fill: url(#Dégradé_sans_nom_51);
}
</style>
<linearGradient id="Dégradé_sans_nom_5" data-name="Dégradé sans nom 5" x1="245" y1="503" x2="747" y2="503" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#55c3ec"/>
<stop offset="1" stop-color="#1d71b8" stop-opacity=".8"/>
</linearGradient>
<linearGradient id="Dégradé_sans_nom_51" data-name="Dégradé sans nom 5" x1="399.4" y1="504.3" x2="595.1" y2="504.3" xlink:href="#Dégradé_sans_nom_5"/>
<linearGradient id="Dégradé_sans_nom_26" data-name="Dégradé sans nom 26" x1="74.5" y1="560.2" x2="106.2" y2="591.8" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#55c3ec"/>
<stop offset="1" stop-color="#1d71b8" stop-opacity=".8"/>
</linearGradient>
<linearGradient id="Dégradé_sans_nom_33" data-name="Dégradé sans nom 33" x1="74.2" y1="559.9" x2="106.5" y2="592.2" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#55c3ec"/>
<stop offset="1" stop-color="#1d71b8" stop-opacity=".5"/>
</linearGradient>
<linearGradient id="Dégradé_sans_nom_261" data-name="Dégradé sans nom 26" x1="158.2" y1="648.8" x2="176.7" y2="667.3" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_331" data-name="Dégradé sans nom 33" x1="157.8" y1="648.4" x2="177.1" y2="667.7" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_262" data-name="Dégradé sans nom 26" x1="210.2" y1="714.7" x2="249.8" y2="754.3" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_332" data-name="Dégradé sans nom 33" x1="209.9" y1="714.3" x2="250.2" y2="754.6" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_263" data-name="Dégradé sans nom 26" x1="-54" y1="72.2" x2="-14.4" y2="111.8" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_333" data-name="Dégradé sans nom 33" x1="-54.4" y1="71.9" x2="-14.1" y2="112.2" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_264" data-name="Dégradé sans nom 26" x1="485.1" y1="-9.2" x2="503.7" y2="9.4" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_334" data-name="Dégradé sans nom 33" x1="484.8" y1="-9.6" x2="504" y2="9.7" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_265" data-name="Dégradé sans nom 26" x1="825.1" y1="682.3" x2="856.8" y2="713.9" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_335" data-name="Dégradé sans nom 33" x1="824.8" y1="681.9" x2="857.1" y2="714.3" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_266" data-name="Dégradé sans nom 26" x1="308.5" y1="356.5" x2="340.3" y2="388.3" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_336" data-name="Dégradé sans nom 33" x1="308.1" y1="356.2" x2="340.7" y2="388.7" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_267" data-name="Dégradé sans nom 26" x1="540.4" y1="450.4" x2="559" y2="469" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_337" data-name="Dégradé sans nom 33" x1="540.1" y1="450" x2="559.4" y2="469.3" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_268" data-name="Dégradé sans nom 26" x1="-336.4" y1="326.9" x2="-296.8" y2="366.5" gradientTransform="translate(342.9 490.5) rotate(-175.4)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_338" data-name="Dégradé sans nom 33" x1="-336.7" y1="326.5" x2="-296.4" y2="366.8" gradientTransform="translate(342.9 490.5) rotate(-175.4)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_269" data-name="Dégradé sans nom 26" x1="115" y1="-29.9" x2="133.6" y2="-11.3" gradientTransform="translate(814.9 151.4) rotate(139.6)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_339" data-name="Dégradé sans nom 33" x1="114.7" y1="-30.2" x2="134" y2="-11" gradientTransform="translate(814.9 151.4) rotate(139.6)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_2610" data-name="Dégradé sans nom 26" x1="94.5" y1="304.2" x2="124.4" y2="334" gradientTransform="translate(568 142) rotate(97.9)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_3310" data-name="Dégradé sans nom 33" x1="94.2" y1="303.8" x2="124.7" y2="334.4" gradientTransform="translate(568 142) rotate(97.9)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_2611" data-name="Dégradé sans nom 26" x1="435.8" y1="254.1" x2="454.4" y2="272.7" gradientTransform="translate(257.1 -349) rotate(52.9)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_3311" data-name="Dégradé sans nom 33" x1="435.5" y1="253.8" x2="454.8" y2="273.1" gradientTransform="translate(257.1 -349) rotate(52.9)" xlink:href="#Dégradé_sans_nom_33"/>
</defs>
<g id="Calque_1">
<circle class="st13" cx="499.5" cy="499.5" r="499.5"/>
<g>
<path class="st0" d="M618.3,252h-244.6c-72.1,0-128.7,59.2-128.7,128.7v244.6c0,72.1,59.2,128.7,128.7,128.7h244.6c72.1,0,128.7-59.2,128.7-128.7v-244.6c0-72.1-59.2-128.7-128.7-128.7ZM497.3,656.2c-82.4,0-151.9-69.5-151.9-151.9s66.9-151.9,151.9-151.9,151.9,69.5,151.9,151.9-69.5,151.9-151.9,151.9ZM659.5,378.2c-20.6,0-36-15.4-36-36s15.4-36,36-36,36,15.4,36,36c0,20.6-15.4,36-36,36Z"/>
<path class="st14" d="M497.3,406.5c-54.1,0-97.8,43.8-97.8,97.8s43.8,97.8,97.8,97.8,97.8-43.8,97.8-97.8-43.8-97.8-97.8-97.8Z"/>
</g>
</g>
<g id="Calque_2">
<g id="Calque_3">
<circle class="st10" cx="90.4" cy="576" r="22.4"/>
<circle class="st7" cx="175.6" cy="607.9" r="13.1"/>
<circle class="st2" cx="140.8" cy="691.6" r="28"/>
<circle class="st4" cx="829.7" cy="602.6" r="28"/>
<circle class="st1" cx="908.9" cy="562.1" r="13.1"/>
<circle class="st5" cx="840.9" cy="698.1" r="22.4"/>
<circle class="st8" cx="466.1" cy="876.5" r="22.5"/>
<circle class="st9" cx="538.6" cy="839.8" r="13.1"/>
<circle class="st6" cx="686.1" cy="170.1" r="28"/>
<circle class="st3" cx="733.7" cy="247.7" r="13.1"/>
<circle class="st11" cx="236.9" cy="206.5" r="21.1"/>
<circle class="st12" cx="315.4" cy="164.9" r="13.1"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.8 KiB

+154
View File
@@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 1000 1000">
<!-- Generator: Adobe Illustrator 29.7.1, SVG Export Plug-In . SVG Version: 2.1.1 Build 8) -->
<defs>
<style>
.st0 {
fill: url(#Dégradé_sans_nom_265);
stroke: url(#Dégradé_sans_nom_33);
}
.st0, .st1, .st2, .st3, .st4, .st5, .st6, .st7, .st8, .st9, .st10, .st11 {
stroke-miterlimit: 10;
}
.st1 {
fill: url(#Dégradé_sans_nom_269);
stroke: url(#Dégradé_sans_nom_334);
}
.st2 {
fill: url(#Dégradé_sans_nom_268);
stroke: url(#Dégradé_sans_nom_333);
}
.st3 {
fill: url(#Dégradé_sans_nom_266);
stroke: url(#Dégradé_sans_nom_331);
}
.st4 {
fill: url(#Dégradé_sans_nom_267);
stroke: url(#Dégradé_sans_nom_332);
}
.st12 {
fill: url(#Dégradé_sans_nom_261);
}
.st13 {
fill: url(#Dégradé_sans_nom_262);
}
.st14 {
fill: url(#Dégradé_sans_nom_264);
}
.st15 {
fill: url(#Dégradé_sans_nom_263);
}
.st5 {
fill: url(#Dégradé_sans_nom_2616);
stroke: url(#Dégradé_sans_nom_3311);
}
.st6 {
fill: url(#Dégradé_sans_nom_2615);
stroke: url(#Dégradé_sans_nom_3310);
}
.st16 {
fill: #fff;
}
.st17 {
fill: url(#Dégradé_sans_nom_26);
}
.st7 {
fill: url(#Dégradé_sans_nom_2610);
stroke: url(#Dégradé_sans_nom_335);
}
.st8 {
fill: url(#Dégradé_sans_nom_2613);
stroke: url(#Dégradé_sans_nom_338);
}
.st9 {
fill: url(#Dégradé_sans_nom_2614);
stroke: url(#Dégradé_sans_nom_339);
}
.st10 {
fill: url(#Dégradé_sans_nom_2611);
stroke: url(#Dégradé_sans_nom_336);
}
.st11 {
fill: url(#Dégradé_sans_nom_2612);
stroke: url(#Dégradé_sans_nom_337);
}
</style>
<linearGradient id="Dégradé_sans_nom_26" data-name="Dégradé sans nom 26" x1="373.2" y1="159.5" x2="625.1" y2="411.5" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#55c3ec"/>
<stop offset="1" stop-color="#1d71b8" stop-opacity=".8"/>
</linearGradient>
<linearGradient id="Dégradé_sans_nom_261" data-name="Dégradé sans nom 26" x1="143.1" y1="200.5" x2="395" y2="452.4" gradientTransform="translate(30.8 109.3)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_262" data-name="Dégradé sans nom 26" x1="81.3" y1="60.6" x2="333.2" y2="312.5" gradientTransform="translate(187.1 873.6) rotate(-90)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_263" data-name="Dégradé sans nom 26" x1="-44.4" y1="16.5" x2="207.5" y2="268.4" gradientTransform="translate(705.4 808.2) rotate(-180)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_264" data-name="Dégradé sans nom 26" x1="-67.9" y1="-58.9" x2="184" y2="193" gradientTransform="translate(770.9 385.1) rotate(90)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_265" data-name="Dégradé sans nom 26" x1="74.5" y1="560.2" x2="106.2" y2="591.8" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_33" data-name="Dégradé sans nom 33" x1="74.2" y1="559.9" x2="106.5" y2="592.2" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#55c3ec"/>
<stop offset="1" stop-color="#1d71b8" stop-opacity=".5"/>
</linearGradient>
<linearGradient id="Dégradé_sans_nom_266" data-name="Dégradé sans nom 26" x1="158.2" y1="648.8" x2="176.7" y2="667.3" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_331" data-name="Dégradé sans nom 33" x1="157.8" y1="648.4" x2="177.1" y2="667.7" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_267" data-name="Dégradé sans nom 26" x1="210.2" y1="714.7" x2="249.8" y2="754.3" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_332" data-name="Dégradé sans nom 33" x1="209.9" y1="714.3" x2="250.2" y2="754.6" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_268" data-name="Dégradé sans nom 26" x1="-54" y1="72.2" x2="-14.4" y2="111.8" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_333" data-name="Dégradé sans nom 33" x1="-54.4" y1="71.9" x2="-14.1" y2="112.2" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_269" data-name="Dégradé sans nom 26" x1="485.1" y1="-9.2" x2="503.7" y2="9.4" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_334" data-name="Dégradé sans nom 33" x1="484.8" y1="-9.6" x2="504" y2="9.7" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_2610" data-name="Dégradé sans nom 26" x1="825.1" y1="682.3" x2="856.8" y2="713.9" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_335" data-name="Dégradé sans nom 33" x1="824.8" y1="681.9" x2="857.1" y2="714.3" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_2611" data-name="Dégradé sans nom 26" x1="308.5" y1="356.5" x2="340.3" y2="388.3" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_336" data-name="Dégradé sans nom 33" x1="308.1" y1="356.2" x2="340.7" y2="388.7" gradientTransform="translate(909.8 659.5) rotate(105)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_2612" data-name="Dégradé sans nom 26" x1="540.4" y1="450.4" x2="559" y2="469" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_337" data-name="Dégradé sans nom 33" x1="540.1" y1="450" x2="559.4" y2="469.3" gradientTransform="translate(661.8 133.9) rotate(60)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_2613" data-name="Dégradé sans nom 26" x1="-336.4" y1="326.9" x2="-296.8" y2="366.5" gradientTransform="translate(342.9 490.5) rotate(-175.4)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_338" data-name="Dégradé sans nom 33" x1="-336.7" y1="326.5" x2="-296.4" y2="366.8" gradientTransform="translate(342.9 490.5) rotate(-175.4)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_2614" data-name="Dégradé sans nom 26" x1="115" y1="-29.9" x2="133.6" y2="-11.3" gradientTransform="translate(814.9 151.4) rotate(139.6)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_339" data-name="Dégradé sans nom 33" x1="114.7" y1="-30.2" x2="134" y2="-11" gradientTransform="translate(814.9 151.4) rotate(139.6)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_2615" data-name="Dégradé sans nom 26" x1="94.5" y1="304.2" x2="124.4" y2="334" gradientTransform="translate(568 142) rotate(97.9)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_3310" data-name="Dégradé sans nom 33" x1="94.2" y1="303.8" x2="124.7" y2="334.4" gradientTransform="translate(568 142) rotate(97.9)" xlink:href="#Dégradé_sans_nom_33"/>
<linearGradient id="Dégradé_sans_nom_2616" data-name="Dégradé sans nom 26" x1="435.8" y1="254.1" x2="454.4" y2="272.7" gradientTransform="translate(257.1 -349) rotate(52.9)" xlink:href="#Dégradé_sans_nom_26"/>
<linearGradient id="Dégradé_sans_nom_3311" data-name="Dégradé sans nom 33" x1="435.5" y1="253.8" x2="454.8" y2="273.1" gradientTransform="translate(257.1 -349) rotate(52.9)" xlink:href="#Dégradé_sans_nom_33"/>
</defs>
<g id="Calque_1">
<circle class="st16" cx="499.5" cy="499.5" r="499.5"/>
</g>
<g id="Calque_2">
<g id="Calque_3">
<ellipse class="st17" cx="499.2" cy="285.5" rx="139.8" ry="209.5"/>
<ellipse class="st12" cx="299.9" cy="435.8" rx="139.8" ry="209.5" transform="translate(-207.3 586.3) rotate(-72)"/>
<ellipse class="st13" cx="373.6" cy="666.3" rx="209.5" ry="139.8" transform="translate(-385.1 576.9) rotate(-54)"/>
<ellipse class="st15" cx="623.9" cy="665.8" rx="139.8" ry="209.5" transform="translate(-272.2 493.9) rotate(-36)"/>
<ellipse class="st14" cx="703.9" cy="443.1" rx="209.5" ry="139.8" transform="translate(-94.9 211.2) rotate(-16)"/>
<circle class="st0" cx="90.4" cy="576" r="22.4"/>
<circle class="st3" cx="175.6" cy="607.9" r="13.1"/>
<circle class="st4" cx="140.8" cy="691.6" r="28"/>
<circle class="st2" cx="829.7" cy="602.6" r="28"/>
<circle class="st1" cx="908.9" cy="562.1" r="13.1"/>
<circle class="st7" cx="840.9" cy="698.1" r="22.4"/>
<circle class="st10" cx="466.1" cy="876.5" r="22.5"/>
<circle class="st11" cx="538.6" cy="839.8" r="13.1"/>
<circle class="st8" cx="686.1" cy="170.1" r="28"/>
<circle class="st9" cx="733.7" cy="247.7" r="13.1"/>
<circle class="st6" cx="236.9" cy="206.5" r="21.1"/>
<circle class="st5" cx="315.4" cy="164.9" r="13.1"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.6 KiB

+102
View File
@@ -0,0 +1,102 @@
<script setup lang="ts">
const appConfig = useAppConfig()
const { forced: forcedColorMode } = useDocusColorMode()
const { isEnabled: isAssistantEnabled } = useAssistant()
const { isEnabled, locales } = useDocusI18n()
const { subNavigationMode } = useSubNavigation()
const links = computed(() => {
const list = []
if (appConfig.socials?.gitea) {
list.push({
'icon': 'i-simple-icons-gitea',
'to': appConfig.socials.gitea,
'target': '_blank',
'aria-label': 'Gitea',
})
}
if (appConfig.github?.url) {
list.push({
'icon': 'i-simple-icons-github',
'to': appConfig.github.url,
'target': '_blank',
'aria-label': 'GitHub',
})
}
return list
})
</script>
<template>
<UHeader
:ui="{ center: 'flex-1' }"
:class="{ 'flex flex-col': subNavigationMode === 'header' }"
>
<AppHeaderCenter />
<template #left>
<AppHeaderLeft />
</template>
<template #right>
<AppHeaderCTA />
<template v-if="isAssistantEnabled">
<AssistantChat />
</template>
<template v-if="isEnabled && locales.length > 1">
<ClientOnly>
<LanguageSelect />
<template #fallback>
<div class="h-8 w-8 animate-pulse bg-neutral-200 dark:bg-neutral-800 rounded-md" />
</template>
</ClientOnly>
<USeparator
orientation="vertical"
class="h-8"
/>
</template>
<UContentSearchButton class="lg:hidden" />
<ClientOnly v-if="!forcedColorMode">
<UColorModeButton />
<template #fallback>
<div class="h-8 w-8 animate-pulse bg-neutral-200 dark:bg-neutral-800 rounded-md" />
</template>
</ClientOnly>
<template v-if="links?.length">
<UButton
v-for="(link, index) of links"
:key="index"
v-bind="{ color: 'neutral', variant: 'ghost', ...link }"
/>
</template>
</template>
<template #toggle="{ open, toggle }">
<IconMenuToggle
:open="open"
class="lg:hidden"
@click="toggle"
/>
</template>
<template #body>
<AppHeaderBody />
</template>
<template
v-if="subNavigationMode === 'header'"
#bottom
>
<AppHeaderBottom />
</template>
</UHeader>
</template>
+3
View File
@@ -0,0 +1,3 @@
<template>
<div />
</template>
+47
View File
@@ -0,0 +1,47 @@
<script setup lang="ts">
const { sections } = useSubNavigation()
const navMenuVariants = useUIConfig('navigationMenu')
</script>
<template>
<template v-if="sections.length">
<!-- Empty spacer: keeps the header's flex-1 center slot from collapsing
while the real menu below is absolutely positioned so it can match
the article's content-column width instead of this slot's width. -->
<div class="hidden lg:block w-full" />
<UContainer class="absolute inset-x-0 inset-y-0 hidden lg:flex items-center pointer-events-none">
<!-- Mirrors the docs page's actual layout: an outer 10-col grid (left
doc-tree sidebar = col-span-2) containing a second, nested 10-col
grid for the article body (right TOC sidebar = col-span-2 of that
inner grid). Matching both levels is what lines this menu up with
the real content column instead of a naive single-level fraction. -->
<div class="grid grid-cols-10 gap-10 w-full pointer-events-auto">
<div class="col-span-8 col-start-3 grid grid-cols-10 gap-10">
<div class="col-span-8 col-start-1">
<UNavigationMenu
:items="sections"
:highlight="navMenuVariants.highlight ?? true"
:highlight-color="navMenuVariants.highlightColor"
:variant="navMenuVariants.variant ?? 'pill'"
:color="navMenuVariants.color"
class="-mx-[10px] w-[calc(100%+20px)] [&>div]:w-full"
:ui="{ list: 'w-full justify-between', item: 'py-0' }"
/>
</div>
</div>
</div>
</UContainer>
</template>
<UContentSearchButton
v-else
:collapsed="false"
class="w-full"
variant="soft"
:ui="{
leadingIcon: 'size-4 mx-0.5',
}"
/>
</template>
+43
View File
@@ -0,0 +1,43 @@
<script setup lang="ts">
withDefaults(defineProps<{
width?: string
height?: string
zIndex?: string
top?: string
left?: string
right?: string
blur?: string
colors?: string[]
}>(), {
width: '10rem',
height: '10rem',
zIndex: '10',
top: '0',
left: 'auto',
right: 'auto',
blur: '50px',
colors: () => ['rgba(0, 71, 225, 0.34)', 'rgba(26, 214, 255, 0.22)', 'rgba(0, 71, 225, 0.22)'],
})
</script>
<template>
<div
class="pointer-events-none absolute w-full"
:style="{
top,
insetInlineStart: left,
insetInlineEnd: right,
zIndex,
maxWidth: width,
height,
filter: `blur(${blur})`,
}"
>
<div
class="w-full h-full"
:style="{
background: `linear-gradient(97.62deg, ${colors[0]} 2.27%, ${colors[1]} 65%, ${colors[2]} 98.48%)`,
}"
/>
</div>
</template>
+17
View File
@@ -0,0 +1,17 @@
<script setup lang="ts">
const { sidebarNavigation } = useSubNavigation()
const contentNavVariants = useUIConfig('contentNavigation')
</script>
<template>
<UContentNavigation
:collapsible="true"
:default-open="false"
:highlight="contentNavVariants.highlight ?? true"
:highlight-color="contentNavVariants.highlightColor"
:variant="contentNavVariants.variant ?? 'link'"
:color="contentNavVariants.color"
:navigation="sidebarNavigation"
/>
</template>
+30
View File
@@ -0,0 +1,30 @@
<script setup lang="ts">
const { subNavigationMode, sections } = useSubNavigation()
</script>
<template>
<div
v-if="subNavigationMode === 'aside'"
class="mb-2"
>
<UPageAnchors :links="sections" />
<USeparator
type="dashed"
class="my-4"
/>
</div>
<div
v-else
class="mb-4"
>
<UContentSearchButton
:collapsed="false"
class="w-full"
variant="soft"
:ui="{
leadingIcon: 'size-4 mx-0.5',
}"
/>
</div>
</template>
+102
View File
@@ -0,0 +1,102 @@
<script setup lang="ts">
import { useClipboard } from '@vueuse/core'
import { joinURL, withTrailingSlash } from 'ufo'
import { useRuntimeConfig } from '#imports'
const route = useRoute()
const toast = useToast()
const runtimeConfig = useRuntimeConfig()
const appBaseURL = runtimeConfig.app?.baseURL || '/'
const mcpRoute = (runtimeConfig.public.mcp as { route?: string } | undefined)?.route || '/mcp'
const { copy, copied } = useClipboard()
const { t } = useDocusI18n()
const markdownLink = computed(() => `${window?.location?.origin}${withTrailingSlash(appBaseURL)}raw${route.path}.md`)
const mcpServerUrl = computed(() => `${window?.location?.origin}${joinURL(appBaseURL, mcpRoute)}`)
const mcpDeeplink = computed(() => `${window?.location?.origin}${joinURL(appBaseURL, mcpRoute, 'deeplink')}`)
const items = computed(() => [
[{
label: t('docs.copy.link'),
icon: 'i-lucide-link',
onSelect() {
copy(markdownLink.value)
},
},
{
label: t('docs.copy.view'),
icon: 'i-simple-icons:markdown',
target: '_blank',
to: markdownLink.value,
},
{
label: t('docs.copy.gpt'),
icon: 'i-simple-icons:openai',
target: '_blank',
to: `https://chatgpt.com/?hints=search&q=${encodeURIComponent(`Read ${markdownLink.value} so I can ask questions about it.`)}`,
},
{
label: t('docs.copy.claude'),
icon: 'i-simple-icons:anthropic',
target: '_blank',
to: `https://claude.ai/new?q=${encodeURIComponent(`Read ${markdownLink.value} so I can ask questions about it.`)}`,
}],
[
{
label: 'Copy MCP Server URL',
icon: 'i-lucide-link',
onSelect() {
copy(mcpServerUrl.value)
toast.add({
title: 'Copied to clipboard',
icon: 'i-lucide-check-circle',
})
},
},
{
label: 'Add MCP Server',
icon: 'i-simple-icons:cursor',
target: '_blank',
to: mcpDeeplink.value,
},
],
])
async function copyPage() {
const page = await $fetch<string>(`/raw${route.path}.md`)
copy(page)
}
</script>
<template>
<UFieldGroup size="sm">
<UButton
:label="t('docs.copy.page')"
:icon="copied ? 'i-lucide-check' : 'i-lucide-copy'"
color="neutral"
variant="soft"
class="bg-[rgba(12,13,12,0.8)] hover:bg-[rgba(18,17,16,0.9)] border border-[#121110]"
:ui="{
leadingIcon: 'text-neutral size-3.5',
}"
@click="copyPage"
/>
<UDropdownMenu
size="sm"
:items="items"
:content="{
align: 'end',
side: 'bottom',
sideOffset: 8,
}"
>
<UButton
icon="i-lucide-chevron-down"
color="neutral"
variant="soft"
class="bg-[rgba(12,13,12,0.8)] hover:bg-[rgba(18,17,16,0.9)] border border-[#121110] border-l-[#121110]"
/>
</UDropdownMenu>
</UFieldGroup>
</template>
+164
View File
@@ -0,0 +1,164 @@
<script setup lang="ts">
import { kebabCase } from 'scule'
import type { ContentNavigationItem, Collections, DocsCollectionItem } from '@nuxt/content'
import { findPageHeadline } from '@nuxt/content/utils'
definePageMeta({
layout: 'docs',
})
const route = useRoute()
const { locale, isEnabled, t } = useDocusI18n()
const { isOpen } = useAssistant()
const appConfig = useAppConfig()
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
const collectionName = computed(() => isEnabled.value ? `docs_${locale.value}` : 'docs')
const [{ data: page }, { data: surround }] = await Promise.all([
useAsyncData(kebabCase(route.path), () => queryCollection(collectionName.value as keyof Collections).path(route.path).first() as Promise<DocsCollectionItem>),
useAsyncData(`${kebabCase(route.path)}-surround`, () => {
return queryCollectionItemSurroundings(collectionName.value as keyof Collections, route.path, {
fields: ['description'],
})
}),
])
if (!page.value) {
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
}
const title = page.value.seo?.title || page.value.title
const description = page.value.seo?.description || page.value.description
const headline = ref(findPageHeadline(navigation?.value, page.value?.path))
const breadcrumbs = computed(() => findPageBreadcrumbs(navigation?.value, page.value?.path || ''))
// Set `hideHeader: true` in a page's frontmatter to skip the title/description
// block entirely (e.g. for a page that builds its own custom layout).
const hideHeader = computed(() => !!(page.value as unknown as Record<string, unknown>)?.hideHeader)
// Set `hideCopyPage: true` in a page's frontmatter to hide the "Copy page"
// dropdown (copy link / view as markdown / open in ChatGPT / Claude).
const hideCopyPage = computed(() => !!(page.value as unknown as Record<string, unknown>)?.hideCopyPage)
// Set `hideToc: true` in a page's frontmatter to hide the right-hand
// "On this page" table-of-contents sidebar.
const hideToc = computed(() => !!(page.value as unknown as Record<string, unknown>)?.hideToc)
useSeo({
title,
description,
type: 'article',
modifiedAt: (page.value as unknown as Record<string, unknown>).modifiedAt as string | undefined,
breadcrumbs,
})
watch(() => navigation?.value, () => {
headline.value = findPageHeadline(navigation?.value, page.value?.path) || headline.value
})
defineOgImage('Docs', {
headline: headline.value,
title: title?.slice(0, 60),
description: formatOgDescription(title, description),
})
const github = computed(() => appConfig.github ? appConfig.github : null)
const giteaUrl = computed(() => appConfig.socials?.gitea as string | undefined)
// "Edit this page" points at Gitea (git.djeex.fr), not the GitHub mirror.
// Gitea's edit route is `/{owner}/{repo}/_edit/{branch}/{path}` (note the
// leading underscore — different from GitHub's `/edit/{branch}/{path}`).
const editLink = computed(() => {
if (!giteaUrl.value) {
return
}
return [
giteaUrl.value,
'_edit',
'main',
'content',
`${page.value?.stem}.${page.value?.extension}`,
].filter(Boolean).join('/')
})
// Add the page path to the prerender list
addPrerenderPath(`/raw${route.path}.md`)
</script>
<template>
<UPage
v-if="page"
class="relative"
:ui="isOpen ? { center: 'lg:col-span-10' } : undefined"
>
<UPageHeader
v-if="!hideHeader"
:title="page.title"
:description="page.description"
:headline="headline"
:ui="{
wrapper: 'flex-row items-center flex-wrap justify-between',
}"
>
<template #links>
<UButton
v-for="(link, index) in (page as DocsCollectionItem).links"
:key="index"
size="sm"
v-bind="link"
/>
<DocsPageHeaderLinks v-if="!hideCopyPage" />
</template>
</UPageHeader>
<UPageBody>
<ContentRenderer
v-if="page"
:value="page"
/>
<USeparator v-if="giteaUrl || github">
<div
class="flex items-center gap-2 text-sm text-muted"
>
<UButton
v-if="editLink"
variant="link"
color="neutral"
:to="editLink"
target="_blank"
icon="i-lucide-pen"
:ui="{ leadingIcon: 'size-4' }"
>
{{ t('docs.edit') }}
</UButton>
<template v-if="giteaUrl">
<span>{{ t('common.or') }}</span>
<UButton
variant="link"
color="neutral"
:to="`${giteaUrl}/issues/new`"
target="_blank"
icon="i-lucide-alert-circle"
:ui="{ leadingIcon: 'size-4' }"
>
{{ t('docs.report') }}
</UButton>
</template>
</div>
</USeparator>
<UContentSurround :surround="surround" />
</UPageBody>
<template
v-if="!isOpen && !hideToc"
#right
>
<DocsAsideRight
:page="page"
/>
</template>
</UPage>
</template>