Commit 06a5a8a8 authored by CSA's avatar CSA
Browse files

Simplify menu system

parent 82ede950
......@@ -3,5 +3,6 @@
{{ partial "widgets/banner.html" . }}
{{/* Navigation menu */}}
{{ $.Scratch.Set "menu" (dict "name" "nav-main" "template" "h") }}
{{ partial "widgets/menu.html" . }}
{{ $.Scratch.Set "menu" (dict "name" "nav-main") }}
{{ partial "widgets/menu/h.html" . }}
{{/*
An item template takes at least these arguments:
- lineage
- itemName: (string)
Optional parameters:
- linkClass: (string) classes to pass to the link HTML element
- icon: (string) FontAwesome4 icon to display along the item
*/}}
{{ $params := $.Scratch.Get "menu-item" }}
{{ $i18nKey := (printf "%s-%s" (delimit $params.lineage "-") $params.itemName) }}
{{ $link := urls.Parse (i18n $i18nKey 1) }}
<a {{ if $params.linkClass }} class="{{ $params.linkClass }}"{{ end }} href="{{ cond (or (eq $link.Scheme "http") (eq $link.Scheme "https")) (i18n $i18nKey 1) (i18n $i18nKey 1 | relLangURL) }}">
{{ if $params.icon }}<i class="fa fa-{{ $params.icon }}"></i> {{ end }}{{ i18n $i18nKey 2 }}
</a>
{{/*
Menu template takes at least these arguments:
- lineage
- name: (string)
- level: (int)
Optional arguments:
- icon: (string)
- linkClass: (string)
- itemClass: (string)
*/}}
{{ $params := $.Scratch.Get "menu" }}
{{/* Some params need to be saved for after the next recursion level */}}
{{ $name := $params.name }}
{{ $icon := $params.icon }}
{{ $linkClass := $params.linkClass }}
{{ $itemName := (delimit $params.lineage "-") }}
{{ $.Scratch.SetInMap "menu" "ignoreTemplate" true }}
{{ if eq $params.level 1 }}
{{ $.Scratch.SetInMap "menu" "linkClass" (printf "%s %s" $params.linkClass " pure-menu-link") }}
<div class="pure-menu pure-menu-horizontal">
<aside id="menu-{{ $params.name }}-open" class="pure-menu-open">
<a href="#menu-{{ $params.name }}-open">
<i class="fa fa-bars fa-2x"></i>
</a>
</aside>
<ul class="rawList pure-menu-list pure-menu-navigation">
{{ partial "menu/proc.html" . }}
</ul>
<a href="#menu-nav-main" id="menu-nav-main-close" class="pure-menu-close">
<i class="fa fa-times fa-2x"></i>
</a>
</div>
{{ else }}
<a class="{{ $linkClass }}" href="{{ i18n $itemName 1 }}">{{ if $icon }}<i class="fa fa-{{ $icon }}"></i> {{ end }}{{ i18n $itemName 2 }}</a>
<ul class="pure-menu-children">
{{ partial "menu/proc.html" . }}
</ul>
{{ end }}
{{/*
Menu header takes at least one argument:
- name: (string)
Optional arguments:
- icon: (string)
*/}}
<a href="{{ i18n .name 1 }}" class="menu-header center">
{{ if .icon }}
<div>
<i class="fa fa-4x fa-{{ .icon }}"></i>
</div>
{{ end }}
{{ if .name }}
<h3>{{ i18n .name 2 }}</h3>
{{ end }}
</a>
{{/*
Entry image takes at least these arguments:
- lineage
- itemName: (string)
Optional arguments:
- linkClass: (string)
- image: (string)
*/}}
{{ $params := $.Scratch.Get "menu-item" }}
{{ $i18nKey := (printf "%s-%s" (delimit $params.lineage "-") $params.itemName) }}
<a {{ if $params.linkClass }} class="{{ $params.linkClass }}"{{ end }} href="{{ i18n $i18nKey 1 | relLangURL }}">
<img class="fitImg" src="{{ $params.image | strings.TrimPrefix "static/" | relURL }}" alt="{{ i18n $i18nKey 2 }}">
</a>
{{/*
An item template takes at least these arguments:
- lineage
- itemName: (string) entry id
- level: (int) recursion level
- template: (string) menu type h/v
Optional parameters:
- itemClass: (string) classes to pass to the list item HTML element
- linkClass: (string) classes to pass to the link HTML element
- icon: (string) FontAwesome4 icon to display along the item
- itemChildren
*/}}
{{ $params := $.Scratch.Get "menu-item" }}
{{ $lineage := $params.lineage }}
{{ $level := $params.level }}
{{ $i18nKey := (printf "%s-%s" (delimit $lineage "-") $params.itemName) }}
<li class=" pure-menu-item{{ if $params.itemChildren }} pure-menu-has-children pure-menu-allow-hover{{ end }}{{ if $params.itemClass }} {{ $params.itemClass }}{{ end }}">
{{ if $params.itemChildren }}
{{ $.Scratch.Set "menu" ($.Scratch.Get "menu-item") }}
{{ $.Scratch.SetInMap "menu" "level" (add 1 $level) }}
{{ $.Scratch.SetInMap "menu" "lineage" (split $i18nKey "-") }}
{{ $.Scratch.SetInMap "menu" "items" $params.itemChildren }}
{{ $.Scratch.SetInMap "menu-item" "itemChildren" "" }}
{{ partial "menu/proc.html" . }}
{{ $.Scratch.SetInMap "menu" "lineage" $lineage }}
{{ $.Scratch.SetInMap "menu" "level" $level }}
{{ else }}
{{ partial (printf "menu/%s-item.html" $params.template) . }}
{{ end }}
</li>
{{/*
proc.html takes minimum these arguments:
- lineage
- name: (string)
- items
Optional arguments:
- template: (string) h or v, defaults to "v"
- itemClass: (string) classes for the item to pass to the item template
- linkClass: (string) classes for the link to pass to the item template
Internal arguments: some recursion shit you probably shouldn't use
- ignoreTemplate: (bool) Skip templating for raw logic (some recursion shit)
*/}}
{{ $params := $.Scratch.Get "menu" }}
{{ if not ($params.ignoreTemplate) }}
{{/* Need to do some templating */}}
{{ partial (printf "menu/%s.html" (default "v" $params.template)) . }}
{{ else }}
{{/* Next time we want to do templating */}}
{{ $.Scratch.SetInMap "menu" "ignoreTemplate" false }}
{{ $params := $.Scratch.Get "menu" }}
{{/* Initialize the menu-item template */}}
{{ $.Scratch.Set "menu-item" ($.Scratch.Get "menu") }}
{{ $.Scratch.SetInMap "menu-item" "itemClass" $params.itemClass }}
{{ $.Scratch.SetInMap "menu-item" "linkClass" $params.linkClass }}
{{ range $i := $params.items }}
{{ $type := (printf "%T" $i) }}
{{ if eq "string" $type }}
{{ $.Scratch.SetInMap "menu-item" "icon" "" }}
{{ $.Scratch.SetInMap "menu-item" "itemName" $i }}
{{ partial "menu/item.html" $ }}
{{ else }}
{{ range $j, $k := $i }}
{{ $type := (printf "%T" $k) }}
{{ if eq "string" $type }}
{{ $.Scratch.SetInMap "menu-item" "itemName" $j }}
{{ $.Scratch.SetInMap "menu-item" "icon" $k }}
{{ partial "menu/item.html" $ }}
{{ else }}
{{ range $y := $k }}
{{ $type := (printf "%T" $y) }}
{{ if (eq "string" $type) }}
{{ if ($.Scratch.Get "items") }}
{{ $.Scratch.Add "items" $y }}
{{ else }}
{{ $.Scratch.Set "items" (slice $y) }}
{{ end }}
{{ else }}
{{ range $a, $b := $y }}
{{ if or (eq $a "items") (eq $a "icon") }}
{{ $.Scratch.Set $a $b }}
{{ else if ($.Scratch.Get "items") }}
{{ $.Scratch.Add "items" $y }}
{{ else }}
{{ $.Scratch.Set "items" (slice $y) }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ $icon := ($.Scratch.Get "icon") }}
{{ $items := ($.Scratch.Get "items") }}
{{ if or $icon $items }}
{{ $.Scratch.Set "icon" "" }}
{{ $.Scratch.Set "items" "" }}
{{ $.Scratch.SetInMap "menu-item" "itemName" $j }}
{{ $.Scratch.SetInMap "menu-item" "icon" $icon }}
{{ $.Scratch.SetInMap "menu-item" "itemChildren" $items }}
{{ partial "menu/item.html" $ }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{/*
An item template takes at least these arguments:
- lineage
- itemName: (string)
Optional parameters:
- linkClass: (string) classes to pass to the link HTML element
- icon: (string) FontAwesome4 icon to display along the item
*/}}
{{ $params := $.Scratch.Get "menu-item" }}
{{ $i18nKey := (printf "%s-%s" (delimit $params.lineage "-") $params.itemName) }}
{{ $menuPath := (delimit $params.lineage "/") }}
{{ $imageBase := printf "static/images/menus/%s/%s" $menuPath $params.itemName }}
{{ if fileExists (printf "%s.png" $imageBase) }}
{{ $.Scratch.SetInMap "menu-item" "image" (printf "%s.png" $imageBase) }}
{{ partial "menu/image.html" . }}
{{ else if fileExists (printf "%s.jpg" $imageBase) }}
{{ $.Scratch.SetInMap "menu-item" "image" (printf "%s.jpg" $imageBase) }}
{{ partial "menu/image.html" . }}
{{ else }}
{{ if $params.icon }}<i class="fa fa-{{ $params.icon }}"></i> {{ end }}{{ i18n $i18nKey 2 | markdownify }}
{{ end }}
{{/*
Menu template takes at least these arguments:
- lineage
- name: (string)
- level: (int)
Optional arguments:
- icon: (string)
- linkClass: (string)
- itemClass: (string)
*/}}
{{ $params := $.Scratch.Get "menu" }}
{{ $itemName := (delimit $params.lineage "-") }}
{{ if eq $params.level 1 }}
{{ $itemClass := (printf "%s %s" $params.itemClass " center") }}
{{ $.Scratch.SetInMap "menu" "itemClass" $itemClass }}
{{ partial "menu/header.html" (dict "name" $params.name "icon" $params.icon) }}
{{ else }}
<a class="{{ $params.linkClass }}" href="{{ i18n $itemName 1 }}">{{ if $params.icon }}<i class="fa fa-{{ $params.icon }}"></i> {{ end }}{{ i18n $itemName 2 }}</a>
{{ end }}
<ul class="rawList">
{{ $.Scratch.SetInMap "menu" "ignoreTemplate" true }}
{{ partial "menu/proc.html" . }}
</ul>
{{/*
Menu widget, generates a menu following a template. Menus are stored in the
data/vaytheme/ folder.
Usage :
{{ $.Scratch.Set "menu" (dict "name" "nav-main" "template" "h" "class" "") }}
{{ partial "widgets/menu.html" . }}
Menu parameters:
- name: menu file to look for in the data/vaytheme/ folder
- template: h/v for horizontal or vertical menu
A YAML menu file typically looks like this:
icon: map-signs
items:
- "home": "globe"
- "agenda": ["truc": "thumbs-o-up", "bidule"]
- "press": ["icon": "newspaper-o", "items": ["badtv": "lock", "brochures"]]
- "contact"
If you do not wish to pass any parameters to the menu from the menu data, it is also
possible to put your entries directly at the root of the menu:
"home": "globe"
"agenda": ["truc": "thumbs-o-up", "bidule"]
"press": ["icon": "newspaper-o", "items": ["badtv": "lock", "brochures"]]
"contact"
Each entry may have an associated value or not. This associated value can be either
a FontAwesome4 icon or a list of children. In case you would like to have an icon for
an entry with children, do as in the "press" key in the example above: an "icon" key
containing the icon, and an "items" key containing the children.
The 'items' key is reserved for (sub)entries within the menu.
More formats are supported (JSON, TOML, YAML)! See Hugo docs:
https://gohugo.io/templates/data-templates/
Menu entries are then looked up in the i18n folder to allow translating the menu.
The i18n key looked up is $menu-$entry(-$subentry).
There is no arbitrary limit on how deep the menu can go.
An entry may have an associated URL ("one" key) and a content ("other" key).
Each menu template has its own specifics.
v - VERTICAL MENU
Menu name and icon will be rendered as a menu header.
This menu markdownifies the content taken from the translation files.
Links are not taken from the translation files, to allow for text without links.
If an image is available, it will be used.
h - HORIZONTAL MENU
Everything is in a div that has pure-menu and pure-menu-horizontal classes.
Links have the pure-menu-link added to them.
*/}}
{{ $params := $.Scratch.Get "menu" }}
{{ $name := $params.name }}
{{ $template := $params.template }}
{{ $menu := index .Site.Data.vaytheme.menus $name }}
{{ if $menu }}
{{ $.Scratch.SetInMap "menu" "lineage" (slice $name) }}
{{ $.Scratch.SetInMap "menu" "items" $menu.items }}
{{ $.Scratch.SetInMap "menu" "icon" $menu.icon }}
{{ $.Scratch.SetInMap "menu" "level" 1 }}
{{ $.Scratch.SetInMap "menu" "itemClass" "" }}
{{ $.Scratch.SetInMap "menu" "linkClass" "" }}
<nav id="menu-{{ $name }}" class="menu-{{ $name }}">
{{ partial "menu/proc.html" . }}
</nav>
{{ end }}
{{/*
Menu item takes:
- name (item name) eg. nav-about
Optional arguments:
- class (menu item class)
- linkClass (menu item link class)
h-item also supports:
- children (sub-items)
*/}}
{{ $params := $.Scratch.Get "menu-item" }}
{{ $link := i18n $params.name 1 }}
<li class="pure-menu-item pure-menu-allow-hover {{ with $params.children }}pure-menu-has-children {{ end }}{{ with $params.itemClass }}{{ . }} {{ end }}">
<a class="pure-menu-link {{ with $params.linkClass }}{{ . }}{{ end }}" href="{{ cond (hasPrefix $link "http") $link ($link | relLangURL) }}">
{{/*{{ with $params.icon }}<i class="fa fa-{{ . }}"></i> {{ end }}*/}}{{ i18n $params.name 2 }}
</a>
{{ with $params.children }}
<ul class="pure-menu-children">
{{ range . }}
{{ $name := printf "%s-%s" $params.name . }}
{{ $link := i18n $name 1 }}
<li class="pure-menu-item"><a class="pure-menu-link {{ with $params.linkClass }}{{ . }}{{ end }}" href="{{ cond (hasPrefix $link "http") $link ($link | relLangURL) }}">{{ i18n $name 2 }}</a></li>
{{ end }}
</ul>
{{ end }}
</li>
{{/*
Menu takes:
- name (menu name)
Optional arguments:
- class (menu div class)
- childClass (menu item class)
- linkClass (menu item link class)
h menu does not understand additional parameters.
h menu structure is as such :
- "item"
- "parent": ["subEntry", "anotherOne"]
*/}}
{{ $params := $.Scratch.Get "menu" }}
{{ $children := index .Site.Data.vaytheme.menus $params.name }}
<nav id="menu-{{ $params.name }}" class="widget-menu{{ with $params.class }} {{ . }}{{ end }}">
<div class="pure-menu pure-menu-horizontal">
<aside id="menu-{{ $params.name }}-open" class="pure-menu-open">
<a href="#menu-{{ $params.name }}-open">
<i class="fa fa-bars fa-2x"></i>
</a>
</aside>
<ul class="rawList pure-menu-list pure-menu-navigation">
{{/* Here we parse the menu */}}
{{ range $children }}
{{/* We reset here so children't aren't passed to the next top-level entry */}}
{{ $.Scratch.Set "menu-item" (dict "class" (default "" $params.childClass) "linkClass" (default "" $params.linkClass)) }}
{{ if eq "string" (printf "%T" .) }}
{{/* First-level item */}}
{{ $.Scratch.SetInMap "menu-item" "name" (printf "%s-%s" $params.name .) }}
{{ partial "widgets/menu/h-item.html" $ }}
{{ else }}
{{/* Entry with children */}}
{{ range $top, $children := . }}
{{ $.Scratch.SetInMap "menu-item" "name" (printf "%s-%s" $params.name $top) }}
{{ $.Scratch.SetInMap "menu-item" "children" $children }}
{{ partial "widgets/menu/h-item.html" $ }}
{{ end }}
{{ end }}
{{ end }}
</ul>
<a href="#menu-nav-main" id="menu-nav-main-close" class="pure-menu-close">
<i class="fa fa-times fa-2x"></i>
</a>
</div>
</nav>
{{/*
Entry image is a special v-item instance which takes an additional parameter called 'image'
*/}}
{{ $params := $.Scratch.Get "menu-item" }}
<a{{ with $params.linkClass }} class="{{ . }}"{{ end }} href="{{ i18n $params.name 1 | relLangURL }}">
<img class="fitImg" src="{{ $params.image | strings.TrimPrefix "static/" | relURL }}" alt="{{ i18n $params.name 2 }}">
</a>
{{/*
An item template takes at least these arguments:
- name (item name) eg. nav-about
- icon (fontAwesome icon name, can be empty)*
Optional arguments:
- markdown (set to true to ignore links and process content as Markdown)
- class (menu item class)
- linkClass (menu item link class)
v-item does not support additional parameters.
*/}}
{{ $params := $.Scratch.Get "menu-item" }}
{{ $menuPath := (delimit (split $params.name "-") "/") }}
{{ $imageBase := printf "static/images/menus/%s" $menuPath }}
<li>
{{ if fileExists (printf "%s.jpg" $imageBase) }}
{{ $.Scratch.SetInMap "menu-item" "image" (printf "%s.jpg" $imageBase) }}
{{ partial "widgets/menu/v-image.html" . }}
{{ else if fileExists (printf "%s.png" $imageBase) }}
{{ $.Scratch.SetInMap "menu-item" "image" (printf "%s.png" $imageBase) }}
{{ partial "widgets/menu/v-image.html" . }}
{{ else }}
{{ with $params.icon }}<i class="fa fa-{{ . }}"></i> {{ end }}{{ with $params.markdown }}{{ i18n $params.name 2 | markdownify }}{{ else }}{{ i18n $params.name 2 }}{{ end }}
{{ end }}
</li>
{{/*
Menu takes:
- name (menu name)
Optional arguments:
- navigation (set to true to start a <nav> element)
- class (menu div/nav class)
- headerClass (menu header link class)
- childClass (menu item class)
- linkClass (menu item link class)
h menu structure is as such :
"icon": "faIconName"
"items":
"entry": "faIconName"
"parentEntry":
"icon": "faIconName"
"items":
"subEntry": "faIconName"
"anotherOne": "faIconName"
*/}}
{{ $params := $.Scratch.Get "menu" }}
{{ $children := index .Site.Data.vaytheme.menus $params.name }}
{{ with $params.navigation }}
<nav id="menu-{{ $params.name }}" class="widget-menu{{ with $params.class }} {{ . }}{{ end }}">
{{ else }}
<div id="menu-{{ $params.name }}" class="widget-menu{{ with $params.class }} {{ . }}{{ end }}">
{{ end }}
<a href="{{ i18n $params.name 1 }}" class="widget-menu-v-header{{ with $params.headerClass }} {{ . }}{{ end }}">
{{ with $children.icon }}
<div>
<i class="fa fa-4x fa-{{ . }}"></i>
</div>
{{ end }}
<h3>{{ i18n $params.name 2 }}</h3>
</a>
<ul class="rawList">
{{/* Here we parse the actual menu */}}
{{ range $entry, $value := $children.items }}
{{ $.Scratch.Set "menu-item" (dict "name" (printf "%s-%s" $params.name $entry) "class" (default "" $params.childClass) "linkClass" (default "" $params.linkClass)) }}
{{ if eq "string" (printf "%T" $value) }}
{{ $.Scratch.SetInMap "menu-item" "icon" $value }}
{{ partial "widgets/menu/v-item.html" $ }}
{{ else }}
{{ $.Scratch.SetInMap "menu-item" "icon" $value.icon }}
{{ range $subEntry, $icon := $value }}
{{ $.Scratch.SetInMap "menu-item" "name" (printf "%s-%s-%s" $params.name $entry $subEntry) }}
{{ $.Scratch.SetInMap "menu-item" "icon" $icon }}
{{ partial "widgets/menu/v-item.html" $ }}
{{ end }}
{{ end }}
{{ end }}
{{ with $params.navigation }}
</nav>
{{ else }}
</div>
{{ end }}
{{/*
Menu takes:
- name (menu name)
Optional arguments:
- navigation (set to true to start a <nav> element)
- class (menu div/nav class)
- headerClass (menu header link class)
- childClass (menu item class)
- linkClass (menu item link class)
h menu structure is as such :
"icon": "faIconName"
"items":
"entry": "faIconName"
"parentEntry":
"icon": "faIconName"
"items":
"subEntry": "faIconName"
"anotherOne": "faIconName"
*/}}
{{ $params := $.Scratch.Get "menu" }}
{{ $children := index .Site.Data.vaytheme.menus $params.name }}
{{ with $params.navigation }}
<nav id="menu-{{ $params.name }}" class="widget-menu{{ with $params.class }} {{ . }}{{ end }}">
{{ else }}
<div id="menu-{{ $params.name }}" class="widget-menu{{ with $params.class }} {{ . }}{{ end }}">
{{ end }}
<div class="widget-menu-v-header{{ with $params.headerClass }} {{ . }}{{ end }}">
{{ with $children.icon }}
<div>
<i class="fa fa-4x fa-{{ . }}"></i>
</div>
{{ end }}
<h3>{{ i18n $params.name 2 }}</h3>
</div>
<ul class="rawList">
{{/* Here we parse the actual menu */}}
{{ range $children.items }}
{{ range $entry, $value := . }}
{{ $.Scratch.Set "menu-item" (dict "name" (printf "%s-%s" $params.name $entry) "class" (default "" $params.childClass) "linkClass" (default "" $params.linkClass) "markdown" "true") }}
{{ if eq "string" (printf "%T" $value) }}
{{ $.Scratch.SetInMap "menu-item" "icon" $value }}
{{ partial "widgets/menu/v-item.html" $ }}
{{ else }}
{{ $.Scratch.SetInMap "menu-item" "icon" $value.icon }}
{{ range $subEntry, $icon := $value }}
{{ $.Scratch.SetInMap "menu-item" "name" (printf "%s-%s-%s" $params.name $entry $subEntry) }}
{{ $.Scratch.SetInMap "menu-item" "icon" $icon }}
{{ partial "widgets/menu/v-item.html" $ }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ with $params.navigation }}
</nav>
{{ else }}
</div>
{{ end }}
......@@ -26,7 +26,7 @@
{{ $sizes := (dict "48" 2 "64" 3 "96" 4) }}
{{ $columnSpan := 2 }}
<div class="widget-pillar">
<div class="widget-pillar{{ with $pillar.class }} {{ . }}{{ end }}">
<style scoped="scoped">
/* Default size */
@supports (grid-area: auto) {
......@@ -72,12 +72,13 @@
{{ range $count, $i := $pillar.items }}
<div {{ with $pillar.childClass }}class="{{ . }}"{{ end }} style="grid-area: column{{ $count }};">
{{ if eq $i.type "menu" }}
<!-- Menu type needs name -->
{{ $params := $i.params }}
{{/* Can't join two dicts? That's sad :'( Now we have to use Scratch */}}
{{ $.Scratch.Set "menu" (dict "template" "v" "name" $i.name) }}
{{ $.Scratch.Set "menu" (dict "name" $i.name) }}
{{ range $key, $value := $i.params }}{{ $.Scratch.SetInMap "menu" $key $value }}{{ end }}
{{ partial "widgets/menu.html" $ }}
{{ partial "widgets/menu/v.html" $ }}
{{ else if eq $i.type "markdownmenu" }}
{{ $.Scratch.Set "menu" (dict "name" $i.name) }}
{{ range $key, $value := $i.params }}{{ $.Scratch.SetInMap "menu" $key $value }}{{ end }}
{{ partial "widgets/menu/vmarkdown.html" $ }}
{{ else if eq $i.type "template" }}
<!-- Template type needs name -->
{{ partial (printf "%s.html" ($i.name | strings.TrimSuffix ".html")) $ }}
......
......@@ -17,7 +17,6 @@ a:hover, a:visited, a:link, a:active { text-decoration: none; color: inherit; }
h1, h2, h3, h4, h5, h6 { margin: 0; font-family: "Fjalla One", sans-serif; }
p { overflow: hidden; }
p > img { margin: auto; display: block; max-width: 100%; }
li { text-align: justify; }
/* Functions */
.center { text-align: center; }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment