all repos — py-vite @ 1efa6e0263169bfcf34cbbbd7fed158b66244255

the original vite, written in python

vite/vite.py (view raw)

  1"""
  2Vite - A simple and minimal static site generator that JustWorks™
  3Author: Anirudh <icyph0x@pm.me>
  4License: MIT
  5"""
  6
  7import sys
  8import pathlib
  9import os
 10import jinja2
 11import time
 12import http.server
 13import socketserver
 14import shutil
 15import datetime
 16
 17from markdown2 import markdown_path
 18from huepy import *
 19from livereload import Server
 20from subprocess import call
 21
 22
 23# constants
 24PAGES_PATH = 'pages/'
 25BUILD_PATH = 'build/'
 26TEMPL_PATH = 'templates/'
 27TEMPL_FILE = ''
 28PORT = 1911
 29
 30
 31def import_config():
 32    try:
 33        sys.path.append(os.getcwd())
 34        globals()['config'] = __import__('config') 
 35        global TEMPL_FILE
 36        TEMPL_FILE = os.path.join(TEMPL_PATH, config.template)
 37    except ImportError:
 38        print(bad('Error: config.py not found.'))
 39        print(que('Are you sure you\'re in a project directory?'))
 40        sys.exit(1)
 41
 42
 43def create_project(path):
 44    try:
 45        abs_path = pathlib.Path(path).resolve()
 46        cur_path = pathlib.Path('.').resolve()
 47        os.makedirs(os.path.join(path, 'build'))
 48        os.mkdir(os.path.join(path, 'pages'))
 49        os.mkdir(os.path.join(path, 'templates'))
 50        os.mkdir(os.path.join(path, 'static'))
 51        create_config(path)
 52        create_template(path)
 53        print(good('Created project directory at %s.' % (abs_path)))
 54    except FileExistsError:
 55        print(bad('Error: specified path exists.'))
 56
 57
 58def create_path(path):
 59    head, tail = os.path.split(path)
 60    now = datetime.datetime.now()
 61    today = now.strftime('%Y-%m-%d')
 62
 63    try:
 64        os.makedirs(os.path.join(PAGES_PATH, head))
 65    except FileExistsError:
 66        pass
 67    if os.path.exists(os.path.join(PAGES_PATH, head, tail)):
 68        print(bad('Error: specified path exists.'))
 69    else:
 70        with open(os.path.join(PAGES_PATH, head, tail), 'w') as f:
 71            to_write = (
 72"""---
 73template:
 74title:
 75subtitle:
 76date: {t}
 77---\n"""
 78             ).format(t=today)
 79            f.write(to_write)
 80        print(good('Created %s.') % (os.path.join(PAGES_PATH, head, tail)))
 81
 82
 83def create_config(path):
 84    with open(os.path.join(path, 'config.py'), 'w') as f:
 85        f.write("""# config.py - Vite's configuration script
 86
 87title = ''
 88author = ''
 89header = ''
 90footer = '' 
 91post_build = []
 92template = 'index.html'  # default is index.html\n""")
 93
 94
 95def create_template(path):
 96    with open(os.path.join(path, 'templates', 'index.html'), 'w') as f:
 97        f.write("""<!DOCTYPE html>
 98<html>
 99<header>
100	{{ header }}
101	<title>
102		{{ title }}	
103	</title>
104</header>
105
106<body>
107	{{ body }}
108</body>
109
110<footer>
111	{{ footer }}
112	<p> {{ author }} </p>
113<footer>
114
115                """)
116
117# jinja2
118def jinja_render(html, tmpl):
119    template_loader = jinja2.FileSystemLoader('./')
120    env = jinja2.Environment(loader=template_loader)
121    try:
122        template = env.get_template(tmpl)
123        meta = html.metadata
124        output = template.render(title=meta['title'] if 'title' in meta else config.title,
125                             author=meta['author'] if 'author' in meta else config.author,
126                             header=meta['header'] if 'header' in meta else config.header,
127                             footer=meta['footer'] if 'footer' in meta else config.footer,
128                             date=meta['date'] if 'date' in meta else '',
129                             subtitle=meta['subtitle'] if 'subtitle' in meta else '',
130                             body=html)
131        return output
132    except jinja2.exceptions.TemplateNotFound:
133        print(bad('Error: specified template not found: %s' % (tmpl)))
134        sys.exit(1)
135
136
137def fm_template(metadata):
138    try:
139        page_template = os.path.join(os.path.join(TEMPL_PATH, metadata['template']))
140    except KeyError:
141        page_template = TEMPL_FILE
142    return page_template
143
144
145def markdown_render(filename):
146    html = markdown_path(os.path.join(PAGES_PATH, filename), extras=['metadata', 'fenced-code-blocks', 'header-ids', 'footnotes', 'smarty-pants'])
147    return html
148
149
150def html_gen():
151    def index_render(f, d=''):
152        index_html = markdown_render(os.path.join(d, f))
153        output = jinja_render(index_html, fm_template(index_html.metadata))
154        with open(os.path.join(BUILD_PATH, d, 'index.html'), 'w') as ff:
155            ff.write(output)
156            if d:
157                print(run('Rendered ' + white('%s/%s') % (d, f)))
158            else:
159                print(run('Rendered ' + white('%s') % (f)))
160
161    def normal_render(f, d=''):
162        html_text = markdown_render(os.path.join(d, f))
163        html_file = os.path.splitext(os.path.join(BUILD_PATH, d, f))[0]
164        os.mkdir(html_file)
165        output = jinja_render(html_text, fm_template(html_text.metadata))
166        with open(os.path.join(html_file, 'index.html'), 'w') as ff:
167            ff.write(output)
168            if d:
169                print(run('Rendered ' + white('%s/%s') % (d, f)))
170            else:
171                print(run('Rendered ' +  white('%s') % (f)))
172
173
174    for root, dirs, files in os.walk(PAGES_PATH):
175        for d in dirs:
176            os.mkdir(os.path.join(BUILD_PATH, d))
177            for f in os.listdir(os.path.join(PAGES_PATH, d)):
178                if os.path.splitext(f)[1] != '.md':
179                    shutil.copyfile(os.path.join(PAGES_PATH, d, f),
180                                    os.path.join(BUILD_PATH, d, f))
181                    print(run('Copied ' + white('%s/%s') % (d, f)))
182                elif f == '_index.md':
183                    index_render(f, d)
184                else:
185                    normal_render(f, d)
186
187    for f in os.listdir(PAGES_PATH):
188        if os.path.isfile(os.path.join(PAGES_PATH, f)):
189            if os.path.splitext(f)[1] != '.md':
190                shutil.copyfile(os.path.join(PAGES_PATH, f), os.path.join(BUILD_PATH, f))
191                print(run('Copied ' + white('%s') % (f)))
192            elif f == '_index.md':
193                index_render(f)
194            else:
195                normal_render(f)
196
197
198def server():
199#    handler = http.server.SimpleHTTPRequestHandler
200#    os.chdir(os.path.join(os.getcwd(), BUILD_PATH))
201    server = Server()
202    try:
203        print(run(f'Serving the {italic(yellow("build"))} directory at {white(f"http://localhost:{PORT}")}'))
204        print(white('Ctrl+C') + ' to stop.')
205        server.serve(port=PORT, root='build/')
206    except KeyboardInterrupt:
207        print(info('Stopping server.'))
208        sys.exit(1)
209
210
211def clean():
212    for f in os.listdir(BUILD_PATH):
213        fpath = os.path.join(BUILD_PATH, f)
214        try:
215            if os.path.isfile(fpath):
216                os.unlink(fpath)
217            elif os.path.isdir(fpath):
218                shutil.rmtree(fpath)
219        except Exception as e:
220            print(e)
221
222
223def builder():
224    path = os.getcwd()
225    start = time.process_time()
226    if not os.listdir(os.path.join(path, PAGES_PATH)):
227        print(info(italic('pages') + ' directory is empty. Nothing to build.'))
228        sys.exit(1)
229    else:
230        clean()
231        html_gen()
232        if os.path.exists(os.path.join(os.getcwd(), 'static')):
233            shutil.copytree(os.path.join(os.getcwd(), 'static'), os.path.join(BUILD_PATH, 'static'))
234        print(good('Done in %0.5fs.' % (time.process_time() - start)))
235        try:
236            if config.post_build != '':
237                print(run('Running post-build actions...'))
238                for s in config.post_build:
239                    print(info(f'{s}'))
240                    call([s])
241        except AttributeError:
242            pass
243