forked from rra/distribusi
Compare commits
54 Commits
Author | SHA1 | Date |
---|---|---|
|
4964790762 | 12 months ago |
|
9ef68194db | 12 months ago |
|
1418feeaa8 | 12 months ago |
|
06cf1f5bdd | 12 months ago |
|
63becedaf5 | 2 years ago |
|
6b627f0f96 | 2 years ago |
|
7a2f8a5142 | 2 years ago |
|
6dd9fb7b40 | 2 years ago |
|
46e68fc966 | 2 years ago |
|
545577978a | 2 years ago |
|
60275a475e | 3 years ago |
|
e730cfec55 | 3 years ago |
|
f766f67cee | 3 years ago |
|
49a521ea14 | 3 years ago |
|
69fa5bb7c5 | 3 years ago |
|
5253d37411 | 3 years ago |
|
c0c069cead | 3 years ago |
|
64f449eee8 | 3 years ago |
|
601d5e86e7 | 3 years ago |
|
fd370294be | 3 years ago |
|
cb9e19d1a2 | 3 years ago |
|
2a0834734f | 3 years ago |
|
63902c079a | 3 years ago |
|
6a9fbe9856 | 3 years ago |
|
321405c66f | 3 years ago |
|
010020e08b | 3 years ago |
|
e21a78324f | 3 years ago |
|
d5335f3212 | 3 years ago |
|
3247286a7e | 3 years ago |
|
8529d952cd | 3 years ago |
|
6400b2aea2 | 3 years ago |
|
89067b48f7 | 3 years ago |
|
bc6fa0bad8 | 3 years ago |
|
fc19d536df | 3 years ago |
|
28f8793613 | 3 years ago |
|
52830ff7c4 | 3 years ago |
|
55e8fe190e | 3 years ago |
|
80e8a5e4fd | 3 years ago |
|
b613eef36c | 3 years ago |
|
dbe0e59b90 | 3 years ago |
|
1611144f72 | 3 years ago |
|
9b8be7c761 | 4 years ago |
|
cb37e6428b | 4 years ago |
|
dc92a81035 | 4 years ago |
|
e1ef66e646 | 4 years ago |
|
df71f44550 | 4 years ago |
|
d5606e5325 | 4 years ago |
|
8829a84b65 | 4 years ago |
|
6212f25536 | 4 years ago |
|
b31e211498 | 4 years ago |
|
02b0e00892 | 4 years ago |
|
415f8a5ac8 | 4 years ago |
|
afaa58d710 | 4 years ago |
|
7687aa96a2 | 4 years ago |
13 changed files with 414 additions and 355 deletions
@ -0,0 +1,51 @@ |
|||
# Changelog |
|||
|
|||
The changelog was only added at version 0.0.4. |
|||
|
|||
## 0.0.10 |
|||
|
|||
- Fix `-nf` functionality ([#5](https://git.vvvvvvaria.org/varia/distribusi/pulls/5)) (thanks @losttra8n!) |
|||
|
|||
## 0.0.9 |
|||
|
|||
- Fix thumbnail generation (thanks @dickreckard!) |
|||
- Adjust formatting for usage output |
|||
|
|||
## 0.0.8 |
|||
|
|||
- Allow to ignore hidden directories with `--no-hidden` |
|||
- Files and directories are now sorted during distribusification. |
|||
- Allow to append `index.html` to the menu items with `--menu-with-index` |
|||
|
|||
## 0.0.7 |
|||
|
|||
Let's think a bit about safety and robustness: |
|||
|
|||
- distribusi only overwrites (or removes) indexes that have been created by distribusi itself |
|||
- override the above behaviour with `--force` |
|||
- `--exclude` now allows you to exclude folder names from being listed, this behaviour is not influenced by `--force` |
|||
|
|||
And also some refactoring and niceties: |
|||
|
|||
- Distribusi only prints when called with `--verbose` |
|||
- Restyled `--verbose` output |
|||
- Generated indexes can be removed with `--remove-indexes` |
|||
- .html and .txt files are now expanded and included as snippets in the index file |
|||
- code rewrite for clarity |
|||
- HTML output is more precisely styleable |
|||
|
|||
## 0.0.6 |
|||
|
|||
Woops, we missed that one. |
|||
|
|||
## 0.0.5 |
|||
|
|||
- Use loose bounds for dependencies |
|||
- Don't call exiftools on every execution |
|||
- If `PILLOW` can't thumbnail an image it is included as a link instead |
|||
|
|||
## 0.0.4 |
|||
|
|||
- Add captions from EXIF metadata |
|||
- Custom stylesheet usage |
|||
- Ability to hide filenames |
@ -1,6 +1,4 @@ |
|||
PIPENV := pipenv run |
|||
|
|||
publish: |
|||
@rm -rf dist |
|||
@$(PIPENV) python setup.py bdist_wheel --universal |
|||
@$(PIPENV) twine upload dist/* |
|||
@python setup.py bdist_wheel --universal |
|||
@twine upload dist/* |
|||
|
@ -1,11 +0,0 @@ |
|||
[[source]] |
|||
name = "pypi" |
|||
url = "https://pypi.org/simple" |
|||
verify_ssl = true |
|||
|
|||
[dev-packages] |
|||
pillow = "*" |
|||
python-magic = "*" |
|||
twine = "*" |
|||
|
|||
[packages] |
@ -1,169 +0,0 @@ |
|||
{ |
|||
"_meta": { |
|||
"hash": { |
|||
"sha256": "84f37d28add02d81cc62fe51ee634dcc491c25ebdd9e0076e67f43039cd58c56" |
|||
}, |
|||
"pipfile-spec": 6, |
|||
"requires": {}, |
|||
"sources": [ |
|||
{ |
|||
"name": "pypi", |
|||
"url": "https://pypi.org/simple", |
|||
"verify_ssl": true |
|||
} |
|||
] |
|||
}, |
|||
"default": {}, |
|||
"develop": { |
|||
"bleach": { |
|||
"hashes": [ |
|||
"sha256:48d39675b80a75f6d1c3bdbffec791cf0bbbab665cf01e20da701c77de278718", |
|||
"sha256:73d26f018af5d5adcdabf5c1c974add4361a9c76af215fe32fdec8a6fc5fb9b9" |
|||
], |
|||
"version": "==3.0.2" |
|||
}, |
|||
"certifi": { |
|||
"hashes": [ |
|||
"sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c", |
|||
"sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a" |
|||
], |
|||
"version": "==2018.10.15" |
|||
}, |
|||
"chardet": { |
|||
"hashes": [ |
|||
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", |
|||
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" |
|||
], |
|||
"version": "==3.0.4" |
|||
}, |
|||
"docutils": { |
|||
"hashes": [ |
|||
"sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6", |
|||
"sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274", |
|||
"sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6" |
|||
], |
|||
"version": "==0.14" |
|||
}, |
|||
"idna": { |
|||
"hashes": [ |
|||
"sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", |
|||
"sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" |
|||
], |
|||
"version": "==2.7" |
|||
}, |
|||
"pillow": { |
|||
"hashes": [ |
|||
"sha256:00203f406818c3f45d47bb8fe7e67d3feddb8dcbbd45a289a1de7dd789226360", |
|||
"sha256:0616f800f348664e694dddb0b0c88d26761dd5e9f34e1ed7b7a7d2da14b40cb7", |
|||
"sha256:1f7908aab90c92ad85af9d2fec5fc79456a89b3adcc26314d2cde0e238bd789e", |
|||
"sha256:2ea3517cd5779843de8a759c2349a3cd8d3893e03ab47053b66d5ec6f8bc4f93", |
|||
"sha256:48a9f0538c91fc136b3a576bee0e7cd174773dc9920b310c21dcb5519722e82c", |
|||
"sha256:5280ebc42641a1283b7b1f2c20e5b936692198b9dd9995527c18b794850be1a8", |
|||
"sha256:5e34e4b5764af65551647f5cc67cf5198c1d05621781d5173b342e5e55bf023b", |
|||
"sha256:63b120421ab85cad909792583f83b6ca3584610c2fe70751e23f606a3c2e87f0", |
|||
"sha256:696b5e0109fe368d0057f484e2e91717b49a03f1e310f857f133a4acec9f91dd", |
|||
"sha256:870ed021a42b1b02b5fe4a739ea735f671a84128c0a666c705db2cb9abd528eb", |
|||
"sha256:916da1c19e4012d06a372127d7140dae894806fad67ef44330e5600d77833581", |
|||
"sha256:9303a289fa0811e1c6abd9ddebfc770556d7c3311cb2b32eff72164ddc49bc64", |
|||
"sha256:9577888ecc0ad7d06c3746afaba339c94d62b59da16f7a5d1cff9e491f23dace", |
|||
"sha256:987e1c94a33c93d9b209315bfda9faa54b8edfce6438a1e93ae866ba20de5956", |
|||
"sha256:99a3bbdbb844f4fb5d6dd59fac836a40749781c1fa63c563bc216c27aef63f60", |
|||
"sha256:99db8dc3097ceafbcff9cb2bff384b974795edeb11d167d391a02c7bfeeb6e16", |
|||
"sha256:a5a96cf49eb580756a44ecf12949e52f211e20bffbf5a95760ac14b1e499cd37", |
|||
"sha256:aa6ca3eb56704cdc0d876fc6047ffd5ee960caad52452fbee0f99908a141a0ae", |
|||
"sha256:aade5e66795c94e4a2b2624affeea8979648d1b0ae3fcee17e74e2c647fc4a8a", |
|||
"sha256:b78905860336c1d292409e3df6ad39cc1f1c7f0964e66844bbc2ebfca434d073", |
|||
"sha256:b92f521cdc4e4a3041cc343625b699f20b0b5f976793fb45681aac1efda565f8", |
|||
"sha256:bfde84bbd6ae5f782206d454b67b7ee8f7f818c29b99fd02bf022fd33bab14cb", |
|||
"sha256:c2b62d3df80e694c0e4a0ed47754c9480521e25642251b3ab1dff050a4e60409", |
|||
"sha256:c5e2be6c263b64f6f7656e23e18a4a9980cffc671442795682e8c4e4f815dd9f", |
|||
"sha256:c99aa3c63104e0818ec566f8ff3942fb7c7a8f35f9912cb63fd8e12318b214b2", |
|||
"sha256:dae06620d3978da346375ebf88b9e2dd7d151335ba668c995aea9ed07af7add4", |
|||
"sha256:db5499d0710823fa4fb88206050d46544e8f0e0136a9a5f5570b026584c8fd74", |
|||
"sha256:f36baafd82119c4a114b9518202f2a983819101dcc14b26e43fc12cbefdce00e", |
|||
"sha256:f52b79c8796d81391ab295b04e520bda6feed54d54931708872e8f9ae9db0ea1", |
|||
"sha256:ff8cff01582fa1a7e533cb97f628531c4014af4b5f38e33cdcfe5eec29b6d888" |
|||
], |
|||
"index": "pypi", |
|||
"version": "==5.3.0" |
|||
}, |
|||
"pkginfo": { |
|||
"hashes": [ |
|||
"sha256:5878d542a4b3f237e359926384f1dde4e099c9f5525d236b1840cf704fa8d474", |
|||
"sha256:a39076cb3eb34c333a0dd390b568e9e1e881c7bf2cc0aee12120636816f55aee" |
|||
], |
|||
"version": "==1.4.2" |
|||
}, |
|||
"pygments": { |
|||
"hashes": [ |
|||
"sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d", |
|||
"sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc" |
|||
], |
|||
"version": "==2.2.0" |
|||
}, |
|||
"python-magic": { |
|||
"hashes": [ |
|||
"sha256:f2674dcfad52ae6c49d4803fa027809540b130db1dec928cfbb9240316831375", |
|||
"sha256:f3765c0f582d2dfc72c15f3b5a82aecfae9498bd29ca840d72f37d7bd38bfcd5" |
|||
], |
|||
"index": "pypi", |
|||
"version": "==0.4.15" |
|||
}, |
|||
"readme-renderer": { |
|||
"hashes": [ |
|||
"sha256:bb16f55b259f27f75f640acf5e00cf897845a8b3e4731b5c1a436e4b8529202f", |
|||
"sha256:c8532b79afc0375a85f10433eca157d6b50f7d6990f337fa498c96cd4bfc203d" |
|||
], |
|||
"version": "==24.0" |
|||
}, |
|||
"requests": { |
|||
"hashes": [ |
|||
"sha256:65b3a120e4329e33c9889db89c80976c5272f56ea92d3e74da8a463992e3ff54", |
|||
"sha256:ea881206e59f41dbd0bd445437d792e43906703fff75ca8ff43ccdb11f33f263" |
|||
], |
|||
"version": "==2.20.1" |
|||
}, |
|||
"requests-toolbelt": { |
|||
"hashes": [ |
|||
"sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237", |
|||
"sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5" |
|||
], |
|||
"version": "==0.8.0" |
|||
}, |
|||
"six": { |
|||
"hashes": [ |
|||
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", |
|||
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" |
|||
], |
|||
"version": "==1.11.0" |
|||
}, |
|||
"tqdm": { |
|||
"hashes": [ |
|||
"sha256:3c4d4a5a41ef162dd61f1edb86b0e1c7859054ab656b2e7c7b77e7fbf6d9f392", |
|||
"sha256:5b4d5549984503050883bc126280b386f5f4ca87e6c023c5d015655ad75bdebb" |
|||
], |
|||
"version": "==4.28.1" |
|||
}, |
|||
"twine": { |
|||
"hashes": [ |
|||
"sha256:7d89bc6acafb31d124e6e5b295ef26ac77030bf098960c2a4c4e058335827c5c", |
|||
"sha256:fad6f1251195f7ddd1460cb76d6ea106c93adb4e56c41e0da79658e56e547d2c" |
|||
], |
|||
"index": "pypi", |
|||
"version": "==1.12.1" |
|||
}, |
|||
"urllib3": { |
|||
"hashes": [ |
|||
"sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", |
|||
"sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" |
|||
], |
|||
"version": "==1.24.1" |
|||
}, |
|||
"webencodings": { |
|||
"hashes": [ |
|||
"sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78" |
|||
], |
|||
"version": "==0.5.1" |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,12 @@ |
|||
#!/bin/bash |
|||
|
|||
# Ultra wild west single binary compiling |
|||
# https://github.com/linkedin/shiv |
|||
|
|||
shiv --output-file=distribusi.pyz \ |
|||
--site-packages=.venv/lib/python3.7/site-packages/ \ |
|||
--entry-point=distribusi.cli.cli_entrypoint \ |
|||
--python="/usr/bin/env python3" \ |
|||
--compressed \ |
|||
--compile-pyc \ |
|||
. |
@ -1,59 +1,93 @@ |
|||
import argparse |
|||
import os |
|||
|
|||
from distribusi.distribusi import distribusify |
|||
|
|||
|
|||
def build_argparser(): |
|||
parser = argparse.ArgumentParser(""" |
|||
distbusi is a content management system for the web that produces static |
|||
index pages based on folders in the filesystem. It is inspired by the |
|||
automatic index functions featured in several web servers. It works by |
|||
traversing the file system and directory hierarchy to automatically list |
|||
all the files in the directory and providing them with html classes and |
|||
tags for easy styling. |
|||
parser = argparse.ArgumentParser( |
|||
""" |
|||
distribusi is a content management system for the web that produces static |
|||
index pages based on folders in the files system. It is inspired by the |
|||
automatic index functions featured in several popular web servers. |
|||
distribusi works by traversing the file system and directory hierarchy to |
|||
automatically list all the files in the directory, detect the file types |
|||
and providing them with relevant html classes and tags for easy styling. |
|||
""") |
|||
|
|||
parser.add_argument( |
|||
'-d', |
|||
'--directory', |
|||
help="Select which directory to distribute" |
|||
'-d', '--directory', help="Select which directory to distribute", default="." |
|||
) |
|||
|
|||
parser.add_argument( |
|||
'-v', |
|||
'--verbose', |
|||
help="Print verbose debug output", |
|||
action="store_true" |
|||
'-s', '--style', help="Select a CSS style sheet to include" |
|||
) |
|||
|
|||
parser.add_argument( |
|||
'-v', '--verbose', help="Print verbose debug output", action="store_true" |
|||
) |
|||
|
|||
parser.add_argument( |
|||
'-t', |
|||
'--thumbnail', |
|||
help="Generate 150x150 thumbnails for images", |
|||
action="store_true" |
|||
help="Generate 450x450 thumbnails for images", |
|||
action="store_true", |
|||
) |
|||
|
|||
parser.add_argument( |
|||
'-n', |
|||
'--no-template', |
|||
help="Don't use the template to ouput html", |
|||
action="store_true" |
|||
help="Don't use the template to output html", |
|||
action="store_true", |
|||
) |
|||
|
|||
parser.add_argument( |
|||
'-nf', |
|||
'--no-filenames', |
|||
help="Don't add file names to listing", |
|||
action="store_true", |
|||
) |
|||
|
|||
parser.add_argument( |
|||
'-c', |
|||
'--captions', |
|||
help="Adds image captions based on EXIF metadata, requires 'exiftool'", |
|||
action="store_true", |
|||
) |
|||
|
|||
parser.add_argument( |
|||
'-r', |
|||
'--remove-index', |
|||
help="Recursively removes all instances of index.html that have been previously made by distribusi", |
|||
action="store_true") |
|||
|
|||
parser.add_argument( |
|||
'-e', |
|||
'--exclude-directory', |
|||
help="Exclude one or multiple directories from indexing", |
|||
nargs="*", |
|||
metavar='DIR') |
|||
|
|||
parser.add_argument( |
|||
'-f', |
|||
'--force', |
|||
help="Force whether distribusi overwrites or removes instances of index.html not generated by distribusi, use at own risk!", |
|||
action="store_true") |
|||
|
|||
parser.add_argument( |
|||
'--no-hidden', |
|||
help="Exclude hidden directories", |
|||
action="store_true") |
|||
|
|||
parser.add_argument( |
|||
'--menu-with-index', |
|||
help="Append index.html to menu items to aid navigation", |
|||
action="store_true") |
|||
|
|||
return parser |
|||
|
|||
|
|||
def cli_entrypoint(): |
|||
parser = build_argparser() |
|||
args = parser.parse_args() |
|||
|
|||
if args.directory: |
|||
if args.verbose: |
|||
print('Generating directory listing for', args.directory) |
|||
if args.thumbnail: |
|||
print('Making thumbnails') |
|||
directory = args.directory |
|||
else: |
|||
directory = '.' |
|||
|
|||
distribusify(args, directory) |
|||
distribusify(args, args.directory) |
|||
|
@ -1,127 +1,219 @@ |
|||
import base64 |
|||
import os |
|||
import subprocess |
|||
from io import BytesIO |
|||
|
|||
import magic |
|||
from distribusi.page_template import html_footer, html_head |
|||
from PIL import Image |
|||
|
|||
from distribusi.page_template import html_footer, html_head |
|||
from distribusi.mappings import CODE_TYPES, FILE_TYPES, SUB_TYPES |
|||
|
|||
CODE_TYPES = [ |
|||
'x-c', |
|||
'html' |
|||
] |
|||
|
|||
FILE_TYPES = { |
|||
'image': '<img class="image" src="{}">', |
|||
'pdf': ( |
|||
'<object data="{}" class="pdf" type="application/pdf">' |
|||
'<embed src="{}" type="application/pdf" /></object>' |
|||
), |
|||
'text': '<a href="{}" class="text">{}</a>', |
|||
'video': ( |
|||
'<video class="video" controls>' |
|||
'<source src="{}"></source></video>' |
|||
), |
|||
'audio': ( |
|||
'<audio controls class="audio">' |
|||
'<source src="{}"></source></audio>' |
|||
), |
|||
} |
|||
MIME_TYPE = magic.Magic(mime=True) |
|||
|
|||
|
|||
MIME_TYPE = magic.Magic(mime=True) |
|||
def caption(image): |
|||
try: |
|||
process = subprocess.Popen( |
|||
['exiftool', '-Comment', image], stdout=subprocess.PIPE) |
|||
out, err = process.communicate() |
|||
except Exception as e: |
|||
print(e) |
|||
print('Do you have exiftool installed?') |
|||
try: |
|||
caption = out.decode("utf-8").split(": ", 1)[1] |
|||
except Exception as e: |
|||
caption = '' |
|||
print(e) |
|||
return caption |
|||
|
|||
|
|||
def thumbnail(image, name, args): |
|||
try: |
|||
size = (450, 450) |
|||
im = Image.open(image) |
|||
im.thumbnail(size) |
|||
|
|||
if (im.mode == 'RGBA'): |
|||
bg = Image.new('RGBA', im.size, (255,255,255)) |
|||
composite = Image.alpha_composite(bg, im) |
|||
im=composite.convert('RGB') |
|||
|
|||
output = BytesIO() |
|||
im.save(output, format='JPEG') |
|||
im_data = output.getvalue() |
|||
data_url = base64.b64encode(im_data).decode() |
|||
if args.captions: |
|||
cap = caption(image) |
|||
else: |
|||
cap = name |
|||
return ( |
|||
"<figure><a href='{}'><img class='thumbnail' src='data:image/jpg;base64,{}'></a><figcaption>{}</figcaption></figure>" |
|||
).format(name, data_url, cap) |
|||
except Exception as e: |
|||
print('Thumbnailer:', e) |
|||
return "<figure><a href='{}'><img src='{}'></a><figcaption>{}</figcaption></figure>".format(name, name, name) |
|||
|
|||
|
|||
def div(args, type_, subtype, tag, name): |
|||
id_name = name.split('.')[0].replace(' ', '_') |
|||
if args.no_filenames: |
|||
filename = '' |
|||
else: |
|||
filename = '<span class="filename">{}</span>'.format(name) |
|||
|
|||
if 'image' in type_: |
|||
html = '<div id="{}" class="{}">{}</div>' |
|||
elif 'pdf' in subtype: |
|||
html = '<div id="{}" class="{}">{}' + filename + '</div>' |
|||
elif 'dir' in type_ or 'html' in subtype or 'unkown-file' in subtype: |
|||
html = '<div id="{}" class="{}">{}</div>' |
|||
else: |
|||
html = '<div id="{}" class="{}">{}' + filename + '</div>' |
|||
|
|||
return html.format(id_name, subtype, tag) |
|||
|
|||
def thumbnail(image, name): |
|||
size = (450, 450) |
|||
im = Image.open(image) |
|||
im.thumbnail(size) |
|||
output = BytesIO() |
|||
im.save(output, format='JPEG') |
|||
im_data = output.getvalue() |
|||
data_url = base64.b64encode(im_data).decode() |
|||
return ( |
|||
"<a href='{}'><img class='thumbnail' " |
|||
"src='data:image/jpg;base64,{}'></a>" |
|||
).format(name, data_url) |
|||
|
|||
def check_distribusi_index(args, index): |
|||
""" |
|||
check whether a index.html file is generated by distribusi |
|||
""" |
|||
|
|||
def div(mime, tag, *values): |
|||
id_name = values[0].split('.')[0].replace(' ', '_') |
|||
if not args.force: |
|||
with open(index, 'r') as f: |
|||
if '<meta name="generator" content="distribusi" />' in f.read(): |
|||
return True |
|||
else: |
|||
if args.verbose: |
|||
print(index, 'not generated by distribusi, skipping') |
|||
return False |
|||
elif args.force: |
|||
return True |
|||
|
|||
if 'image' in mime: |
|||
html = '<div id="{}">{}<br><span class="filename">{}</span></div>' |
|||
elif 'pdf' in mime: |
|||
html = '<div id="{}">{}<br><class="filename">{}</span></div>' |
|||
else: |
|||
html = '<div id="{}">{}</div>' |
|||
def write_index(args,index, html, html_head, html_footer): |
|||
with open(index, 'w') as f: |
|||
if not args.no_template: |
|||
if args.style: |
|||
fs = open(args.style, "r") |
|||
style = fs.read() |
|||
styled_html_head = html_head % style |
|||
else: |
|||
styled_html_head = html_head % '' |
|||
f.write(styled_html_head) |
|||
|
|||
return html.format(id_name, tag, values[0]) |
|||
for line in html: |
|||
f.write(line + '\n') |
|||
|
|||
if not args.no_template: |
|||
f.write(html_footer) |
|||
|
|||
|
|||
def distribusify(args, directory): # noqa |
|||
for root, dirs, files in os.walk(directory): |
|||
html = [] |
|||
|
|||
if args.verbose: |
|||
print('Listing', root) |
|||
|
|||
for name in files: |
|||
if args.exclude_directory: |
|||
if args.verbose: |
|||
print('Adding', name) |
|||
if 'index.html' not in name: |
|||
full_path = os.path.join(root, name) |
|||
mime = MIME_TYPE.from_file(full_path) |
|||
mime, format = mime.split('/') # example: plain text |
|||
print('Excluding directory:', ", ".join(args.exclude_directory)) |
|||
dirs[:] = [d for d in dirs if d not in args.exclude_directory] |
|||
|
|||
if args.verbose: |
|||
print(mime, format) |
|||
|
|||
if mime in FILE_TYPES: |
|||
# expansion for different kind of textfiles |
|||
if mime == 'text': |
|||
if name.endswith('.html') or name.endswith('.txt'): |
|||
# what types of text files to expand |
|||
a = open(full_path).read() |
|||
elif format in CODE_TYPES: |
|||
# if the plain text is code, |
|||
# which types do we wrap in pre-tags? |
|||
a = "<pre>"+open(full_path).read()+"</pre>" |
|||
else: |
|||
a = FILE_TYPES[mime] |
|||
|
|||
if mime == 'image' and args.thumbnail: |
|||
a = thumbnail(full_path, name) |
|||
else: |
|||
a = FILE_TYPES[mime] |
|||
|
|||
if format in FILE_TYPES: |
|||
a = FILE_TYPES[format] |
|||
|
|||
if mime not in FILE_TYPES and format not in FILE_TYPES: |
|||
# catch exceptions not defined in FILE_TYPES before |
|||
a = "<a href='{}'>{}</a>" |
|||
if args.verbose: |
|||
message = 'mime-type not in list, adding as href: \n' |
|||
print(message, mime, format, name) |
|||
if args.no_hidden: |
|||
dirs = list(filter(lambda d: not d.startswith('.'), dirs)) |
|||
files = list(filter(lambda f: not f.startswith('.'), files)) |
|||
|
|||
a = a.replace('{}', name) |
|||
html.append(div(mime, a, name)) |
|||
dirs.sort() |
|||
files.sort() |
|||
|
|||
if root != directory: |
|||
html.append('<a href="../">../</a>') |
|||
if not args.remove_index: |
|||
html = [] |
|||
|
|||
for name in dirs: |
|||
a = "<a href='{}' class='dir'>{}/</a>".replace('{}', name) |
|||
html.append(div('dir', a, 'folder')) |
|||
if args.verbose: |
|||
print('Generating directory listing for', root) |
|||
|
|||
for name in sorted(files): |
|||
|
|||
with open(os.path.join(root, 'index.html'), 'w') as f: |
|||
if not args.no_template: |
|||
f.write(html_head) |
|||
if 'index.html' not in name: |
|||
full_path = os.path.join(root, name) |
|||
mime = MIME_TYPE.from_file(full_path) |
|||
# example: MIME plain/text becomes 'type' plain 'subtype' text |
|||
type_, subtype = mime.split('/') |
|||
|
|||
for line in html: |
|||
f.write(line+'\n') |
|||
caption = name |
|||
|
|||
if not args.no_template: |
|||
f.write(html_footer) |
|||
if args.verbose: |
|||
print('Found', name, 'as', mime) |
|||
|
|||
if type_ in FILE_TYPES: |
|||
|
|||
a = FILE_TYPES[type_].format(name, caption) |
|||
|
|||
# expansion for different kind of text files |
|||
if type_ == 'text': |
|||
if name.endswith('.html') or subtype == 'html': |
|||
subtype = 'html' |
|||
# what types of text files to expand |
|||
a = '<section id="{}">{}</section>'.format(name, open(full_path).read()) |
|||
elif subtype in CODE_TYPES or name.endswith('.txt'): |
|||
# if the plain text is code, |
|||
# which types do we wrap in pre-tags? |
|||
a = "<pre>" + open(full_path).read() + "</pre>" |
|||
else: |
|||
subtype = subtype+' unkown-file' |
|||
a = "<a href='{}'>{}</a>" |
|||
# a = FILE_TYPES[type_] |
|||
|
|||
if type_ == 'image': |
|||
if args.thumbnail: |
|||
a = thumbnail(full_path, name, args) |
|||
if args.no_filenames: |
|||
caption = "" |
|||
a = FILE_TYPES[type_].format(name, caption) |
|||
if args.captions: |
|||
caption = caption(full_path) |
|||
a = FILE_TYPES[type_].format(name, caption) |
|||
|
|||
if subtype in SUB_TYPES: |
|||
a = SUB_TYPES[subtype] |
|||
|
|||
if type_ not in FILE_TYPES and subtype not in SUB_TYPES: |
|||
# catch exceptions not yet defined in FILE_TYPES or SUB_TYPES |
|||
a = "<a href='{}'>{}</a>" |
|||
if args.verbose: |
|||
message = 'not in list of file types, adding as plain href: \n' |
|||
print(type_, subtype, message, name) |
|||
subtype = subtype + ' unkown-file' |
|||
|
|||
a = a.replace('{}', name) |
|||
|
|||
html.append(div(args, type_, subtype, a, name)) |
|||
|
|||
if root != directory: |
|||
if args.menu_with_index: |
|||
html.append('<a href="../index.html">../</a>') |
|||
else: |
|||
html.append('<a href="../">../</a>') |
|||
|
|||
for name in dirs: |
|||
if args.menu_with_index: |
|||
a = "<a href='{}/index.html'>{}</a>".replace('{}', name) |
|||
else: |
|||
a = "<a href='{}'>{}/</a>".replace('{}', name) |
|||
|
|||
html.insert(0, div(args, 'dir', 'dir', a, 'folder')) |
|||
|
|||
index = os.path.join(root, 'index.html') |
|||
if os.path.exists(index): |
|||
if check_distribusi_index(args, index): |
|||
write_index(args,index,html, html_head, html_footer) |
|||
elif not os.path.exists(index): |
|||
write_index(args,index,html, html_head, html_footer) |
|||
|
|||
if args.remove_index: |
|||
index = os.path.join(root, 'index.html') |
|||
if 'index.html' in files: |
|||
try: |
|||
if check_distribusi_index(args, index): |
|||
if args.verbose: |
|||
print('Removing index.html from', root) |
|||
os.remove(index) |
|||
except Exception as e: |
|||
print(e) |
|||
|
@ -0,0 +1,14 @@ |
|||
CODE_TYPES = ['x-c', 'x-shellscript', 'x-python'] |
|||
|
|||
FILE_TYPES = { |
|||
'image': '<figure><img class="image" src="{}"><figcaption>{}</figcaption></figure>', |
|||
'text': '<a href="{}" class="text">{}</a>', |
|||
'video': ('<video controls>' '<source src="{}"></video>'), |
|||
'audio': ('<audio controls class="audio">' '<source src="{}"></audio>'), |
|||
} |
|||
|
|||
SUB_TYPES = { |
|||
'pdf': ( |
|||
'<object data="{}" class="pdf" type="application/pdf">' |
|||
'<embed src="{}" type="application/pdf" /></object>') |
|||
} |
@ -0,0 +1,9 @@ |
|||
[build-system] |
|||
requires = [ |
|||
"setuptools >= 41.0.0", |
|||
"wheel", |
|||
] |
|||
build-backend = "setuptools.build_meta" |
|||
|
|||
[tool.black] |
|||
skip-string-normalization = true |
Loading…
Reference in new issue