9 changed files with 208 additions and 37 deletions
+1 -1
View File
@@ -86,6 +86,7 @@ $row-gutter-height: $row-height + $row-gutter;
};
@while $offset<=$max-size {
$i: $i+1;
@if $odd{
$offset:$offset+$col-width;
$odd:false;
@@ -96,7 +97,6 @@ $row-gutter-height: $row-height + $row-gutter;
.#{$class-name}#{$i} {
#{$prop}: $offset;
};
$i: $i+1;
}
}
+7
View File
@@ -202,3 +202,10 @@ $paper-height: $page-height + ( $edge * 2 );
*/
-webkit-region-break-before: always;
}
img.missing-hd{
opacity: 0.5;
border: 1mm red solid;
}
+3 -4
View File
@@ -36,7 +36,7 @@
.body:before,
.body:after {
display: block;
font-family: "Belgika8th", sans-serif;
font-family: sans-serif;
font-size: 6pt;
line-height: $line-height;
letter-spacing: 0.25pt;
@@ -47,10 +47,9 @@
.body:after { bottom: $line-height * -3; }
/*gauche*/
/*.body:before { content: "Type d'article — Titre de l'article"; } */
.paper:nth-child(odd) .body:before { content: "Pied de page"; }
/*droite*/
/*.body:before { content: "Médor n°1 — printemps 2015"; }*/
.paper:nth-child(even) .body:before { content: "Médor — hiver 2016-2017"; }
.paper:nth-child(even) .body:before { content: "Pied de page"; }
.body:after { content: counter(folio); z-index: 499;}
+51
View File
@@ -8,3 +8,54 @@ $(function() {
$("#master-page").attr("data-width", $(".paper:first-child").width()).hide();
});
// __ ______
// / / / / __ \
// / /_/ / / / /
// / __ / /_/ /
// /_/ /_/_____/
var len;
var switchedLen = 0;
function imageExists($elmt, src, callback) {
var img = new Image();
img.onload = function() { callback($elmt, src, true); };
img.onerror = function() { callback($elmt, src, false); };
img.src = src;
}
function switchHD($img, src, exists) {
// console.log('src=' + src + ', exists=' + exists);
if(exists){
$img.attr('src', src);
}else{
console.error('src '+src+' does not exists');
$img.addClass('missing-hd');
}
switchedLen++;
// console.log('len : '+len+" | switchedLen : "+switchedLen);
if(len == switchedLen)
console.log('HD assets enabled');
}
function enableHD(){
console.log('enabling HD assets');
len = $('img').length;
$('img').each(function(index, el) {
// console.log('img', el);
var $img = $(el);
var src = $img.attr('src');
// console.log('src BEFORE',src);
src = src.replace('assets', 'assets-hd');
src = src.replace('-preview', '');
// console.log('src AFTER', src);
// $img.attr('src', src);
imageExists($img, src, switchHD);
// console.log('--');
});
}
+1 -1
View File
@@ -1 +1 @@
nb_page = 100;
nb_page = 50;
+121 -17
View File
@@ -17,17 +17,36 @@ from bs4 import BeautifulSoup
import pypandoc
import json
import re
import pyphen
_BOOK_SRC = 'book-src'
_BUILD_d = "build"
# CUR_PATH = os.path.dirname(os.path.abspath(__file__))
# hyphenator
_H_FR = pyphen.Pyphen(lang='fr')
_ERROR_PREF = '\033[1m[!!]\033[0m '
print("Building book")
def main():
# clean build directory
if os.path.isdir(_BUILD_d):
shutil.rmtree(_BUILD_d, ignore_errors=True)
os.mkdir(_BUILD_d)
if not os.path.isdir(_BUILD_d):
# shutil.rmtree(_BUILD_d, ignore_errors=True)
os.mkdir(_BUILD_d)
if os.path.isdir(os.path.join(_BUILD_d, 'assets')):
shutil.rmtree(os.path.join(_BUILD_d, 'assets'), ignore_errors=True)
if os.path.isfile(os.path.join(_BUILD_d, 'stories.html')):
shutil.rmtree(os.path.join(_BUILD_d, 'stories.html'), ignore_errors=True)
print('Hyphen has fr language')
print('fr' in pyphen.LANGUAGES)
parse_book(_BOOK_SRC)
@@ -91,20 +110,19 @@ def generate_html(book, toc):
# get story div
story_dom = template_dom.find('div', {"id":"flow-main"})
#
# loop through pages to convert them to html and add it to main html file
# book_build_d_pages = os.path.join(_BUILD_d,'pages')
# os.mkdir(book_build_d_pages)
pi = 0
for p in toc:
print(toc[p]['file'])
pagename = toc[p]['file'].replace('.md', '')
for page in toc:
# print(toc[p])
pagename = toc[page]['label']
pageid = re.sub('[^a-z0-9]+', '-', pagename.lower())
print("\033[92m"+pageid+"\033[0m")
# files
in_f = os.path.join(_BOOK_SRC, toc[p]['file'])
in_f = os.path.join(_BOOK_SRC, toc[page]['file'])
if not os.path.isfile(in_f):
print("Source path is not a file, can't generate html : "+in_f)
print(_ERROR_PREF+"Source path is not a file, can't generate html : "+in_f)
continue
# print('in_f : '+in_f)
@@ -122,22 +140,35 @@ def generate_html(book, toc):
extra_args=pdoc_args,
filters=pdoc_filters)
# outputfile=out_f)
# print("output :\n"+output)
output_dom = BeautifulSoup(output, 'html.parser')
# print("output_dom :")
# print(output_dom)
# append html story page to template_dom
story_page = BeautifulSoup('<div class="story-page" id="story-page-'+str(pi)+'"></div>', 'html.parser')
story_page.div.append(output_dom)
story_dom.append(story_page)
# hyphenate paragraphes
for node in output_dom.find_all('p'):
hyphenate(node)
# print(str(output_dom))
# copy images
for img in output_dom.find_all('img'):
# print('-- img ',img)
att_src = re.sub(r"^\/", "", img['src'])
img['src'] = att_src
# domimg = output_dom.find('img', {'src':img['src']})
# domimg['src'] = att_src
# print(domimg)
src_img = os.path.join(_BOOK_SRC, att_src)
# print('- - '+src_img)
if not os.path.isfile(src_img):
print("Source path is not a file, can't copy img : "+src_img)
print(_ERROR_PREF+"Source path is not a file, can't copy img : \033[1m"+src_img+"\033[0m")
continue
dest_img = os.path.join(_BUILD_d, att_src)
@@ -149,13 +180,86 @@ def generate_html(book, toc):
shutil.copyfile(src_img, dest_img)
# append html story page to template_dom
story_page = BeautifulSoup('<div class="story-page story-page-'+str(pi)+'" id="'+pageid+'"></div>', 'html.parser')
story_page.div.append(output_dom)
story_dom.append(story_page)
pi = pi+1
# create main html file from filled template html dom
book_html_f = os.path.join(_BUILD_d,'stories.html')
with open(book_html_f, 'w') as fp:
fp.write(template_dom.prettify())
fp.write(template_dom.prettify(formatter=None))
def hyphenate(node):
# print("hyphenate")
nodetext = node.get_text()
# print(nodetext)
nodestr = str(node)
# print(nodestr)
for word in nodetext.split(' '):
# do not hyphenate if it's not a real word
if len(word) < 5 or re.search('\w+', word) == None:
continue
# cleaning word
# remove all non-alphanumerical characteres duplicated or more
word = re.sub('\W{2,}', '', word)
# remove all non-alphanumerical at the begining of word
word = re.sub('^\W', '', word)
# remove all non-alphanumerical at the end of word
word = re.sub('\W$', '', word)
# remove all word remaing having special chars
if re.search('\W+', word):
continue
# hyphenate word
word_hyphenated = _H_FR.inserted(word)
# remove hyphen precedeted by less than 3 letters
word_hyphenated = re.sub(r'^(\w{,2})-', r'\1', word_hyphenated)
# remove hyphen followed by less than 3 letters
word_hyphenated = re.sub(r'-(\w{,2})$', r'\1', word_hyphenated)
# replace scores by html elemt &shy;
word_hyphenated = re.sub(r'(\w)-(\w)', r'\1&shy;\2', word_hyphenated)
# replace double scores by score+$shy;
word_hyphenated = re.sub(r'--', r'-&shy;', word_hyphenated)
# TODO: attention au date 1950-1960, le tiret disparait
# print(word_hyphenated)
if re.search('\b+', word):
print(word+" | "+word_hyphenated)
try:
# replace word by hyhanated_word on source
nodestr = re.sub(word, word_hyphenated, nodestr)
# replaced_str_dom = BeautifulSoup(replaced_str, 'html.parser')
# node.string = replaced_str
# node.string.replace_with(node.string)
except Exception as e:
print(_ERROR_PREF+'Replacement error with \033[1m'+word+'\033[0m | \033[1m'+word_hyphenated+"\033[0m")
print(e)
print(node.string)
print('[//]')
pass
# add none breaking spaces
nbspzr_before = ['»', '\!', '\?', ':', ';']
for char in nbspzr_before:
nodestr = re.sub(r'(\w|>)\s('+char+')', r'\1&nbsp;\2', nodestr)
nbspzr_after = ['«']
for char in nbspzr_after:
nodestr = re.sub(r'('+char+')\s(\w|<)', r'\1&nbsp;\2', nodestr)
# print(nodestr)
# replace node by hyphenated one
node.replace_with(nodestr)
if __name__ == "__main__":
+21 -12
View File
@@ -6,15 +6,24 @@ var rename = require('gulp-rename');
var shell = require('gulp-shell')
var watch = require('gulp-watch');
var webserver = require('gulp-webserver');
var portscanner = require('portscanner');
gulp.task('webserver', function() {
gulp.src('.')
.pipe(webserver({
livereload: false,
directoryListing: false,
open: false,
fallback: 'index.html'
}));
gulp.task('webserver', ['build'], function() {
// Find the first available port. Asynchronously checks, so first port
// determined as available is returned.
portscanner.findAPortNotInUse(8000, 8020, '127.0.0.1', function(error, port) {
// console.log('AVAILABLE PORT AT: ' + port)
gulp.src('.')
.pipe(webserver({
port:port,
livereload: false,
directoryListing: false,
open: false,
fallback: 'index.html'
}));
})
});
gulp.task('scss', function () {
@@ -29,9 +38,9 @@ gulp.task('gui', function () {
.pipe(gulp.dest('./assets/css/dist'));
});
gulp.task('sync', shell.task([
'./bin/sync.sh'
]));
// gulp.task('sync', shell.task([
// './bin/sync.sh'
// ]));
gulp.task('build', shell.task([
'./bin/build.py'
@@ -39,7 +48,7 @@ gulp.task('build', shell.task([
// default gulp task
gulp.task('default', ['webserver', 'sync', 'scss', 'gui', 'build'], function() {
gulp.task('default', ['scss', 'gui', 'webserver'], function() {
gulp.watch('./assets/css/**/*.scss', ['scss']);
gulp.watch('./assets/css/gui.scss', ['gui']);
gulp.watch(['bin/build.py', './book-src/*', './templates/*.tpl.html'], ['build']);
+2 -1
View File
@@ -16,7 +16,8 @@
"gulp-sass": "^2.0.1",
"gulp-shell": "^0.5.2",
"gulp-watch": "^4.2.4",
"gulp-webserver": "^0.9.1"
"gulp-webserver": "^0.9.1",
"portscanner": "^2.1.1"
},
"dependencies": {}
}
+1 -1
View File
@@ -14,7 +14,7 @@
<div id="master-page" class="paper">
<div class="page">
<div class="body">
<div class="bloc x1 y1 w8 b0 flow-main" style="margin-bottom:0pt;"></div>
<div class="bloc x1 y1 w8 h12 flow-main" style="margin-bottom:0pt;"></div>
<!-- <div class="bloc x0 w1 flow-fn" style="bottom: 115pt;"></div> -->
</div>
</div>