(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ function getServerUrl() { return `${location.origin}${location.origin.charAt(location.origin.length - 1) !== "/" ? "/" : "" }`; } module.exports = { getServerUrl, build: { protected_dirs: ["assets", "style", "articles"], default_meta_keys: ["title", "description", "image", "open_graph", "json_ld"], }, }; },{}],2:[function(require,module,exports){ const { getServerUrl } = require("./config"); module.exports = { images_url: `${getServerUrl()}assets/images/`, articles_url: `${getServerUrl()}articles/`, }; },{"./config":1}],3:[function(require,module,exports){ "use strict"; module.exports = { setRenderCycleRoot(renderCycleRoot) { this.renderCycleRoot = renderCycleRoot; }, objectToHtml: function objectToHtml(obj) { const { tag } = obj; const node = document.createElement(tag); const excludeKeys = ["tag", "contents", "style_rules", "state"]; Object.keys(obj) .filter(attr => !excludeKeys.includes(attr)) .forEach(attr => { if (attr === "class") { node.classList.add(...obj[attr].split(" ").filter(s => s !== "")); } else { node[attr] = obj[attr]; } }); if (obj.contents && typeof obj.contents === "string") { node.innerHTML = obj.contents; } else { obj.contents && obj.contents.length > 0 && obj.contents.forEach(el => { switch (typeof el) { case "string": node.innerHTML = el; break; case "object": node.appendChild(objectToHtml(el)); break; } }); } if (obj.style_rules) { Object.keys(obj.style_rules).forEach(rule => { node.style[rule] = obj.style_rules[rule]; }); } return node; }, renderCycle: function () { this.subRender(this.renderCycleRoot.render(), document.getElementsByTagName("main")[0], { mode: "replace", }); }, subRender(object, htmlNode, options = { mode: "append" }) { const insert = this.objectToHtml(object); switch (options.mode) { case "append": htmlNode.appendChild(insert); break; case "override": htmlNode.innerHTML = ""; htmlNode.appendChild(insert); break; case "insert-before": htmlNode.insertBefore(insert, htmlNode.childNodes[options.insertIndex]); break; case "adjacent": /** * options.insertLocation must be one of: * * afterbegin * afterend * beforebegin * beforeend */ htmlNode.insertAdjacentHTML(options.insertLocation, insert); break; case "replace": htmlNode.parentNode.replaceChild(insert, htmlNode); break; case "remove": htmlNode.remove(); break; } }, }; },{}],4:[function(require,module,exports){ "use strict"; const objectHtmlRenderer = require("object-to-html-renderer") class ImageCarousel { constructor(props) { this.props = props; this.id = performance.now(); this.state = { showImageIndex: 0, }; this.RUN_INTERVAL = 5000; this.props.images.length > 1 && this.run(); } run() { this.runningInterval = setInterval(() => { let { showImageIndex } = this.state; const { images } = this.props; this.state.showImageIndex = showImageIndex < images.length - 1 ? ++showImageIndex : 0; this.refreshImage(); }, this.RUN_INTERVAL); } setImageIndex(i) { clearInterval(this.runningInterval); this.state.showImageIndex = i; this.refreshImage(); } refreshImage() { objectHtmlRenderer.subRender(this.render(), document.getElementById(this.id), { mode: "replace", }); } render() { const { showImageIndex } = this.state; const { images } = this.props; return { tag: "div", id: this.id, class: "image-carousel", contents: [ { tag: "img", property: "image", alt: `image carousel ${images[showImageIndex].replace(/\.[A-Za-z]+/, "")}`, src: images[showImageIndex], }, images.length > 1 && { tag: "div", class: "carousel-bullets", contents: images.map((_, i) => { const active = showImageIndex === i; return { tag: "span", class: `bullet ${active ? "active" : ""}`, onclick: this.setImageIndex.bind(this, i), }; }), }, ], }; } } module.exports = ImageCarousel; },{"object-to-html-renderer":3}],5:[function(require,module,exports){ "use strict"; class KuadradoValues { render() { return { tag: "section", class: "kuadrado-values", contents: [ { tag: "div", class: "page-contents-center", contents: [ { tag: "h2", contents: "<blue>Éthique</blue>", }, { tag: "ul", class: "values-list", contents: [ [ "<emoji>📖</emoji> <blue>Partage des connaissances</blue>", `Pour sortir de l'élitisme de l'ingénierie, pour sortir de la domination par l'obscurantisme et de la consommation aveugle, pour aller plus loin ensemble, le partage du savoir est fondamental.`, ], [ "<emoji>💻</emoji> <blue>Logiciels libres et open source</blue>", `Toutes mes productions numériques, jeux vidéo, web, software, sont <b><a href="https://fr.wikipedia.org/wiki/Logiciel_libre" target="_blank">libres et open source</a></b>. <br/> ainsi que les outils engagés dans leur fabrication.`, ], [ "<emoji>🌿</emoji> <blue>Écologie</blue>", `Nous vivons une époque ou l'utilisation de la technologie connaît une croissance exponentielle notament à travers internet. <br/>Il est primordial de construire le numérique dans une direction de légèreté et d'économie de ressources.`, ], ].map(v => { const [title, body] = v; return { tag: "li", contents: [ { tag: "h3", contents: title }, { tag: "p", contents: body }, ], }; }), }, ], }, ], }; } } module.exports = KuadradoValues; },{}],6:[function(require,module,exports){ "use strict"; const { articles_url } = require("../../constants"); const objectHtmlRenderer = require("object-to-html-renderer"); const ImageCarousel = require("../generic-components/image-carousel"); const { loadArticles, getArticleDate, getArticleBody } = require("../lib/article-utils"); class NewsArticles { constructor() { this.id = performance.now().toString(); this.state = { loading: true, articles: [], showArticleIndex: -1, }; this.loadArticles(); } loadArticles() { loadArticles(`${articles_url}news`).then(articles => { this.state.articles = articles; this.state.showArticleIndex = this.state.articles.length - 1; this.refresh(); }); } refresh() { objectHtmlRenderer.subRender(this.render(), document.getElementById(this.id), { mode: "replace", }); } renderArticle(articleData) { return { tag: "article", class: `${articleData.images ? "grid-2" : "grid-1"}`, typeof: "Article", contents: [ { tag: "div", class: "date", contents: [ { tag: "time", property: "datePublished", contents: getArticleDate(articleData.date), }, ], }, { tag: "div", class: "title", contents: [ { tag: "h3", contents: articleData.title, property: "headline", }, ], }, { tag: "div", class: "subtitle", contents: [ { tag: "strong", contents: articleData.subtitle, property: "alternativeHeadline", }, ], }, { tag: "div", class: "body", contents: [ { tag: "p", contents: getArticleBody(articleData.body), property: "articleBody", }, ], }, articleData.images && new ImageCarousel({ images: articleData.images.map(img => `${articleData.path}/images/${img}`), }).render(), ], }; } renderArticlePlaceholder() { return { tag: "article", class: "article-placeholder", contents: [ { tag: "div", class: "date" }, { tag: "div", class: "title" }, { tag: "div", class: "subtitle" }, { tag: "div", class: "body" }, { tag: "div", class: "image-carousel" }, ], }; } handleChangeArticle(dir) { let { showArticleIndex, articles } = this.state; showArticleIndex = dir === "prev" ? showArticleIndex - 1 >= 0 ? showArticleIndex - 1 : 0 : showArticleIndex + 1 <= articles.length - 1 ? showArticleIndex + 1 : articles.length - 1; this.state.showArticleIndex = showArticleIndex; this.refresh(); } render() { const { articles, showArticleIndex } = this.state, showNext = showArticleIndex < articles.length - 1, showPrev = showArticleIndex > 0; return { tag: "div", id: this.id, class: "articles-displayer page-contents-center", contents: articles.length > 0 ? [ this.renderArticle(articles[showArticleIndex]), { tag: "div", class: "prev-next-buttons", contents: [ { tag: "button", class: `prev-btn ${!showPrev ? "disabled" : "active"}`, contents: "Précédent", onclick: this.handleChangeArticle.bind(this, "prev"), }, { tag: "button", class: `next-btn ${!showNext ? "disabled" : "active"}`, contents: "Suivant", onclick: this.handleChangeArticle.bind(this, "next"), }, ], }, ] : [this.renderArticlePlaceholder()], }; } } module.exports = NewsArticles; },{"../../constants":2,"../generic-components/image-carousel":4,"../lib/article-utils":10,"object-to-html-renderer":3}],7:[function(require,module,exports){ "use strict"; const { images_url } = require("../../constants"); class ThemeCard { constructor(props) { this.props = props; } render() { return { tag: "a", class: "theme-card", href: this.props.href, contents: [ { tag: "div", class: "card-img", contents: [{ tag: "img", alt:`thematic image ${this.props.img.replace(/\.[A-Za-z]+/, "")}`,src: `${images_url}${this.props.img}` }], }, { tag: "div", class: "card-title", contents: [{ tag: "h2", class: "section-title", contents: this.props.title }], }, { tag: "div", class: "card-description", contents: [{ tag: "p", contents: this.props.description }], }, ], }; } } module.exports = ThemeCard; },{"../../constants":2}],8:[function(require,module,exports){ "use strict"; class WhoAmI { render() { return { tag: "section", id: "whoami", contents: [ { tag: "div", class: "page-contents-center", contents: [ { tag: "h2", contents: "Qui sommes-nous-je ?", }, { tag: "div", class: "presentation-card", contents: [ { tag: "div", class: "header", contents: [ { tag: "div", class: "pic", contents: [ { tag: "img", alt: "portrait Pierre Jarriges pixel art by Lucie Ventadour", src: "assets/images/pijar_profile_lt_square.png", }, ], }, { tag: "div", class: "header-text", contents: [ { tag: "h3", contents: "Pierre Jarriges", }, { tag: "h4", contents: "Artiste, auteur BD, compositeur, développeur informatique", }, { tag: "strong", contents: "Créateur de <blue>Kuadrado Software</blue> en Février 2021.", }, ], }, ], }, { tag: "div", class: "body", contents: [ { tag: "p", contents: ` “ La création de <b><blue>Kuadrado Software</blue></b> vient de la volonté de développer différents axes ensembles : <br /><br /> <emoji>🎮</emoji> D'une part exprimer une passion en créant des <b>jeux vidéo indépendants</b> sur un modèle léger et artisanal dans une identité artistique forte, et de les distribuer sans compromission par une logique du marché ; en effet, partir à la conquête du marché à dos de startup n'est pas l'objectif de Kuadrado Software. Il s'agit avant tout de se donner les moyens de partager avec le monde une idée de liberté, de partage et de plaisir de créer des choses simples. <br /><br /> <emoji>💡</emoji> D'autre part il s'agit aussi de porter un <b>projet pédagogique</b> autour de la création de jeu vidéo, et plus largement de la vulgarisation numérique. Le partage de connaissances et l'apprentissage collectif étant pour moi l'instrument le plus efficace de lutte contre l'élitisme, contre le cloisonnement face à la technologie (et donc à sa surconsommation), et tout simplement un moyen d'ouverture vers les autres. <br /><br /> À l'heure d'aujourd'hui Kuadrado Software est construit sur un modèle d'auto-entreprise. <br /> Cependant le but n'est pas de tout développer seul, il s'agit bien de pouvoir à terme rassembler plusieurs énergies dans le même état d'esprit, former des équipes de travail et de création, et s'inscrire dans un tissu local de savoir-faire, tout en gardant un modèle d'entreprise basé sur l'indépendance, afin de rester aussi léger, libéral, et modulaire que possible.” `, }, ], }, ], }, ], }, ], }; } } module.exports = WhoAmI; },{}],9:[function(require,module,exports){ "use strict"; const { images_url } = require("../constants"); const KuadradoValues = require("./home-page-components/kuadrado-values"); const NewsArticles = require("./home-page-components/news-articles"); const ThemeCard = require("./home-page-components/theme-card"); const WhoAmI = require("./home-page-components/whoami"); const WebPage = require("./lib/web-page"); class HomePage extends WebPage { render() { return { tag: "div", id: "home-page", contents: [ { tag: "div", class: "page-header", contents: [ { tag: "div", class: "big-logo page-contents-center", contents: [ { tag: "img", alt: "logo Kuadrado", src: `${images_url}logo_kuadrado.svg`, }, { tag: "img", class: "logo-text", alt: "Kuadrado", src: `${images_url}logo_kuadrado_txt.svg`, }, ], }, { tag: "h1", contents: "Kuadrado Software", class: "page-contents-center" }, { tag: "p", class: "page-contents-center", contents: `Studio de création de jeux vidéo basé en Ardèche, Vernoux en Vivarais.<br />Création artisitique numérique | Développement d'outillage logiciel libre et open source | Pédagogie.`, }, { tag: "ul", class: "philo-bubbles", contents: ["Simplicité", "Légèreté", "Écologie"].map(word => { return { tag: "li", contents: [{ tag: "span", contents: word }], }; }), }, ], }, { tag: "section", class: "page-contents-center poles", contents: [ { title: "Jeux", img: "game_controller.svg", href: "/games/", description: "Créations vidéoludiques, jeux web et jeux PC, projets en cours.", }, { title: "Pédagogie", img: "brain.svg", href: "/education/", description: `S'approprier la technologie par le partage de connaissances.`, }, { title: "Software", img: "meca_proc.svg", href: "/software-development/", description: `R&D, projets expérimentaux, web et outillage logiciel`, }, ].map(cardProps => new ThemeCard(cardProps).render()), }, // { // tag: "section", // class: "page-philo", // contents: [ // { // tag: "p", // class: "page-contents-center", // contents: `Travailler pour le plaisir de créer, de maîtriser et de comprendre.`, // }, // ], // }, // { // tag: "section", // class: "page-contents-center", // id:"news", // contents: [ // { tag: "h2", contents: "Actu", class: "section-title" }, // new NewsArticles().render(), // ], // }, // new KuadradoValues().render(), // new WhoAmI().render(), ], }; } } module.exports = HomePage; },{"../constants":2,"./home-page-components/kuadrado-values":5,"./home-page-components/news-articles":6,"./home-page-components/theme-card":7,"./home-page-components/whoami":8,"./lib/web-page":12}],10:[function(require,module,exports){ "use strict"; const { fetchjson, fetchtext } = require("./fetch"); function getArticleBody(text) { return text.replaceAll("\n", "<br/>"); } function getArticleDate(date) { return `${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}`; } function loadArticles(dir_url) { return new Promise((resolve, reject) => { fetchjson(`${dir_url}/index.json`) .then(json => { Promise.all( json.articles.map(async artDir => { const artPath = `${artDir}/${artDir}.json`; const art = await fetchjson(`${dir_url}/${artPath}`); const tmpSplit = artPath.split("/"); tmpSplit.pop(); const absArtPath = `${dir_url}/${tmpSplit.join("/")}`; return Object.assign(art, { path: absArtPath }); }) ) .then(articles => { populateArticles(articles) .then(completeArticles => resolve(completeArticles)) .catch(e => reject(e)); }) .catch(e => reject(e)); }) .catch(e => console.log(e)); }); } function populateArticles(articles) { return new Promise((resolve, reject) => { Promise.all( articles.map(async article => { if (article.body.indexOf("<file>") !== -1) { const txtPath = article.body.replace("<file>", ""); const textValue = await fetchtext(`${article.path}/${txtPath}`); article.body = textValue; article.date = article.date ? new Date(article.date) : undefined; } return article; }) ) .then(completeArticles => resolve(completeArticles.sort((a, b) => b.date - a.date))) .catch(e => reject(e)); }); } module.exports = { loadArticles, getArticleBody, getArticleDate, populateArticles, }; },{"./fetch":11}],11:[function(require,module,exports){ "use strict"; function fetchjson(url) { return new Promise((resolve, reject) => { fetch(url) .then(r => r.json()) .then(r => resolve(r)) .catch(e => reject(e)); }); } function fetchtext(url) { return new Promise((resolve, reject) => { fetch(url) .then(r => r.text()) .then(r => resolve(r)) .catch(e => reject(e)); }); } module.exports = { fetchjson, fetchtext, }; },{}],12:[function(require,module,exports){ "use strict"; class WebPage { constructor(args) { Object.assign(this, args); } } module.exports = WebPage; },{}],13:[function(require,module,exports){ "use strict"; const HomePage = require("./homepage"); const runPage = require("./run-page"); runPage(HomePage); },{"./homepage":9,"./run-page":14}],14:[function(require,module,exports){ "use strict"; const objectHtmlRenderer = require("object-to-html-renderer") const Template = require("./template/template"); module.exports = function runPage(PageComponent) { const template = new Template({ page: new PageComponent() }); objectHtmlRenderer.setRenderCycleRoot(template); objectHtmlRenderer.renderCycle(); }; },{"./template/template":16,"object-to-html-renderer":3}],15:[function(require,module,exports){ "use strict"; const { images_url } = require("../../../constants"); const NAV_MENU_ITEMS = [ { url: "/games/", text: "Jeux" }, { url: "/education/", text: "Pédagogie", // submenu: [ // { url: "/gamedev", text: "Création de jeux vidéo" }, // ] }, { url: "/software-development/", text: "Software" } ]; class NavBar { constructor() { this.initEventHandlers(); } handleBurgerClick() { document.getElementById("nav-menu-list").classList.toggle("responsive-show"); } initEventHandlers() { window.addEventListener("click", event => { if ( event.target.id !== "nav-menu-list" && !event.target.classList.contains("burger") && !event.target.parentNode.classList.contains("burger") ) { document.getElementById("nav-menu-list").classList.remove("responsive-show"); } }); } renderHome() { return { tag: "div", class: "home", contents: [ { tag: "a", href: "/", contents: [ { tag: "img", alt: "Logo Kuadrado", src: `${images_url}logo_kuadrado.svg`, }, { tag: "img", alt: "Kuadrado Software", class: "logo-text", src: `${images_url}logo_kuadrado_txt.svg`, }, ], }, ], }; } renderMenu(menuItemsArray, isSubmenu = false, parentUrl = "") { return { tag: "ul", id: "nav-menu-list", class: isSubmenu ? "submenu" : "", contents: menuItemsArray.map(item => { const { url, text, submenu } = item; const href = `${parentUrl}${url}`; return { tag: "li", class: !isSubmenu && window.location.pathname === href ? "active" : "", contents: [ { tag: "a", href, contents: text, }, ].concat(submenu ? [this.renderMenu(submenu, true, url)] : []), }; }), }; } renderResponsiveBurger() { return { tag: "div", class: "burger", onclick: this.handleBurgerClick.bind(this), contents: [{ tag: "span", contents: "···" }], }; } render() { return { tag: "nav", contents: [ this.renderHome(), this.renderResponsiveBurger(), this.renderMenu(NAV_MENU_ITEMS), ], }; } } module.exports = NavBar; },{"../../../constants":2}],16:[function(require,module,exports){ "use strict"; const { in_construction } = require("../../config"); const { images_url } = require("../../constants"); const NavBar = require("./components/navbar"); class Template { constructor(props) { this.props = props; } render() { return { tag: "main", contents: [ { tag: "header", contents: [new NavBar().render()], }, in_construction && { tag: "section", class: "warning-banner", contents: [ { tag: "strong", class: "page-contents-center", contents: "Site en construction ...", }, ], }, { tag: "section", id: "page-container", contents: [this.props.page.render()], }, { tag: "footer", contents: [ { tag: "div", class: "logo", contents: [ { tag: "img", alt: `logo Kuadrado`, src: `${images_url}logo_kuadrado.svg`, }, { tag: "img", class: "text-logo", alt: "Kuadrado Software", src: `${images_url}logo_kuadrado_txt.svg`, }, ], }, { tag: "span", contents: "32 rue Simon Vialet, 07240 Vernoux en Vivarais. Ardèche, France", }, { tag: "div", contents: [ { tag: "strong", contents: "<blue>Contact : </blue>" }, { tag: "a", href: "mailto:contact@kuadrado-software.fr", contents: "contact@kuadrado-software.fr", }, ], }, { tag: "div", class: "social", contents: [ { tag: "strong", contents: "<blue>Sur les réseaux : </blue>", }, { tag: "a", href: "https://www.linkedin.com/company/kuadrado-software", target: "_blank", contents: "in", title: "Linkedin", }, { tag: "a", href: "https://twitter.com/KuadradoSoft", target: "_blank", contents: "t", title: "Twitter", style_rules: { fontFamily: "serif" }, }, ], }, { tag: "span", contents: `Copyright © ${new Date() .getFullYear()} Kuadrado Software | Toutes les images du site ont été réalisées par mes soins et peuvent être réutilisées pour un usage personnel.`, }, ], }, ], }; } } module.exports = Template; },{"../../config":1,"../../constants":2,"./components/navbar":15}]},{},[13]);