diff options
| -rw-r--r-- | .gitignore | 11 | ||||
| -rw-r--r-- | README.md | 31 | ||||
| -rw-r--r-- | src/args.py | 9 | ||||
| -rwxr-xr-x | src/bcst.py | 11 | ||||
| -rw-r--r-- | src/resource.py | 23 | ||||
| -rw-r--r-- | src/theme.py | 29 | ||||
| -rw-r--r-- | themes/default/assets/script.js | 103 | ||||
| -rw-r--r-- | themes/default/assets/style.css | 110 | ||||
| -rw-r--r-- | themes/default/index.html | 37 | ||||
| -rw-r--r-- | themes/default/resources.json | 20 |
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" + } + } +} |
