aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore11
-rw-r--r--README.md31
-rw-r--r--src/args.py9
-rwxr-xr-xsrc/bcst.py11
-rw-r--r--src/resource.py23
-rw-r--r--src/theme.py29
-rw-r--r--themes/default/assets/script.js103
-rw-r--r--themes/default/assets/style.css110
-rw-r--r--themes/default/index.html37
-rw-r--r--themes/default/resources.json20
10 files changed, 384 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..78ebe7e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+
+##### Python
+__pycache__
+env
+
+##### Emacs
+\#*
+.\#*
+
+##### Other
+tests
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d6cf9cd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,31 @@
+Beautiful Custom Start Page
+===
+BCST allow you to create a beautiful start page very quickly. To install the dependencies, simply run:
+
+ > pip install jinja2
+
+Simple right a simple json resource file:
+
+ {
+ "title": "Default Theme",
+ "bookmarks": {
+ "engines": {
+ "Qwant": "https://www.qwant.com/",
+ "DDG": "https://duckduckgo.com/",
+ "Google": "http://google.fr"
+ },
+ "Reddit": {
+ "Home": "https://www.reddit.com/",
+ "Unixporn": "https://www.reddit.com/r/Unixporn",
+ "Linux": "https://www.reddit.com/me/m/linux"
+ },
+ "Social": {
+ "Discord": "https://discordapp.com/channels/@me",
+ "Twitter": "https://twitter.com/",
+ "LinuxRocks": "https://linuxrocks.online/web/getting-started"
+ }
+ }
+ }
+Then simply run:
+
+> ./src/bcst.py \<resource-file-path> \<start-page-destination>
diff --git a/src/args.py b/src/args.py
new file mode 100644
index 0000000..6ae54bf
--- /dev/null
+++ b/src/args.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+
+import argparse
+
+args_parser = argparse.ArgumentParser()
+args_parser.add_argument("resource", help="A JSON resource file.")
+args_parser.add_argument("destination", help="Start page folder name.")
+args = args_parser.parse_args()
+
diff --git a/src/bcst.py b/src/bcst.py
new file mode 100755
index 0000000..850fbdb
--- /dev/null
+++ b/src/bcst.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+
+from args import args
+from resource import Resource
+from theme import Theme
+
+
+res=Resource(args.resource)
+t=Theme("themes/default",res.json)
+
+t.deploy(args.destination)
diff --git a/src/resource.py b/src/resource.py
new file mode 100644
index 0000000..f521022
--- /dev/null
+++ b/src/resource.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+from os import path
+import json, jsonschema
+
+
+class Resource:
+ def __init__(self, resource):
+ self.resource=resource
+ # Read data
+ try:
+ with open(resource,'r') as f:
+ self.data=f.read()
+ except IOError:
+ print("Unable to found "+resource)
+ exit(1)
+ # Decode data
+ try:
+ self.json=json.loads(self.data)
+ except:
+ print("Unable to read json from "+resource)
+ exit(1)
+
diff --git a/src/theme.py b/src/theme.py
new file mode 100644
index 0000000..9859451
--- /dev/null
+++ b/src/theme.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+
+from resource import Resource
+from shutil import copytree, ignore_patterns
+from jinja2 import Template
+import os
+
+class Theme:
+
+ def __init__(self, path, resource_data):
+ res=Resource(path+"/resources.json")
+ self.theme_path=path.strip('/')
+ self.data=res.json
+ self.data.update(resource_data)
+ # Read theme
+ try:
+ with open(path+"/index.html",'r') as f:
+ self.template=Template(f.read())
+ except IOError:
+ print("Unable to found "+resource)
+ exit(1)
+
+
+ def deploy(self, path):
+ copytree(self.theme_path, path, dirs_exist_ok=True,ignore=ignore_patterns("*.json","index.html"))
+ themes_dir=os.path.split(self.theme_path)[0]
+ theme_dir=os.path.split(self.theme_path)[1]
+ with open(path+"/index.html", "w") as index:
+ index.write(self.template.render(self.data))
diff --git a/themes/default/assets/script.js b/themes/default/assets/script.js
new file mode 100644
index 0000000..4681d9e
--- /dev/null
+++ b/themes/default/assets/script.js
@@ -0,0 +1,103 @@
+// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later
+
+var DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
+
+function startTime() {
+ var today = new Date();
+ var h = today.getHours();
+ var ampm = h >= 12 ? 'PM' : 'AM';
+ var m = today.getMinutes();
+ var s = today.getSeconds();
+ m = checkTime(m);
+ s = checkTime(s);
+ var h = h % 12;
+ var h = h ? h : 12; // the hour '0' should be '12'
+
+ //---------------------
+
+ var dow = DAYS[today.getDay()]
+ var dd = ('0' + today.getDate()).slice(-2)
+ var mm = ('0' + (today.getMonth() + 1 )).slice(-2)
+ var yy = today.getFullYear()
+
+ document.getElementById('date').innerHTML = dow + ' ' + yy + '-' + mm + '-' + dd
+
+ //---------------------
+
+ document.getElementById('time').innerHTML =
+ h + ":" + m + ":" + s + ' ' + ampm;
+ var t = setTimeout(startTime, 500);
+}
+
+function checkTime(i) {
+ if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
+ return i;
+}
+
+var dateElem = document.getElementById('date')
+
+var vpwidth = document.documentElement.clientWidth
+var sections = document.querySelectorAll('.box')
+function fixSectionHeight() {
+ var step = 1
+ if (vpwidth >= 480) step = 2;
+ if (vpwidth >= 768) step = 4;
+
+ sections.forEach(function (s) {
+ s.style.height = 'auto'
+ })
+
+ for (var i = 0; i < sections.length; i += step) {
+ var ss = Array.prototype.slice.call(sections, i, i + step)
+ var hss = ss.map(function (e) { return e.clientHeight })
+ var h = Math.max.apply(null, hss)
+ ss.forEach(function (s) {
+ s.style.height = h + 'px'
+ })
+ }
+}
+
+function addLinks(DATA) {
+ const main = document.querySelector("main");
+
+ function createSection(linkGroup) {
+ const section = document.createElement("section");
+
+ const box = document.createElement("div");
+ box.classList.add("box");
+
+ const title = document.createElement("span");
+ title.classList.add("title");
+ title.innerHTML = linkGroup.category;
+
+ const content = document.createElement('div');
+ content.classList.add('content');
+
+ for (let link of linkGroup.links) {
+ const anchor = document.createElement('a');
+ anchor.setAttribute('href', link.url);
+
+ const anchorSpan = document.createElement('span');
+ anchorSpan.classList.add('links');
+ anchorSpan.innerHTML = link.name;
+
+ anchor.appendChild(anchorSpan);
+
+ content.appendChild(anchor);
+ }
+
+ box.appendChild(title);
+ box.appendChild(content)
+
+ section.appendChild(box);
+
+ return section;
+ }
+
+ for (let linkGroup of DATA.linkGroups) {
+ const section = createSection(linkGroup);
+
+ main.appendChild(section);
+ }
+}
+
diff --git a/themes/default/assets/style.css b/themes/default/assets/style.css
new file mode 100644
index 0000000..b2676b4
--- /dev/null
+++ b/themes/default/assets/style.css
@@ -0,0 +1,110 @@
+
+:root {
+--bgdark: #232836;
+--bglight: #282e3f;
+--bglighter: #2f364a;
+
+--fgdark: #8686a4;
+--fglight: #ccccfa;
+
+--accent: #d39ceb;
+--border: #2f364a;
+--disabled: #696969;
+--hover: #ffffff;
+}
+
+* {
+ font-family: "t kiwi Wide";
+ font-size: 20px;
+}
+
+html {
+ background: var(--bgdark);
+ background-position: top -24px left 0;
+ margin-top: -26px;
+}
+
+html, body {
+ width: 100vw;
+ height: 100vh;
+ padding: 0;
+ margin: 0;
+}
+
+main {
+ display: flex;
+ justify-content: center;;
+ overflow-y: auto;
+ flex-flow: row wrap;
+ position: relative;
+ top: 50%;
+ transform: translateY(-50%);
+}
+
+#clock {
+ position: relative;
+ top: -30px;
+ display: flex;
+ text-align: center;
+}
+
+#time, #date {
+ color: var(--fglight);
+ display: inline-block;
+ margin: 0 5px;
+ flex-grow: 1;
+ width: 0;
+}
+
+#time {
+ text-align: left;
+}
+
+#date {
+ text-align: right;
+}
+
+.links {
+ padding: 5px 15px;
+ width: auto;
+ display: block;
+ text-align: center;
+}
+
+a:visited, a {
+ color: var(--fgdark);
+ text-decoration: none;
+ outline: none;
+}
+
+a:not(.tablinks):visited, a:not(.tablinks) { transition: all 00ms ease 0s; }
+a:hover { color: var(--fglight); }
+
+.slash {
+ color: var(--fgdark);
+}
+
+main section {
+ box-sizing: border-box;
+ min-width: 300px;
+}
+
+.title {
+ display: none;
+}
+
+section {
+ margin: 12px;
+ padding: 12px;
+ /*border: 8px solid var(--fgdark);*/
+ box-shadow: 10px 10px 0px 0px rgba(0,0,0,0.13);
+}
+
+section {
+ background-color: var(--bglight);
+ border-radius: 4px;
+}
+
+section:hover {
+ background-color: var(--bglighter);
+}
diff --git a/themes/default/index.html b/themes/default/index.html
new file mode 100644
index 0000000..82133cb
--- /dev/null
+++ b/themes/default/index.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html><head>
+ <meta name="viewport" content="width=device-width,initial-width=1">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link rel="stylesheet" href="assets/style.css">
+ <!-- Removed custom title -->
+<!-- Meta injected by Custom Start Page for SEO purposes -->
+<title>{{ title }}</title>
+<meta name="description" content="Jazz is a free, open source and customisable start page for your browser, hosted by Custom Start Page.">
+</head><span id="warning-container"><i data-reactroot=""></i></span><link type="text/css" id="dark-mode" rel="stylesheet" href=""><style type="text/css" id="dark-mode-custom-style"></style>
+
+
+<body>
+ <!--div id="clock"-->
+ <!--span id="date"--><!--/span-->
+ <!--span class="slash"--><!--/span-->
+ <!--span id="time"--><!--/span-->
+ <!--/div-->
+ <main>
+ {% for key,value in bookmarks.items() %}
+ <section>
+ <div class="box"><span class="title">{{ key }}</span>
+ <div class="content">
+ {% for link_name,link in value.items() %}
+ <a href="{{link}}"><span class="links">{{link_name}}</span></a>
+ {% endfor %}
+ </div>
+ </div>
+ </section>
+ {% endfor %}
+
+
+ </main>
+ <script src="assets/script.js"></script>
+
+</body>
+</html>
diff --git a/themes/default/resources.json b/themes/default/resources.json
new file mode 100644
index 0000000..dd2e1ca
--- /dev/null
+++ b/themes/default/resources.json
@@ -0,0 +1,20 @@
+{
+ "title": "Default Theme",
+ "bookmarks": {
+ "engines": {
+ "Qwant": "https://www.qwant.com/",
+ "DDG": "https://duckduckgo.com/",
+ "Google": "http://google.fr"
+ },
+ "Reddit": {
+ "Home": "https://www.reddit.com/",
+ "Unixporn": "https://www.reddit.com/r/Unixporn",
+ "Linux": "https://www.reddit.com/me/m/linux"
+ },
+ "Social": {
+ "Discord": "https://discordapp.com/channels/@me",
+ "Twitter": "https://twitter.com/",
+ "LinuxRocks": "https://linuxrocks.online/web/getting-started"
+ }
+ }
+}