3 Commits

18 changed files with 369 additions and 189 deletions

24
app.py
View File

@@ -4,7 +4,7 @@ import datetime
from sass import compile as compile_sass
from flask import Flask, redirect, request, url_for, g, Response
from modules import autobuild, locales, helpers, slides
from modules import autobuild, locales, helpers
# ---------- APP CONFIG ------------------------------------------------------
@@ -12,9 +12,7 @@ from modules import autobuild, locales, helpers, slides
app = Flask(__name__)
# load locales and slides
locales.ensure_loaded()
SLIDES = slides.load_slides(app.root_path)
# CSS Compilation and minification
if app.debug:
@@ -47,17 +45,16 @@ def before_request():
@app.context_processor
def _inject_autobuild_vers():
return {'autobuild_vers': autobuild.autobuild_vers}
return {"autobuild_vers": autobuild.autobuild_vers}
@app.context_processor
def _inject_autobuild_date():
return {'autobuild_date': autobuild.autobuild_date}
@app.context_processor
def _inject_slides():
return {"slides": SLIDES}
return {
"autobuild_date": g.translations.get("downloads", {})
.get("date-format", "{DD}.{MM}.{YYYY}")
.format(**autobuild.autobuild_date)
}
@app.context_processor
@@ -65,16 +62,17 @@ def inject_translations():
def translate(text, **kwargs):
section, key = text.split(":", 1)
template = g.translations \
.get(section, {}) \
template = (
g.translations.get(section, {})
.get(key, f"${section}: {key}$")
)
try:
return template.format(**kwargs)
except Exception:
return template
return {'_': translate}
return {"_": translate}
# ---------- ROUTES -------------------------------------------------------

View File

@@ -51,6 +51,7 @@ header = Herunterladen
version = Version:
date = Build-Datum:
date-format = {DD}.{MM}.{YYYY}
img-descr = Disketten-Image
iso-descr = LiveCD-Abbild
@@ -65,10 +66,10 @@ screenshots = Bildschirmfotos
download_choice = Was soll ich wählen?
download_help = Für einen Einsteiger ist die LiveCD am besten geeignet.\n\
\n\
Im Vergleich zu einer LiveCD hat ein universelles Image den Vorteil, dass\
Im Vergleich zu einer LiveCD hat ein universelles Image den Vorteil, dass \
Sie die in KolibriOS vorgenommenen Änderungen speichern können.\n\
\n\
Das Hybrid-Image enthält Unterstützung für die UEFI-Technologie, die zum\
Das Hybrid-Image enthält Unterstützung für die UEFI-Technologie, die zum \
Booten des Systems auf neuen Computern und Laptops verwendet wird.
download_description = Auf dieser Seite können Sie die nächtlichen

View File

@@ -49,6 +49,7 @@ header = Downloads
version = Version:
date = Build date:
date-format = {DD}/{MM}/{YYYY}
img-descr = Floppy disk image
iso-descr = LiveCD image
@@ -61,10 +62,10 @@ all_rev = All nightly builds
download_choice = Which to choose?
download_help = For a beginner, the LiveCD is best.\n\
\n\
Compared to a LiveCD, the advantage of a universal image is that you can\
Compared to a LiveCD, the advantage of a universal image is that you can \
save changes made in KolibriOS.\n\
\n\
Hybrid image includes support for UEFI technology, which is used to boot\
Hybrid image includes support for UEFI technology, which is used to boot \
the system on new computers and laptops.
download_description = On this page you can download the nightly builds

View File

@@ -51,6 +51,7 @@ header = Descargas
version = Versión:
date = Fecha de compilación:
date-format = {DD}.{MM}.{YYYY}
img-descr = Imagen de disquete
iso-descr = Imagen LiveCD
@@ -63,10 +64,10 @@ all_rev = Todos los montajes nocturnos
download_choice = ¿Cuál elegir?
download_help = Para un principiante, el LiveCD es lo mejor.\n\
\n\
En comparación con un LiveCD, la ventaja de una imagen universal es que\
En comparación con un LiveCD, la ventaja de una imagen universal es que \
puedes guardar los cambios realizados en KolibriOS.\n\
\n\
Imagen híbrida incluye soporte para la tecnología UEFI, que se utiliza para\
Imagen híbrida incluye soporte para la tecnología UEFI, que se utiliza para \
arrancar el sistema en los nuevos ordenadores y portátiles.
download_description = En esta página puedes descargar la distribución de

View File

@@ -51,6 +51,7 @@ header = Téléchargements
version = Version :
date = Date de compilation :
date-format = {DD}/{MM}/{YYYY}
img-descr = Image de la disquette
iso-descr = Image du LiveCD
@@ -63,10 +64,10 @@ all_rev = Toutes les constructions nocturnes
download_choice = Que choisir ?
download_help = Pour un débutant, le LiveCD est le meilleur.\n\
\n\
Par rapport à un LiveCD, l`avantage d`une image universelle est que vous\
Par rapport à un LiveCD, l`avantage d`une image universelle est que vous \
pouvez sauvegarder les changements effectués dans KolibriOS.\n\
\n\
L`image hybride inclut le support de la technologie UEFI, qui est utilisée\
L`image hybride inclut le support de la technologie UEFI, qui est utilisée \
pour démarrer le système sur les nouveaux ordinateurs et portables.
download_description = Sur cette page, vous pouvez télécharger la distribution

View File

@@ -50,6 +50,7 @@ header = Scaricamento
version = Versione:
date = Data di compilazione:
date-format = {DD}/{MM}/{YYYY}
img-descr = Immagine su dischetto
iso-descr = Immagine LiveCD
@@ -62,10 +63,10 @@ all_rev = Tutte le build notturne
download_choice = Quale scegliere?
download_help = Per un principiante, il LiveCD è la soluzione migliore.\n\
\n\
Rispetto a un LiveCD, il vantaggio di un`immagine universale è che è\
Rispetto a un LiveCD, il vantaggio di un`immagine universale è che è \
possibile salvare le modifiche apportate in KolibriOS.\n\
\n\
L`immagine ibrida include il supporto per la tecnologia UEFI, utilizzata\
L`immagine ibrida include il supporto per la tecnologia UEFI, utilizzata \
per avviare il sistema su nuovi computer e portatili.
download_description = In questa pagina puoi scaricare la distribuzione delle

View File

@@ -51,6 +51,7 @@ header = Downloads
version = Versie:
date = Builddatum:
date-format = {DD}.{MM}.{YYYY}
img-descr = Afbeelding op diskette
iso-descr = LiveCD-afbeelding
@@ -63,10 +64,10 @@ all_rev = Alle nachtelijke builds
download_choice = Welke moet ik kiezen?
download_help = Voor een beginner is de LiveCD het beste.\n\
\n\
Vergeleken met een LiveCD heeft een universeel image het voordeel dat je\
Vergeleken met een LiveCD heeft een universeel image het voordeel dat je \
wijzigingen die je in KolibriOS hebt aangebracht, kunt opslaan.\n\
\n\
Hybride image bevat ondersteuning voor UEFI-technologie, die wordt gebruikt\
Hybride image bevat ondersteuning voor UEFI-technologie, die wordt gebruikt \
om het systeem op te starten op nieuwe computers en laptops.
download_description = Op deze pagina kunt u de nightly builds-distributie

View File

@@ -51,6 +51,7 @@ header = Скачать
version = Версия:
date = Дата сборки:
date-format = {DD}.{MM}.{YYYY}
img-descr = Образ дискеты
iso-descr = Образ LiveCD
@@ -63,10 +64,10 @@ all_rev = Все ночные сборки
download_choice = Какой выбрать?
download_help = Для новичка лучше всего подойдет LiveCD.\n \
\n\
По сравнению с LiveCD преимущество универсального образа в том, что вы\
По сравнению с LiveCD преимущество универсального образа в том, что вы \
можете сохранить изменения, сделанные в КолибриОС.\n\
\n\
Гибридный образ включает поддержку технологии UEFI, которая используется\
Гибридный образ включает поддержку технологии UEFI, которая используется \
для загрузки системы на новых компьютерах и ноутбуках.
download_description = На этой странице вы можете скачать ночные сборки

85
locales/zh-Hans.ini Normal file
View File

@@ -0,0 +1,85 @@
[title]
language = 简体中文
index = KolibriOS
download = KolibriOS - 下载
[header]
index = KolibriOS 官方网站
download = KolibriOS 下载页
[menu]
kolibrios = KolibriOS
download = 下载
forum = 论坛
wiki = 百科
git = Git
[git]
header = KolibriOS 现已拥抱 Git
text = 来看看我们全新又对开发者友好的代码仓库吧:
[article]
p1 = {kolibrios} 是一个体积微小、功能强大、响应迅速的,面向 x86 兼容机的操作系统。
只需要寥寥数兆字节的磁盘空间、一个 i586 处理器和 12 兆字节内存,
你就能体验到一个丰富的应用生态:
文字处理、图像查看、图形编辑、网页浏览等基本应用一应俱全,甚至还有三十多个有意思的游戏。
在文件系统方面,{kolibrios} 完全支持 FAT12/16/32
同时也支持读取 NTFS、exFAT、ISO9660 和 Ext2/3/4 文件系统。
它还提供了一套丰富的{drivers},囊括众多主流声卡、网卡、显卡。
drivers = 驱动程序
p2 = 试想一款能在短短几秒内启动到图形化界面的操作系统!
不再囿于转着小圈圈的鼠标指针,所有的应用软件都在鼠标点击后极速开启!
得益于 {kolibrios} 的核心部分(内核、驱动)完全采用 {fasm} 汇编语言来编写,这样的高速已经不再是幻想!
快来试试我们的 {kolibrios},将其与现代臃肿的 Windows 和 Linux 系统比比看,你就会发现它们之间的速度差距。
p3 = {kolibrios} 是一个 MenuetOS 的派生分支,从 2004 开始脱离其独立开发。
如果你有需要{feedback}的问题,我们会非常欢迎~
当然,如果能为我们提供{help},我们也感激不尽!
feedback = 反馈
help = 帮助
p_subscription = 希望你能尽情享用我们的作品!
[downloads]
header = 下载链接
version = 当前版本:
date = 构建日期:
date-format = {YYYY}年{MM}月{DD}日
img-descr = 软盘镜像
iso-descr = Live 光盘镜像
distr-descr = 优盘或多系统启动通用包
raw-descr = UEFI/BIOS 混合包
prev_rev = 先前版本
all_rev = 所有即时构建包
download_choice = 该怎么选?
download_help = 对新手而言Live 光盘就是最优解。\n\
\n\
而与之不同的是,通用包允许用户把在系统运行过程中对 KolibriOS 的更改保存下来,例如系统设置之类就可以保存。\n\
\n\
混合启动镜像包含了对 UEFI 技术的支持,可以让你在现代的电脑上更好地启动之。
download_description = 在此页面中,你可以下载我们的即时构建版本,也就是包含了最新的更新。
需要知道的是:这些特性往往会致使系统不稳定,使用时请牢记此项。
这些文件都经过 {zip} 压缩打包。{kolibrios} 以 {gpl} 协议发布,其源码可见于{git}。
git-server = 此仓库站
download_warn = 有些时候,一些防病毒软件会错误地将 {kolibrios} 的镜像标记为威胁项目,这应当是误判。{kolibrios} 完全开源,如果担心存在问题,无论何时何地,你都可以自行构建一份来确保安全。
[screenshots]
header = 内容截屏
1 = KolibriOS 桌面
2 = 演示程序
3 = 不同的文件管理器
4 = 网络相关的程序
5 = 游戏
6 = 开发调试工具
[footer]
team = KolibriOS 开发团队

85
locales/zh-Hant.ini Normal file
View File

@@ -0,0 +1,85 @@
[title]
language = 繁體中文
index = KolibriOS
download = KolibriOS - 下載
[header]
index = KolibriOS 官方站
download = KolibriOS 下載頁
[menu]
kolibrios = KolibriOS
download = 下載
forum = 論壇
wiki = 百科
git = Git
[git]
header = KolibriOS 現已移入 Git
text = 來看看我們又新又友好的代碼倉庫吧:
[article]
p1 = {kolibrios} 是一個空間小、功能強、回應快的,面向 x86 兼容機的作業系統。
只需要寥寥數 MB 磁碟空間、一個 i586 處理器和 12 MB RAM
即可體驗到一個豐富的應用生態:
文字處理、圖像查看、圖形編輯、網頁流覽等基本應用一應俱全,甚至還有三十多個有意思的小遊戲。
在檔案系統方面,{kolibrios} 完全支援 FAT12/16/32
同時也能夠讀取 NTFS、exFAT、ISO9660 和 Ext2/3/4 檔案系統。
它還提供了一套豐富的{drivers},囊括眾多主流音效卡、網卡、顯卡。
drivers = 驅動程式
p2 = 試想一款能在短短幾秒內啟動到圖形化介面的作業系統!
不再囿於轉著小圈圈的滑鼠指標,所有的應用軟體都在點擊後極速開啟!
得益於 {kolibrios} 的核心部分(內核、驅動)完全採用 {fasm} 組合語言來編寫,這樣的高速已不再是幻想!
快來試試我們的 {kolibrios},將其與現代臃腫的 Windows 和 Linux 系統比比看,你就會發現它們之間的速度差距。
p3 = {kolibrios} 是 2004 年自 MenuetOS Fork 而來,也從那一刻起開始脫離它進行自主開發。
歡飲您{feedback}您遇到的任何問題。
如果能為我們提供{help},我們也會感激不盡!
feedback = 回饋
help = 幫助
p_subscription = 希望你能盡情享用我們的作品!
[downloads]
header = 下載連結
version = 當前版本:
date = 構建日期:
date-format = {YYYY}年{MM}月{DD}日
img-descr = 軟碟鏡像
iso-descr = LiveCD 鏡像
distr-descr = 閃存盤或多系統啟用的動通用包
raw-descr = UEFI/BIOS 混合包
prev_rev = 早期版本
all_rev = 所有 Nightly 構建包
download_choice = 如何選擇我要的包?
download_help = 對新手而言LiveCD 就是最優解。\n\
\n\
而與之不同的是,通用包允許使用者把在系統運行過程中對 KolibriOS 作出的更改保存下來,例如系統設置之類就可以保留。\n\
\n\
混合啟動鏡像包含了對 UEFI 技術的支援,可以讓你在現代的電腦上更好地啟動之。
download_description = 在此頁面裏,你可以下載我們的 Nightly 構建包,也即包含了當下最新的更新。
需要知道的是:因爲是即時更新並構建的,這些包往往包含一些導致系統不穩定的特性,請在使用時牢記此項。
這些檔案都是經過 {zip} 壓縮打包的,使用前需解壓。{kolibrios} 以 {gpl} 許可證發佈,其源碼可見於{git}。
git-server = 此倉庫站
download_warn = 有些時候,一些防毒軟體會錯誤地將 {kolibrios} 的鏡像標記為威脅項,這應當是一種誤判。我們的 {kolibrios} 完全開源,如果擔心存在安全問題,無論何時何地,你都可以自行構建一份來確保運行的内容是安全的。
[screenshots]
header = 內容截屏
1 = KolibriOS 桌面
2 = 演示程式
3 = 不同的檔案管理員
4 = 網路相關的程式
5 = 遊戲
6 = 開發調試工具
[footer]
team = KolibriOS 開發團隊

View File

@@ -6,7 +6,7 @@ import time
STATUS_URL = "https://builds.kolibrios.org/status.html"
STATUS_SEC = 300 # refetch each 5 minutes
autobuild_date = "DD.MM.YYYY"
autobuild_date = {"YYYY": "YYYY", "MM": "MM", "DD": "DD"}
autobuild_vers = "0.0.0.0+0000-0000000"
_started = False
@@ -56,12 +56,17 @@ def _refresh_build_date_once():
if not mts:
mds = re.search(r"\b(\d{2})\.(\d{2})\.(\d{4})\b", text)
if mds:
autobuild_date = f"{mds.group(1)}.{mds.group(2)}.{mds.group(3)}"
autobuild_date["YYYY"] = mds.group(1)
autobuild_date["MM"] = mds.group(2)
autobuild_date["DD"] = mds.group(3)
else:
return
else:
y, mo, d = mts.groups()
autobuild_date = f"{d}.{mo}.{y}"
(
autobuild_date["YYYY"],
autobuild_date["MM"],
autobuild_date["DD"],
) = mts.groups()
if last_commit_ver:
autobuild_vers = last_commit_ver

View File

@@ -1,31 +0,0 @@
from pathlib import Path
def load_slides(root_path):
shots_dir = Path(root_path) / "static" / "img" / "screenshots"
if not shots_dir.exists():
return []
slides = []
for path in shots_dir.iterdir():
if not path.is_file():
continue
if path.suffix.lower() not in {".png", ".jpg", ".jpeg", ".webp", ".gif"}:
continue
stem = path.stem
num = int(stem) if stem.isdigit() else None
slides.append(
{
"filename": f"img/screenshots/{path.name}",
"key": stem,
"num": num,
}
)
slides.sort(
key=lambda item: (
item["num"] is None,
item["num"] if item["num"] is not None else item["key"],
)
)
return slides

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

View File

@@ -1,42 +1,119 @@
function dropdown_show(el) {
let x = 0;
let y = 0;
while (el) {
x += el.offsetLeft;
y += el.offsetTop;
el = el.offsetParent;
/* LANGUAGE DROPDOWN */
function dropdown_show(obj)
{
var x = y = 0;
while(obj)
{
x += obj.offsetLeft;
y += obj.offsetTop;
obj = obj.offsetParent;
}
const ddown = document.getElementById("lang-dropdown");
ddown = document.getElementById("lang-dropdown");
ddown.style.display = "block";
ddown.style.left = (x - 72) + "px";
if (ddown.offsetLeft + ddown.offsetWidth + 10 > document.body.offsetWidth) {
ddown.style.left = (document.body.offsetWidth - ddown.offsetWidth - 82) + "px";
ddown.style.left = (x - 72) + "px";
if (ddown.offsetLeft + ddown.offsetWidth +10 > document.body.offsetWidth)
{
ddown.style.left = document.body.offsetWidth - ddown.offsetWidth - 82 + "px";
}
ddown.style.top = (y + 48) + "px";
fade_to(ddown, 1);
op = 0;
appear(1);
}
function dropdown_hide(e) {
for (let t = e && e.target; t; t = t.parentElement) {
if (t.id === "lang-dropdown" || t.id === "lang-butt") return;
function dropdown_hide()
{
ddown = document.getElementById("lang-dropdown");
ddown.style.display="none";
}
function appear(x)
{
if(op < x)
{
op += 0.2;
ddown.style.opacity = op;
ddown.style.filter = 'alpha(opacity=' + op * 100 + ')';
t = setTimeout('appear(' + x + ')', 20);
}
const ddown = document.getElementById("lang-dropdown");
fade_to(ddown, 0, function() {
ddown.style.display = "none";
}
/* SCREENSHOTS GALLERY */
var FIRST_IMG_ID = 1;
var LAST_IMG_ID = 6;
var current = LAST_IMG_ID; // start with last slide so that next() shows the first
window.onload = function() {
// Dynamically create dots based on number of slides
var dots = document.getElementById("dots");
for (var i = FIRST_IMG_ID; i <= LAST_IMG_ID; i++) {
var dot = document.createElement("span");
dot.className = "dot" + (i === current ? " active" : "");
dot.setAttribute("data-slide", i);
dot.onclick = function() {
goToSlide(parseInt(this.getAttribute("data-slide")));
};
dots.appendChild(dot);
}
// If a carousel element exists, advance to the first slide on load
if (document.getElementById("carousel")) next();
};
function updateDots() {
var dots = document.querySelectorAll("#dots .dot");
dots.forEach(function(dot, index) {
// index starts at 0 so add FIRST_IMG_ID to match your slide IDs
dot.classList.toggle("active", (index + FIRST_IMG_ID) === current);
});
}
function fade_to(el, target, done) {
const from = parseFloat(el.style.opacity) || 0;
const delta = target - from;
let start;
function step(ts) {
if (!start) start = ts;
const t = Math.min((ts - start) / 200, 1);
el.style.opacity = from + delta * t;
if (t < 1) requestAnimationFrame(step);
else if (done) done();
function goToSlide(n) {
if (n === current) return;
document.getElementById("slide" + current).className = "minislide";
current = n;
document.getElementById("slide" + current).className = "visible";
if (document.getElementById("carousel")) {
document.getElementById("carousel").innerHTML = document.getElementById("slide" + current).alt;
}
requestAnimationFrame(step);
updateDots();
}
function next() {
document.getElementById("slide" + current).className = "minislide";
if (current >= LAST_IMG_ID) {
current = FIRST_IMG_ID;
} else {
current++;
}
document.getElementById("slide" + current).className = "visible";
if (document.getElementById("carousel")) {
document.getElementById("carousel").innerHTML = document.getElementById("slide" + current).alt;
}
updateDots();
}
function previous() {
document.getElementById("slide" + current).className = "minislide";
if (current <= FIRST_IMG_ID) {
current = LAST_IMG_ID;
} else {
current--;
}
document.getElementById("slide" + current).className = "visible";
if (document.getElementById("carousel")) {
document.getElementById("carousel").innerHTML = document.getElementById("slide" + current).alt;
}
updateDots();
}
function checkkey(e) {
var keycode = window.event ? e.keyCode : e.which;
if (keycode == 37) { previous(); }
else if (keycode == 39) { next(); }
else if (keycode == 27) { dropdown_hide(); }
}

View File

@@ -375,73 +375,26 @@ acronym {
/* SCREENS.CSS */
.gallery {
display: flex;
flex-wrap: wrap;
justify-content: center;
#show {
max-width: 1280px;
max-height: 800px;
width: 100%;
height: 100%;
cursor: pointer;
border: 1px solid $c-screen-border;
display: block;
position: relative;
border-radius: 4px;
overflow: hidden;
&-input {
img {
display: none;
pointer-events: none;
}
max-width: 100%;
&-slide {
display: none;
margin: 0;
order: 1;
flex: 0 0 100%;
}
&-input:checked + &-slide {
display: block;
}
&-show {
max-width: 1280px;
width: 100%;
height: auto;
cursor: pointer;
border: 1px solid $c-screen-border;
display: block;
position: relative;
border-radius: 4px;
overflow: hidden;
img {
&.visible {
display: block;
max-width: 100%;
}
}
&-next {
position: absolute;
inset: 0;
cursor: pointer;
}
&-caption {
text-align: center;
margin: 1.25em auto 1em;
}
&-dot {
display: inline-block;
order: 2;
.dot {
display: inline-block;
width: 0.625em;
height: 0.625em;
background: $c-dot;
border-radius: 50%;
margin: 0 0.25em;
cursor: pointer;
}
}
&-input:checked + &-slide + &-dot .dot {
background: $c-text;
}
}
iframe {
@@ -451,6 +404,30 @@ iframe {
aspect-ratio: 16 / 9;
}
#carousel {
text-align: center;
margin: 1.25em auto 1em;
}
#dots {
text-align: center;
line-height: 1;
}
.dot {
display: inline-block;
width: 0.625em;
height: 0.625em;
background: $c-dot;
border-radius: 50%;
margin: 0 0.25em;
cursor: pointer;
&.active {
background: $c-text;
}
}
/* FOOTER */
#footer {

View File

@@ -1,5 +1,5 @@
<!doctype html>
<html lang="{{ lang }}" onmouseup="dropdown_hide(event)">
<html lang="{{ lang }}" onmouseup="dropdown_hide()">
{% include 'tmpl/_header.htm' %}
@@ -115,43 +115,20 @@
<h1>{{ _('screenshots:header') }}</h1>
{% if slides %}
<div id="screen" class="gallery">
{% for slide in slides %}
<input
type="radio"
name="slide"
id="slide-{{ loop.index0 }}"
class="gallery-input"
{% if loop.first %}checked{% endif %}
<div id="screen" onclick="next()">
<div id="show">
{% for i in range(1, 7) %}
<img
id="slide{{ i }}"
src="{{ url_for('static', filename='img/screenshots/%d.png' % i ) }}"
{% if i == 1 %}class="visible"{% endif %}
alt="{{ _('screenshots:%d' % i) }}"
>
<figure class="gallery-slide">
<div class="gallery-show">
<img
src="{{ url_for('static', filename=slide.filename) }}"
alt="{{ _('screenshots:%s' % slide.key) }}"
>
{% set next_index = 0 if loop.last else loop.index0 + 1 %}
<label
class="gallery-next"
for="slide-{{ next_index }}"
aria-label="Next slide"
></label>
</div>
<figcaption class="gallery-caption">
{{ _('screenshots:%s' % slide.key) }}
</figcaption>
</figure>
<div class="gallery-dot">
<label
class="dot"
for="slide-{{ loop.index0 }}"
aria-label="{{ _('screenshots:%s' % slide.key) }}"
></label>
</div>
{% endfor %}
</div>
</div>
{% endif %}
<div id="carousel"></div>
<div id="dots"></div>
</div>
{% include 'tmpl/_footer.htm' %}

View File

@@ -1,5 +1,5 @@
<!doctype html>
<html lang="{{ lang }}" onmouseup="dropdown_hide(event)">
<html lang="{{ lang }}" onmouseup="dropdown_hide()">
{% include 'tmpl/_header.htm' %}
@@ -20,4 +20,4 @@
{% include 'tmpl/_footer.htm' %}
</body>
</html>
</html>