this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

✨ Bunch of stuff

+403 -54
+1 -4
components/gallery.templ
··· 10 10 padding: 1rem; 11 11 } 12 12 13 - templ GalleryPage(works []ortfodb.AnalyzedWork, language string, title string, titleIsAlreadyTranslated bool) { 13 + templ GalleryPage(works []ortfodb.AnalyzedWork, language string) { 14 14 <main class={ galleryPageMain() }> 15 - if title != "" { 16 - <h1 i18n?={ !titleIsAlreadyTranslated }>{ title }</h1> 17 - } 18 15 { children... } 19 16 @WorksGrid(works, language, "works") 20 17 </main>
+42 -5
components/intro.templ
··· 1 1 package components 2 2 3 + css h1() { 4 + text-align: center; 5 + font-weight: 800; 6 + font-size: clamp(3rem, 10vw, 7rem); 7 + line-height: 0.8; 8 + } 9 + 10 + css explain() { 11 + margin: 0 auto; 12 + margin-top: -2rem; 13 + text-align: center; 14 + } 15 + 16 + css preH1() { 17 + text-align: center; 18 + font-size: 1.2rem; 19 + opacity: 0.5; 20 + margin-bottom: 0; 21 + } 22 + 23 + css introSection() { 24 + margin-bottom: 2rem; 25 + } 26 + 3 27 templ Intro() { 4 - <section class="intro"> 5 - <p class="pre-h1" i18n>Hi! I'm Ewen Le Bihan.</p> 6 - <h1 i18n>These are my creations.</h1> 7 - <p i18n>I'm interested in almost anything that is both creative and digital.</p> 8 - { children... } 28 + <section class={ introSection() }> 29 + <p class={ preH1() } i18n>Hi! I'm Ewen Le Bihan.</p> 30 + <h1 class={ h1() } i18n>These are my creations.</h1> 31 + <p class={ explain() }> 32 + <i18n>I'm interested in almost anything that is both creative and digital.</i18n> 33 + <br/> 34 + { children... } 35 + </p> 36 + </section> 37 + } 38 + 39 + templ IntroWith(pre string, title string, titleNeedsTranslation bool) { 40 + <section class={ introSection() }> 41 + <p class={ preH1() }>{ pre }</p> 42 + <h1 i18n?={ titleNeedsTranslation } class={ h1() }>{ title }</h1> 43 + <p class={ explain() }> 44 + { children... } 45 + </p> 9 46 </section> 10 47 }
+1 -11
components/work_card.templ
··· 3 3 import "fmt" 4 4 import "github.com/ortfo/db" 5 5 import "github.com/ewen-lbh/portfolio/shared" 6 - import "github.com/goodsign/monday" 7 6 8 7 func ThumbPath(work ortfodb.AnalyzedWork, language string) string { 9 8 return shared.Media(work.ThumbnailPath(language, 600)) ··· 11 10 12 11 func Thumb(work ortfodb.AnalyzedWork, language string) ortfodb.Media { 13 12 return work.ThumbnailBlock(language) 14 - } 15 - 16 - func mondayLocale(language string) monday.Locale { 17 - switch language { 18 - case "fr": 19 - return monday.LocaleFrFR 20 - default: 21 - return monday.LocaleEnUS 22 - } 23 13 } 24 14 25 15 func css(work ortfodb.AnalyzedWork, language string) templ.Component { ··· 134 124 </span> 135 125 if work.Metadata.CreatedAt().Year() != 9999 { 136 126 <span class="date"> 137 - { monday.Format(work.Metadata.CreatedAt(), "Jan 2006", mondayLocale(language)) } 127 + { shared.FormatDate(work.Metadata.CreatedAt(), "Jan 2006", language) } 138 128 </span> 139 129 } 140 130 </div>
+8 -7
pages/collection.templ
··· 5 5 import "github.com/ortfo/db" 6 6 7 7 templ Collection(collection shared.Collection, db ortfodb.Database, tags []shared.Tag, techs []shared.Technology, language string) { 8 + @components.IntroWith( 9 + "", 10 + collection.Title[language], 11 + false, 12 + ) { 13 + { collection.Description[language] } 14 + } 8 15 @components.GalleryPage( 9 16 collection.Works(db, tags, techs), 10 17 language, 11 - collection.Title[language], 12 - true, 13 - ) { 14 - <p class="description"> 15 - { collection.Description[language] } 16 - </p> 17 - } 18 + ) 18 19 }
+6 -4
pages/filtered.templ
··· 5 5 import "github.com/ewen-lbh/portfolio/components" 6 6 7 7 templ TagPage(tag shared.Tag, db ortfodb.Database, locale string) { 8 + @components.IntroWith("", tag.Plural, true) { 9 + <i18n>{ tag.Description }</i18n> 10 + } 8 11 @components.GalleryPage( 9 12 tag.Works(db), 10 13 locale, 11 - tag.Plural, 12 - false, 13 14 ) 14 15 } 15 16 16 17 templ TechnologyPage(tech shared.Technology, db ortfodb.Database, locale string) { 18 + @components.IntroWith("", tech.Name, true) { 19 + <i18n>{ tech.Description }</i18n> 20 + } 17 21 @components.GalleryPage( 18 22 tech.Works(db), 19 23 locale, 20 - tech.Name, 21 - true, 22 24 ) 23 25 }
+1 -1
pages/index.templ
··· 9 9 Learn more 10 10 } 11 11 } 12 - @components.GalleryPage(db.WorksSlice(), language, "", false) 12 + @components.GalleryPage(db.WorksSlice(), language) 13 13 }
+64 -8
pages/layout.templ
··· 35 35 window.location.host = domain 36 36 } 37 37 38 + css footer() { 39 + display: flex; 40 + flex-direction: column; 41 + align-items: center; 42 + padding: 10rem 1rem 0; 43 + background-color: #fff; 44 + color: #000; 45 + } 46 + 47 + css footerLinkHint() { 48 + opacity: 0.5; 49 + } 50 + 51 + css footerLinks() { 52 + display: inline-grid; 53 + margin-top: 0; 54 + grid-template-columns: 3rem auto; 55 + } 56 + 57 + css footerLinkPurpose() { 58 + font-family: Manrope Variable, Manrope, sans-serif; 59 + opacity: 0.5; 60 + } 61 + 62 + css footerLinkAnchor() { 63 + font-family: Inconsolata Variable, Inconsolata, monospace; 64 + display: block; 65 + text-decoration: none; 66 + transition: font-weight 0.125s ease; 67 + } 68 + 69 + css footerCredits() { 70 + display: flex; 71 + flex-direction: column; 72 + justify-content: center; 73 + text-align: center; 74 + margin: 3rem 0; 75 + } 76 + 77 + css footerCreditsParagraph() { 78 + text-align: center; 79 + } 80 + 81 + css footerLicense() { 82 + margin: 0 auto; 83 + width: min-content; 84 + } 85 + 86 + css footerLicenseImage() { 87 + margin-top: 0.5rem; 88 + height: 1.5rem; 89 + } 90 + 38 91 templ Layout(contents templ.Component, collections map[string]string, sites []shared.Site, lang string) { 39 92 <!DOCTYPE html> 40 93 <html lang={ lang }> ··· 64 117 </nav> 65 118 </header> 66 119 @contents 67 - <footer> 68 - <section class="sites"> 120 + <footer class={ footer() }> 121 + <section> 69 122 <code>ewen.works/to/</code> 70 - <dl> 123 + <dl class={ footerLinks() }> 71 124 for _, site := range sites { 72 - <dt><a href={ templ.URL("/to/" + site.Name) }>{ site.Name }</a> </dt> 73 - <dd i18n>{ site.Purpose } </dd> 125 + <dt><a class={ footerLinkAnchor() } href={ templ.URL("/to/" + site.Name) }>{ site.Name }</a> </dt> 126 + <dd class={ footerLinkPurpose() } i18n>{ site.Purpose } </dd> 74 127 } 75 128 </dl> 76 129 </section> 77 - <section class="credits"> 78 - <p i18n class="powered-by">Proudly powered by <a href="https://github.com/ortfo">ortfo</a>, my portfolio database management system and <a href="https://github.com/a-h/templ">templ</a></p> 79 - <p class="source-code"><a href="https://github.com/ewen-lbh/portfolio" i18n>Source code</a></p> 130 + <section class={ footerCredits() }> 131 + <p i18n class={ footerCreditsParagraph() }>Proudly powered by <a href="https://github.com/ortfo">ortfo</a>, my portfolio database management system and <a href="https://github.com/a-h/templ">templ</a></p> 132 + <p class={ footerCreditsParagraph() }><a href="https://github.com/ewen-lbh/portfolio" i18n>Source code</a></p> 133 + <a href="https://creativecommons.org/licenses/by-sa/4.0/"> 134 + <img class={ footerLicenseImage() } src={ string(shared.Asset("icons/cc-by-sa.svg")) } alt="Creative Commons Attribution-ShareAlike 4.0 International License"/> 135 + </a> 80 136 </section> 81 137 </footer> 82 138 </body>
+23 -14
pages/work.templ
··· 1 1 package pages 2 2 3 3 import "github.com/ortfo/db" 4 - import "strings" 5 4 import "github.com/ewen-lbh/portfolio/shared" 6 5 import "fmt" 6 + import "github.com/ewen-lbh/portfolio/components" 7 7 8 8 func gridAreas(layout ortfodb.Layout) shared.Selectors { 9 9 var areas []string ··· 117 117 <a href={ templ.URL(block.URL) } class="standalone-link">{ block.Text.String() }</a> 118 118 } 119 119 120 + css tagLink() { 121 + display: inline-block; 122 + padding: 0.2em 0.5em; 123 + text-decoration: none; 124 + } 125 + 126 + css tagLinks() { 127 + display: flex; 128 + flex-wrap: wrap; 129 + justify-content: center; 130 + } 131 + 120 132 templ Work(work ortfodb.AnalyzedWork, tags []shared.Tag, techs []shared.Technology, lang string) { 121 - <main> 122 - @shared.CSS(shared.Merge(colorVariables(work, lang), gridAreas(work.Content[lang].Layout))) 123 - <section class="tags"> 133 + @components.IntroWith( 134 + shared.FormatDate(work.Metadata.CreatedAt(), "January 2006", lang), 135 + work.Content[lang].Title.String(), 136 + false, 137 + ) { 138 + <section class={ tagLinks() }> 124 139 for _, tag := range tags { 125 - <a href={ templ.URL("/" + tag.URLName()) }> 140 + <a class={ tagLink() } href={ templ.URL("/" + tag.URLName()) }> 126 141 #<i18n>{ tag.Singular }</i18n> 127 142 </a> 128 143 } 129 144 </section> 130 - <h1>{ work.Content[lang].Title.String() }</h1> 131 - if work.Metadata.CreatedAt().Year() != 9999 { 132 - <p class="date"> 133 - { work.Metadata.CreatedAt().Format("2006") } 134 - if work.Metadata.WIP { 135 - <span class="wip">· Work in progress</span> 136 - } 137 - </p> 138 - } 145 + } 146 + <main> 147 + @shared.CSS(shared.Merge(colorVariables(work, lang), gridAreas(work.Content[lang].Layout))) 139 148 <section class="content"> 140 149 for _, block := range work.Content[lang].Blocks { 141 150 <div
+238
public/icons/cc-by-sa.svg
··· 1 + <?xml version="1.0" encoding="UTF-8" standalone="no"?> 2 + <!-- Created with Inkscape (http://www.inkscape.org/) --> 3 + 4 + <svg 5 + xmlns:dc="http://purl.org/dc/elements/1.1/" 6 + xmlns:cc="http://creativecommons.org/ns#" 7 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 8 + xmlns:svg="http://www.w3.org/2000/svg" 9 + xmlns="http://www.w3.org/2000/svg" 10 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 11 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 12 + width="282.22223mm" 13 + height="94.191666mm" 14 + viewBox="0 0 1000 333.74999" 15 + id="svg2" 16 + version="1.1" 17 + inkscape:version="0.91 r13725" 18 + sodipodi:docname="hjhj.svg"> 19 + <defs 20 + id="defs4"> 21 + <marker 22 + inkscape:stockid="Arrow2Sstart" 23 + orient="auto" 24 + refY="0.0" 25 + refX="0.0" 26 + id="Arrow2Sstart" 27 + style="overflow:visible" 28 + inkscape:isstock="true"> 29 + <path 30 + id="path4193" 31 + style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#00ff00;stroke-opacity:1;fill:#00ff00;fill-opacity:1" 32 + d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " 33 + transform="scale(0.3) translate(-2.3,0)" /> 34 + </marker> 35 + <marker 36 + inkscape:stockid="Arrow1Sstart" 37 + orient="auto" 38 + refY="0.0" 39 + refX="0.0" 40 + id="marker5081" 41 + style="overflow:visible" 42 + inkscape:isstock="true"> 43 + <path 44 + id="path5083" 45 + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " 46 + style="fill-rule:evenodd;stroke:#00ff00;stroke-width:1pt;stroke-opacity:1;fill:#00ff00;fill-opacity:1" 47 + transform="scale(0.2) translate(6,0)" /> 48 + </marker> 49 + <marker 50 + inkscape:stockid="Arrow1Sstart" 51 + orient="auto" 52 + refY="0.0" 53 + refX="0.0" 54 + id="marker5029" 55 + style="overflow:visible" 56 + inkscape:isstock="true"> 57 + <path 58 + id="path5031" 59 + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " 60 + style="fill-rule:evenodd;stroke:#00ff00;stroke-width:1pt;stroke-opacity:1;fill:#00ff00;fill-opacity:1" 61 + transform="scale(0.2) translate(6,0)" /> 62 + </marker> 63 + <marker 64 + inkscape:stockid="DiamondS" 65 + orient="auto" 66 + refY="0.0" 67 + refX="0.0" 68 + id="DiamondS" 69 + style="overflow:visible" 70 + inkscape:isstock="true"> 71 + <path 72 + id="path4248" 73 + d="M 0,-7.0710768 L -7.0710894,0 L 0,7.0710589 L 7.0710462,0 L 0,-7.0710768 z " 74 + style="fill-rule:evenodd;stroke:#00ff00;stroke-width:1pt;stroke-opacity:1;fill:#00ff00;fill-opacity:1" 75 + transform="scale(0.2)" /> 76 + </marker> 77 + <marker 78 + inkscape:stockid="Arrow1Mstart" 79 + orient="auto" 80 + refY="0.0" 81 + refX="0.0" 82 + id="Arrow1Mstart" 83 + style="overflow:visible" 84 + inkscape:isstock="true"> 85 + <path 86 + id="path4169" 87 + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " 88 + style="fill-rule:evenodd;stroke:#00ff00;stroke-width:1pt;stroke-opacity:1;fill:#00ff00;fill-opacity:1" 89 + transform="scale(0.4) translate(10,0)" /> 90 + </marker> 91 + <marker 92 + inkscape:stockid="Arrow1Sstart" 93 + orient="auto" 94 + refY="0.0" 95 + refX="0.0" 96 + id="Arrow1Sstart" 97 + style="overflow:visible" 98 + inkscape:isstock="true"> 99 + <path 100 + id="path4175" 101 + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " 102 + style="fill-rule:evenodd;stroke:#00ff00;stroke-width:1pt;stroke-opacity:1;fill:#00ff00;fill-opacity:1" 103 + transform="scale(0.2) translate(6,0)" /> 104 + </marker> 105 + <marker 106 + inkscape:stockid="DiamondSstart" 107 + orient="auto" 108 + refY="0.0" 109 + refX="0.0" 110 + id="DiamondSstart" 111 + style="overflow:visible" 112 + inkscape:isstock="true"> 113 + <path 114 + id="path4257" 115 + d="M 0,-7.0710768 L -7.0710894,0 L 0,7.0710589 L 7.0710462,0 L 0,-7.0710768 z " 116 + style="fill-rule:evenodd;stroke:#00ff00;stroke-width:1pt;stroke-opacity:1;fill:#00ff00;fill-opacity:1" 117 + transform="scale(0.2) translate(6,0)" /> 118 + </marker> 119 + <marker 120 + inkscape:stockid="EmptyDiamondLend" 121 + orient="auto" 122 + refY="0.0" 123 + refX="0.0" 124 + id="EmptyDiamondLend" 125 + style="overflow:visible" 126 + inkscape:isstock="true"> 127 + <path 128 + id="path4287" 129 + d="M 0,-7.0710768 L -7.0710894,0 L 0,7.0710589 L 7.0710462,0 L 0,-7.0710768 z " 130 + style="fill-rule:evenodd;fill:#ffffff;stroke:#00ff00;stroke-width:1pt;stroke-opacity:1" 131 + transform="scale(0.8) translate(-7,0)" /> 132 + </marker> 133 + </defs> 134 + <sodipodi:namedview 135 + id="base" 136 + pagecolor="#ffffff" 137 + bordercolor="#666666" 138 + borderopacity="1.0" 139 + inkscape:pageopacity="0.0" 140 + inkscape:pageshadow="2" 141 + inkscape:zoom="0.48" 142 + inkscape:cx="796.96067" 143 + inkscape:cy="205.95272" 144 + inkscape:document-units="px" 145 + inkscape:current-layer="layer1" 146 + showgrid="false" 147 + fit-margin-top="0" 148 + fit-margin-left="0" 149 + fit-margin-right="0" 150 + fit-margin-bottom="0" 151 + inkscape:window-width="1008" 152 + inkscape:window-height="1084" 153 + inkscape:window-x="1024" 154 + inkscape:window-y="0" 155 + inkscape:window-maximized="0" /> 156 + <metadata 157 + id="metadata7"> 158 + <rdf:RDF> 159 + <cc:Work 160 + rdf:about=""> 161 + <dc:format>image/svg+xml</dc:format> 162 + <dc:type 163 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> 164 + <dc:title></dc:title> 165 + </cc:Work> 166 + </rdf:RDF> 167 + </metadata> 168 + <g 169 + inkscape:label="Layer 1" 170 + inkscape:groupmode="layer" 171 + id="layer1" 172 + transform="translate(54.285713,328.79852)"> 173 + <ellipse 174 + style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 175 + id="path4147" 176 + cx="113.13351" 177 + cy="-162.84398" 178 + rx="144.77277" 179 + ry="144.39655" /> 180 + <ellipse 181 + ry="144.39655" 182 + rx="144.77277" 183 + cy="-162.84398" 184 + cx="445.13351" 185 + id="ellipse4149" 186 + style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> 187 + <ellipse 188 + style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 189 + id="ellipse4151" 190 + cx="779.13354" 191 + cy="-162.84398" 192 + rx="144.77277" 193 + ry="144.39655" /> 194 + <path 195 + style="fill:#000003;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" 196 + d="m 419.75525,-55.2442 0.35403,-80.26814 -18.41274,-0.24357 -0.0217,-70.72993 c 0.12723,-4.05366 2.11982,-7.72536 7.74539,-7.39135 l 72.98726,-0.53151 c 4.84361,0.9231 9.21337,2.46221 8.83015,10.1802 l -0.35403,69.77828 -19.20956,0.1992 0,79.75927 z" 197 + id="path4153" 198 + inkscape:connector-curvature="0" 199 + sodipodi:nodetypes="ccccccccccc" /> 200 + <ellipse 201 + style="opacity:1;fill:#000003;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 202 + id="path4155" 203 + cx="445.21628" 204 + cy="-248.43497" 205 + rx="21.015936" 206 + ry="20.318726" /> 207 + <path 208 + style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:31.39999962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" 209 + id="path4157" 210 + sodipodi:type="arc" 211 + sodipodi:cx="782.987" 212 + sodipodi:cy="-160.20003" 213 + sodipodi:rx="63.797535" 214 + sodipodi:ry="72.888451" 215 + sodipodi:start="3.451922" 216 + sodipodi:end="2.9057875" 217 + d="m 722.23688,-182.45814 a 63.797535,72.888451 0 0 1 71.78212,-49.53231 63.797535,72.888451 0 0 1 52.72125,74.50577 63.797535,72.888451 0 0 1 -57.43037,69.814246 63.797535,72.888451 0 0 1 -68.35492,-55.500966" 218 + sodipodi:open="true" /> 219 + <text 220 + xml:space="preserve" 221 + style="font-style:normal;font-weight:normal;font-size:5px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" 222 + x="16.017319" 223 + y="-118.07881" 224 + id="text5237" 225 + sodipodi:linespacing="125%"><tspan 226 + sodipodi:role="line" 227 + id="tspan5239" 228 + x="16.017319" 229 + y="-118.07881" 230 + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:125px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'">CC</tspan></text> 231 + <path 232 + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" 233 + d="m 713.32793,-165.56938 -17.71783,-35.0568 57.71783,19.4413 z" 234 + id="path5247" 235 + inkscape:connector-curvature="0" 236 + sodipodi:nodetypes="cccc" /> 237 + </g> 238 + </svg>
+19
shared/utils.go
··· 3 3 import ( 4 4 "encoding/hex" 5 5 "sort" 6 + "time" 7 + 8 + "github.com/goodsign/monday" 6 9 ) 7 10 8 11 type MapEntry[K comparable, V any] struct { ··· 45 48 } 46 49 return color 47 50 } 51 + 52 + func MondayLocale(language string) monday.Locale { 53 + switch language { 54 + case "fr": 55 + return monday.LocaleFrFR 56 + default: 57 + return monday.LocaleEnUS 58 + } 59 + } 60 + 61 + func FormatDate(date time.Time, format string, locale string) string { 62 + if date.Year() == 9999 { 63 + return "" 64 + } 65 + return monday.Format(date, format, MondayLocale(locale)) 66 + }