Bladeren bron

Alucho site. First commit.

Marcelo Fornet 5 jaren geleden
commit
eb60c4280b

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+build/
+.vscode/

+ 13 - 0
languages/es.txt

@@ -0,0 +1,13 @@
+graphic designer:diseñador gráfico
+work:trabajo
+news:noticias
+about:acerca de
+contact:contacto
+shop:tienda
+all:todos
+poster:poster
+illustration:ilustración
+editorial:editorial
+branding:marca
+other:otros
+About Alejandro:Sobre Alejandro

+ 76 - 0
layout/_base.html

@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+	<meta charset="UTF-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1.0">
+	<meta http-equiv="X-UA-Compatible" content="ie=edge">
+	<title>Alucho Portfolio</title>
+	<link rel="stylesheet" href="{{ 'css/main.css' | static }}">
+	<script src="{{ 'js/eye.js' | static }}"></script>
+</head>
+<body>
+	<header>
+		<div class="header-box">
+			<div class="lbox">
+				<div class="vbox">
+					<a class="first en {% if en %}selected{% endif %}" href="{{ 'en' | lang_url }}">en</a>
+					<a class="first {% if es %}selected{% endif %}" href="{{ 'es' | lang_url }}">es</a>
+				</div>
+				<object id="logo" type="image/svg+xml" data="{{ 'svg/alucho-logo.svg' | static }}"></object>
+				<div class="vbox">
+					<div id="alucho-title" class="hbox"><h1 class="header-title"><a>Alucho Rodríguez</a></h1></div>
+					<div id="designer-subtitle" class="hbox"><a>{{ 'graphic designer' | lang }}</a></div>
+				</div>
+			</div>
+			<div id="menu" class="rbox">
+					<div class="vbox">
+						<div class="hbox">
+							<h1 class="header-title">
+								<div><a href="/work" {% block work_selected %}{% endblock %}>{{ 'work' | lang }}</a></div> /
+								<div><a href="/news" {% block news_selected %}{% endblock %}>{{ 'news' | lang }}</a></div> /
+								<div><a href="/about"{% block about_selected %}{% endblock %}>{{ 'about' | lang }}</a></div> /
+								<div><a href="/contact" {% block contact_selected %}{% endblock %}>{{ 'contact' | lang }}</a></div> /
+								<div><a href="/shop"{% block shop_selected %}{% endblock %} >{{ 'shop' | lang }}</a></div>
+							</h1>
+						</div>
+						<div class="hbox">
+							<div class="header-subtitle">
+								<div><a href="/work/all" {% block all_selected %}{% endblock %}>{{ 'all' | lang }}</a></div> /
+								<div><a href="/work/poster" {% block poster_selected %}{% endblock %}>{{ 'poster' | lang }}</a></div> /
+								<div><a href="/work/illustration" {% block illustration_selected %}{% endblock %}>{{ 'illustration' | lang }}</a></div> /
+								<div><a href="/work/editorial" {% block editorial_selected %}{% endblock %}>{{ 'editorial' | lang }}</a></div> /
+								<div><a href="/work/branding" {% block branding_selected %}{% endblock %}>{{ 'branding' | lang }}</a></div> /
+								<div><a href="/work/other" {% block other_selected %}{% endblock %}>{{ 'other' | lang }}</a></div>
+							</div>
+						</div>
+					</div>
+			</div>
+		</div>
+	</header>
+	<div id="main" class="v">
+		<div class="main-content">
+			{% block main %}
+			{% endblock %}
+		</div>
+	</div>
+	<footer>
+		<h3>
+			copyright / <a href="/">www.alucho.com</a> / 2019 / <a href="/contact">{{ 'contact' | lang }}</a>
+		</h3>
+	</footer>
+
+	<form name="setLangEnglish" action="/i18n/setlang/" method="POST">
+		{# {% csrf_token %} #}
+		<input name="next" type="hidden" value="{{ path }}"/>
+		<input type="hidden" name="language" value="en"/>
+	</form>
+
+	<form name="setLangSpanish" action="/i18n/setlang/" method="POST">
+		{# {% csrf_token %} #}
+		<input name="next" type="hidden" value="{{ path }}"/>
+		<input type="hidden" name="language" value="es"/>
+	</form>
+
+	<script src="{{ 'js/eye.js' | static }}"></script>
+</body>
+</html>

+ 3 - 0
layout/_work_no_all.html

@@ -0,0 +1,3 @@
+{% extends "work.html"%}
+
+{% block all_selected %}{% endblock %}

+ 7 - 0
layout/about.html

@@ -0,0 +1,7 @@
+{% extends "_base.html"%}
+
+{% block about_selected %}class="selected"{% endblock %}
+
+{% block main %}
+{{ "About Alejandro" | lang }}
+{% endblock %}

+ 6 - 0
layout/contact.html

@@ -0,0 +1,6 @@
+{% extends "_base.html"%}
+
+{% block contact_selected %}class="selected"{% endblock %}
+
+{% block main %}
+{% endblock %}

+ 1 - 0
layout/index.html

@@ -0,0 +1 @@
+{% extends "work.html"%}

+ 6 - 0
layout/news.html

@@ -0,0 +1,6 @@
+{% extends "_base.html"%}
+
+{% block news_selected %}class="selected"{% endblock %}
+
+{% block main %}
+{% endblock %}

+ 6 - 0
layout/shop.html

@@ -0,0 +1,6 @@
+{% extends "_base.html"%}
+
+{% block shot_selected %}class="selected"{% endblock %}
+
+{% block main %}
+{% endblock %}

+ 14 - 0
layout/work.html

@@ -0,0 +1,14 @@
+{% extends "_base.html"%}
+
+{% block work_selected %}class="selected"{% endblock %}
+{% block all_selected %}class="selected"{% endblock %}
+
+{% block main %}
+    <div class="sqr-item"><img src="{{ 'image/tile.jpg' | static }}" alt="Ejemplo"></div>
+    <div class="sqr-item"><img src="{{ 'image/tile.jpg' | static }}" alt="Ejemplo"></div>
+    <div class="sqr-item"><img src="{{ 'image/tile.jpg' | static }}" alt="Ejemplo"></div>
+    <div class="sqr-item"><img src="{{ 'image/tile.jpg' | static }}" alt="Ejemplo"></div>
+    <div class="sqr-item"><img src="{{ 'image/tile.jpg' | static }}" alt="Ejemplo"></div>
+    <div class="sqr-item"><img src="{{ 'image/tile.jpg' | static }}" alt="Ejemplo"></div>
+    <div class="sqr-item"><img src="{{ 'image/tile.jpg' | static }}" alt="Ejemplo"></div>
+{% endblock %}

+ 3 - 0
layout/work/all.html

@@ -0,0 +1,3 @@
+{% extends "work.html"%}
+
+{% block all_selected %}class="selected"{% endblock %}

+ 3 - 0
layout/work/branding.html

@@ -0,0 +1,3 @@
+{% extends "_work_no_all.html"%}
+
+{% block branding_selected %}class="selected"{% endblock %}

+ 3 - 0
layout/work/editorial.html

@@ -0,0 +1,3 @@
+{% extends "_work_no_all.html"%}
+
+{% block editorial_selected %}class="selected"{% endblock %}

+ 3 - 0
layout/work/illustration.html

@@ -0,0 +1,3 @@
+{% extends "_work_no_all.html"%}
+
+{% block illustration_selected %}class="selected"{% endblock %}

+ 3 - 0
layout/work/other.html

@@ -0,0 +1,3 @@
+{% extends "_work_no_all.html"%}
+
+{% block other_selected %}class="selected"{% endblock %}

+ 3 - 0
layout/work/poster.html

@@ -0,0 +1,3 @@
+{% extends "_work_no_all.html"%}
+
+{% block poster_selected %}class="selected"{% endblock %}

+ 4 - 0
run_server.sh

@@ -0,0 +1,4 @@
+#!/bin/bash
+python3 sitegen.py --with_index
+cd build
+python3 -m http.server 8001

+ 143 - 0
sitegen.py

@@ -0,0 +1,143 @@
+import argparse
+from jinja2 import Environment, FileSystemLoader, contextfilter
+from pathlib import Path
+from os import walk, makedirs
+from os.path import join, exists, splitext, split
+from shutil import rmtree, copy, copytree
+from functools import lru_cache
+
+LANGUAGES = 'languages'
+
+DEFAULT_LANG = 'en'
+REGISTERED_LANG = set()
+
+
+@lru_cache(None)
+def get_lang_dic(lang):
+    if not exists(LANGUAGES):
+        makedirs(LANGUAGES)
+
+    lang_file = join(LANGUAGES, lang + '.txt')
+
+    if not exists(lang_file):
+        return {}
+    else:
+        dic = {}
+        with open(lang_file) as f:
+            for line in f.readlines():
+                key, value = line.strip('\n').split(':')
+                dic[key] = value
+        return dic
+
+
+def save_dic(lang, dic):
+    with open(join(LANGUAGES, lang + '.txt'), 'w') as f:
+        for key, value in dic.items():
+            f.write(f"{key}:{value}\n")
+
+
+@contextfilter
+def lang(ctx, value):
+    lang = ctx.environment.globals['lang']
+
+    if lang == DEFAULT_LANG:
+        return value
+
+    else:
+        dic = get_lang_dic(lang)
+
+        if value in dic and dic[value]:
+            return dic[value]
+        else:
+            dic[value] = ""
+            save_dic(lang, dic)
+            print(f"Not translated phrase: `{value}`")
+            return value
+
+@contextfilter
+def lang_url(ctx, value):
+    name, _ = splitext(ctx.name)
+    if name.startswith('./'):
+        name = name[2:]
+
+    if value == DEFAULT_LANG:
+        return "/" + name
+    else:
+        REGISTERED_LANG.add(value)
+        return "/" + value + '/' + name
+
+
+def static(value):
+    return f"/static/{value}"
+
+
+def compile(env, path, target):
+    lang = env.globals['lang']
+
+    for base, _, docs in walk(path):
+        cur_base = Path(base)
+        cur_base = Path(*cur_base.parts[1:])
+        for doc in docs:
+            if doc.startswith('_'):
+                # Ignore this files
+                continue
+
+            src = join(base, doc)
+
+            if args.with_index and doc != 'index.html':
+                name, _ = splitext(doc)
+                dst = join(cur_base, name, 'index.html')
+            else:
+                dst = join(cur_base, doc)
+
+            if lang != DEFAULT_LANG:
+                dst = join(lang, dst)
+
+            dst = join(target, dst)
+            dst_folder, _ = split(dst)
+
+            if not exists(dst_folder):
+                makedirs(dst_folder)
+
+            template = env.get_template(join(cur_base, doc))
+            output = template.render()
+
+            with open(dst, 'w') as f:
+                f.write(output)
+
+def run(args):
+    # Load layout
+    file_loader = FileSystemLoader(args.source)
+    env = Environment(loader=file_loader)
+    env.globals['lang'] = DEFAULT_LANG
+
+    # Add filters
+    env.filters['lang'] = lang
+    env.filters['lang_url'] = lang_url
+    env.filters['static'] = static
+
+    path = Path(args.source)
+
+    if exists(args.target):
+        rmtree(args.target)
+
+    makedirs(args.target)
+
+    compile(env, path, args.target)
+
+    copytree('static', join(args.target, 'static'))
+
+    for other_lang in REGISTERED_LANG:
+        env.globals['lang'] = other_lang
+        compile(env, path, args.target)
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser("Site generator")
+
+    parser.add_argument('--with_index', action='store_true', default=False)
+    parser.add_argument('--source', default='layout')
+    parser.add_argument('--target', default='build')
+
+    args = parser.parse_args()
+    run(args)
+

+ 255 - 0
static/css/main.css

@@ -0,0 +1,255 @@
+/* Variables */
+:root {
+	--columns: 5;
+	--tile-margin: .9vw;
+	--body-margin: 3.6vw;
+	/* --tile-margin: 12.75px; */
+	/* --body-margin: 66px; */
+	--header-inner-space: calc(8 * var(--tile-margin));
+	--header-space: calc(10 * var(--tile-margin) - 10px);
+}
+/* Columns */
+/* @media (max-width: 1500px) {
+	:root { --columns: 5; }
+}
+@media (max-width: 1000px) {
+	:root { --columns: 4; }
+}
+@media (max-width: 700px) {
+	:root { --columns: 3; }
+}
+@media (max-width: 500px) {
+	:root { --columns: 2; }
+}
+@media (max-width: 400px) {
+	:root { --columns: 1; }
+} */
+/* Font Size */
+:root {
+	/* font-size: 180%; */
+	font-size: 1.2vw;
+	font-weight: 100;
+}
+h1 {
+	/* font-size: 97%; */
+	font-size: 1.18vw;
+}
+/* @media (max-width: 1500px) {
+	:root { font-size: 22px; }
+	h1 { font-size: 22px; }
+}
+@media (max-width: 1240px) {
+	:root { font-size: 18px; }
+}
+@media (max-width: 1080px) {
+	:root { font-size: 16px; }
+} */
+/* Margins */
+/* @media (max-width: 1080px) {
+	:root {
+		--tile-margin: 12.75px;
+		--body-margin: 33px;
+	}
+} */
+/* Header */
+@media (max-width: 935px) {
+	#menu { visibility: hidden; }
+}
+#logo {
+	width: 9vw;
+	margin: 0 21.5px .2em 15px;
+}
+/* @media (max-width: 460px) {
+	#logo { width: 130px; }
+} */
+/* Typographies */
+@font-face {
+	font-family: 'nexa-light';
+	src: url('/static/font/nexa-light-regular.otf') format('opentype');
+}
+@font-face {
+	font-family: 'geoslab';
+	src: url('/static/font/geoslab703-md-bt-bold.ttf') format('truetype');
+}
+/* Rules */
+:root {
+	font-family: 'nexa-light';
+	letter-spacing: 1.5px;
+}
+.sec-div {
+	font-weight: bold;
+	font-family: 'nexa-light';
+}
+a {
+	color: black;
+	margin: .05rem .3rem;
+	text-decoration: none;
+}
+a.en {
+	margin-bottom: .5em;
+}
+h1 {
+	margin: .5em 0;
+	text-align: center;
+	letter-spacing: 1px;
+	font-weight: 100;
+	font-family: 'geoslab';
+	text-decoration: none;
+	text-transform: uppercase;
+}
+h2 {
+	font-size: .9em;
+	font-family: 'geoslab';
+	text-decoration: none;
+	text-transform: uppercase;
+}
+h3 {
+	font-size: 20px;
+	font-family: 'nexa-light';
+}
+a.current, a[href]:hover {
+	/* cursor: default; */
+	/* display: inline-block; */
+	color: #ff2d00;
+}
+
+a.selected {
+	color: #ff2d00;
+}
+
+div {
+	display: flex;
+}
+body {
+	width: calc(100% - 2*var(--body-margin));
+	margin: 0 var(--body-margin);
+	/* width: 94%;
+	margin: 0 3%; */
+	/* width: calc(100% - 2*var(--body-margin)); */
+	/* margin: 0 var(--body-margin); */
+	position: absolute;
+}
+header {
+	width: calc(100% - 2*(var(--body-margin)));
+	margin: 0;
+	/* width: calc(100% - 2*(var(--body-margin) + var(--tile-margin))); */
+	/* margin: 0 var(--tile-margin); */
+	/* width: 100%; */
+	/* margin: 0 calc(var(--body-margin) + var(--tile-margin)); */
+
+
+	display: flex;
+	flex-direction: column;
+	/* margin: 0 0 0 var(--tile-margin); */
+	justify-content: flex-end;
+	position: fixed;
+	/* width: calc(100% - 2*var(--body-margin) - 2*var(--tile-margin)); */
+	background-color: white;
+	/* padding-bottom: calc(2*var(--tile-margin)); */
+	/* border-bottom: calc(2*var(--tile-margin)); */
+	height: var(--header-space);
+	position: fixed;
+	z-index: 1;
+}
+/* header::after {
+	content: " ";
+	background-color: black;
+	height: var(--header-line-width);
+	width: 100%;
+	align-self: flex-start;
+} */
+.header-box {
+	padding-bottom: calc(2 * var(--tile-margin));
+	overflow: hidden;
+	display: flex;
+	flex-direction: row;
+	align-items: flex-end;
+	justify-content: space-between;
+	flex-wrap: wrap;
+	height: var(--header-inner-space);
+}
+.vbox {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+}
+.rbox .vbox {
+	align-items: flex-end;
+}
+.lbox .vbox {
+	align-items: flex-start;
+}
+.hbox {
+	display: flex;
+	flex-direction: row;
+	align-items: center;
+}
+.lbox {
+	display: flex;
+	flex-direction: row;
+	align-items: flex-end;
+	justify-content: flex-start;
+}
+.rbox {
+	display: flex;
+	flex-direction: row;
+	align-items: center;
+	justify-content: flex-end;
+}
+.header-subtitle {
+	display: flex;
+	flex-direction: row;
+	flex-wrap: wrap;
+	justify-content: flex-end;
+	align-items: center;
+	margin-top: 0;
+}
+#alucho-title, #designer-subtitle {
+	flex-wrap: wrap;
+}
+.no-bottom {
+	margin-bottom: 0;
+}
+.header-title {
+	display: flex;
+	flex-direction: row;
+	flex-wrap: wrap;
+	justify-content: flex-end;
+	align-items: center;
+	/* margin-bottom: 8px; */
+}
+/* header > a, header > h1 {
+	margin: 0 3px;
+} */
+/* .header-subtitle > a {
+	margin: 0 5px;
+} */
+a.first {
+	margin-left: var(--tile-margin);
+}
+a.last {
+	margin-right: var(--tile-margin);
+}
+.main-content {
+	display: flex;
+	flex-direction: row;
+	flex-wrap: wrap;
+	justify-content: flex-start;
+	margin-top: var(--header-space);
+	/* margin: 0; */
+	/* margin-top: calc(var(--header-space) + var(--body-margin)); */
+	position: static;
+}
+.sqr-item {
+	display: flex;
+	width: calc(100% / var(--columns) - 2 * var(--tile-margin));
+	margin: var(--tile-margin);
+}
+.sqr-item img {
+	width: 100%;
+}
+.sqr-item svg {
+	width: 100%;
+	height: 100%;
+	background-color: #bbb9ba;
+}

BIN
static/font/geoslab703-md-bt-bold.ttf


BIN
static/font/nexa-light-regular.otf


BIN
static/image/tile.jpg


BIN
static/image/white.jpg


+ 36 - 0
static/js/eye.js

@@ -0,0 +1,36 @@
+// nilox (c)
+
+window.onload = function () {
+    var eye = document.getElementById('logo');
+
+    var eyeDoc = eye.contentDocument;
+    const logo = eyeDoc.getElementById('alucho-logo');
+    const iris = eyeDoc.getElementById('iris');
+    const pupil = eyeDoc.getElementById('pupil');
+
+    // #iris cx attribute animation settings (relative to #alucho-logo i.e. absolute inside the svg)
+    const istart = 56;
+    const iend = 116;
+    const ilength = iend - istart;
+
+    // #pupil cx attribute animation settings (relative to #iris cx)
+    const pstart = -17;
+    const pend = 17;
+    const plength = pend - pstart;
+    const oY = logo.getAttribute('height') / 2.;
+
+    window.onmousemove = function (ev) {
+        const r = ev.clientX / window.innerWidth;
+
+        const iX = istart + ilength * r;
+        iris.setAttribute('cx', iX);
+
+        const pX = iX + pstart + plength * r;
+        const pY = oY + 16 * r * (1 - r);
+        // p(r) = y0 + a * r * (1 - r) is a parabola
+        // p(0) = p(1) = y0
+        // p(.5) = y0 + a / 4
+        pupil.setAttribute('cx', pX);
+        pupil.setAttribute('cy', pY);
+    };
+};

File diff suppressed because it is too large
+ 5 - 0
static/js/jquery.min.js


File diff suppressed because it is too large
+ 52 - 0
static/svg/alucho-logo.svg


File diff suppressed because it is too large
+ 52 - 0
static/svg/alucho-logo.svg.bak