reader, quotes, backend, favicon, headshot

This commit is contained in:
miggymofongo2 2023-12-27 19:11:21 -08:00
parent d21a10754c
commit c94e5a05c7
60 changed files with 1834 additions and 0 deletions

7
LICENSE Normal file
View file

@ -0,0 +1,7 @@
Copyright (c) 2013 Satoru Matsushima
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

75
app.py Normal file
View file

@ -0,0 +1,75 @@
from flask import Flask, render_template, request, send_from_directory
import os
app = Flask(__name__)
EPUBS_DIR = {
'default': './bookshelf/'
}
@app.route('/')
def index():
return send_from_directory(app.root_path,'index.html')
@app.route('/search', methods=['GET'])
def search():
query = request.args.get('searchQuery', '').lower()
matching_files = []
for _, dir_path in EPUBS_DIR.items():
all_files = [f for f in os.listdir(dir_path) if f.lower().endswith('.epub')]
matching_files += [f for f in all_files if query in f.lower()]
# Render the results as HTML
results_html = "".join([f'<li><a href="#" onclick="loadEpubInBibi(\'/bookshelf/{file}\'); return false;">{file}</a></li>' for file in matching_files])
return results_html
@app.route('/reader/<path:subpath>')
def serve_bibi_assets(subpath):
# This will serve all of Bibi's assets, such as JavaScript, CSS, etc.
return send_from_directory('./reader', subpath)
@app.route('/bookshelf/<filename>')
def serve_epub(filename):
return send_from_directory('./bookshelf', filename)
#@app.route('/reader')
#def serve_bibi_reader():
# book_path = request.args.get('book')
# You might want to do some checks on `book_path` for security reasons.
# return send_from_directory('./reader', 'index.html')
@app.route('/reader')
def serve_bibi_reader():
book_path = request.args.get('book', '')
if book_path:
# Check if the EPUB file exists in the bookshelf
full_path = os.path.join('bookshelf', book_path.strip('/'))
if os.path.exists(full_path):
# Serve the Bibi reader's index.html
# The book path will be handled by Bibi's JavaScript
return send_from_directory('reader', 'index.html')
else:
return "EPUB file not found", 404
return "No book specified", 400
@app.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(app.root_path, './favicon.ico'),
'favicon.ico', mimetype='image/vnd.microsoft.icon')
if __name__ == "__main__":
app.run(debug=True)

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
img/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
img/headshot.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

241
index.html Normal file
View file

@ -0,0 +1,241 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Miguel's Rincon </title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
<script src="https://unpkg.com/htmx.org"></script>
<style>
.quote-banner {
/* Your styling for the banner */
padding: 10px;
text-decoration: blue;
font-weight: bold;
background-color: #a88a8a;
text-align: center;
/* other styles as needed */
}
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f5f5;
}
header {
background-color: #333;
color: white;
text-align: center;
padding: 20px;
position: sticky;
top: 0;
z-index: 100;
}
.navbar {
background-color: #333;
overflow: hidden;
}
.navbar a {
float: left;
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
.navbar a:hover {
background-color: #ddd;
color: black;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background-color: #fff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
h1 {
font-size: 36px;
}
p {
font-size: 18px;
line-height: 1.5;
}
footer {
background-color: #333;
color: white;
text-align: center;
padding: 10px;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container-fluid" style="background-color: bisque;">
<a class="navbar-brand" href="#">El asteroide de Miguel</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarScroll" aria-controls="navbarScroll" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarScroll">
<ul class="navbar-nav me-auto my-2 my-lg-0 navbar-nav-scroll" style="--bs-scroll-height: 100px;">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Reader</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Download a Resume
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Public Interest</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#">Hospitality</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled" aria-disabled="true">Portfolio</a>
</li>
</ul>
<!-- implement a search here for book reader -->
<form class="d-flex" role="search">
<input type="text"
hx-get="/search"
hx-params="searchQuery:val"
hx-trigger="keyup delay:300ms"
hx-target="#resultsContainer"
placeholder="Search for EPUBs...">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
<div class="navbar">
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Services</a>
<a href="#">Contact</a>
</div>
<section class="hero">
<h2>Welcome to Your Website</h2>
<p>Your message or call to action goes here.</p>
</section>
<div class="container">
<h2>About Us</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam eget dui in quam tincidunt malesuada. Vestibulum euismod urna a odio vulputate, ut cursus elit rhoncus.</p>
</div>
<section>
<div class="container">
<div class="row">
<div class="container mt-3">
<h2>¡Soy Miguel!</h2>
<div class="card" style="width:400px">
<img class="card-img-top" src="/img/headshot.jpg" alt="miguel headshot" style="width:100%">
<div class="card-body">
<h4 class="card-title">Miguel Almodovar</h4>
<p class="card-text">Miguel es un profesional comunicatorio que esta aprendiendo como programar</p>
<a href="https://miguelalmodo.com/about" class="btn btn-primary">See Main Bio</a>
</div>
</div>
<br>
</div></div></div>
</section>
<section>
<div class="container-fluid">
<!-- In your HTML file -->
<div id="quoteBanner" class="quote-banner">Quote goes here</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
fetch('quotes.json')
.then(response => response.json())
.then(quotes => {
let currentQuoteIndex = 0;
const quoteBanner = document.getElementById('quoteBanner');
// Function to update quote
function updateQuote() {
quoteBanner.textContent = quotes[currentQuoteIndex++];
if (currentQuoteIndex >= quotes.length) currentQuoteIndex = 0;
}
// Set initial quote and update every 10 seconds
updateQuote();
setInterval(updateQuote, 10000);
});
});
</script>
</section>
<section>
<div class="container">
<p>Aqui puedes completar tareas sobre la ciencia politica y varias otras temas</p>
</div>
</section>
<section>
<!-- search results -->
<div id="resultsContainer"></div>
<!-- search results -->
</section>
<section>
<div class="container">
<a href="https://migs.uber.space/reader/index.html" data-bibi="embed" data-bibi-style="[[ CSS for embeded Bibi frame, as you like ]]">[[ Title of the Book ]]</a>
<script src="/reader/resources/scripts/bibi.js"></script>
<iframe id="bibi-frame" src="/reader/index.html" width="100%" height="600px" frameborder="0"></iframe>
<script>
function loadEpubInBibi(epubUrl) {
document.getElementById('bibi-frame').src = "reader/?book=" + epubUrl;
}
</script>
</div>
</section>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
</body>
</html>

1
quotes.json Normal file
View file

@ -0,0 +1 @@
["\"So many places I want to see... I know I\u2019ll get there someday. I\u2019ll find a way somehow. I\u2019m sure of it.\"\nARIEL, Kingdom Hearts", "\"You be careful, now, both of you.\"\nDAISY DUCK", "\"All for one, and one for all!\"\nGOOFY, Kingdom Hearts", "\"Cricket's the name. Jiminy Cricket, at your service.\"\nJIMINY CRICKET, Kingdom Hearts", "\"I want to be a part of your life no matter what. That's all.\"\nKAIRI, Kingdom Hearts III", "\"There will always be a door to the light.\"\nKING MICKEY, Kingdom Hearts II", "\"We may never meet again, but we'll never forget each other.\"\nLEON, Kingdom Hearts", "\"The heart of all kingdoms, the heart of all that lives. A dominion fit to be called Kingdom Hearts must be MY dominion.\"\nMALEFICENT, Kingdom Hearts II", "\"The name is Merlin! I'm a powerful wizard, and I'll have you know a lot of wisdom comes with age.\"\nMERLIN, Kingdom Hearts Birth by Sleep", "\"Kid, I got two words of advice for you: Attack!\"\nPHILOCTETES, Kingdom Hearts", "\"What really makes someone a hero isn't what they wear or what they say\u2014it's the things they do and how they treat everyone.\"\nQUEEN MINNIE MOUSE, Kingdom Hearts Birth by Sleep", "\"I'm going to face my past.\"\nSIMBA, Kingdom Hearts II", "\"My friends are my power!\"\nSORA, Kingdom Hearts", "\"But the girl could prove useful. And I've got the Heartless on my side. Triton, my old friend...Your day is coming.\"\nURSULA, Kingdom Hearts"]

8
reader/and/jo.js Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,8 @@
/*!
*
* # Bibi Extension: Analytics ()
*
* * © Satoru Matsushima - https://bibi.epub.link or https://github.com/satorumurmur/bibi
* * Open source under the MIT License - https://github.com/satorumurmur/bibi/blob/master/LICENSE
*
*/!function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i:i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=16)}({16:function(e,t){Bibi.x({id:"Analytics",description:"Utilities for Tracking and Logging with Google Analytics.",author:"Satoru Matsushima (@satorumurmur)",version:"1.2.0-demo"})((function(){"use strict";var e,t,n,i,r,a;"string"==typeof this["tracking-id"]&&this["tracking-id"]&&(e=window,t=document,n="script",i="ga",e.GoogleAnalyticsObject=i,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,r=t.createElement(n),a=t.getElementsByTagName(n)[0],r.async=1,r.src="//www.google-analytics.com/analytics.js",a.parentNode.insertBefore(r,a),ga("create",this["tracking-id"],"auto",{allowLinker:!0}),ga("require","linker"),ga("linker:autoLink",S["trustworthy-origins"].reduce((function(e,t){return e.push(t.replace(/^\w+:\/\//,""))}),[])),E.add("bibi:loaded-navigation",(function(){return sML.forEach(I.Panel.BookInfo.Navigation.querySelectorAll("a"))((function(e){return e.addEventListener("click",(function(){ga("send",{hitType:"event",eventCategory:"Bibi: Jumped by Navigation",eventAction:B.Path,eventLabel:e.innerHTML.replace(/<[^>]*>/g,"")+' - "'.concat(e.getAttribute("data-bibi-original-href"),'"'),eventValue:void 0})}))}))})),E.add("bibi:played:by-button",(function(){ga("send",{hitType:"event",eventCategory:"Bibi: Played by Button",eventAction:B.Path,eventLabel:S["parent-uri"]?"on: "+S["parent-uri"].replace(/#.+$/,""):"",eventValue:void 0})})),E.add("bibi:scrolled",(function(){if(100!=R.Current.Percent)return!1;ga("send",{hitType:"event",eventCategory:"Bibi: Read Through",eventAction:B.Path,eventLabel:Date.now()-Bibi.TimeOrigin,eventValue:void 0})})))}))}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,8 @@
/*!
*
* # # Bibi Extension: Unaccessibilizer ("What a...")
*
* * Reluctantly coded by Satoru Matsushima - https://bibi.epub.link or https://github.com/satorumurmur/bibi
* * Released into the public domain under the Unlicense - http://unlicense.org/UNLICENSE
*
*/!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=27)}({27:function(e,t){Bibi.x({id:"Unaccessibilizer",description:"What a...",author:"Satoru Matsushima (@satorumurmur)",version:"1.2.0"})((function(){"use strict";var e=this,t=["-webkit-","-moz-","-ms-",""];E.bind("bibi:postprocessed-item",(function(n){"prevent"==e["select-elements"]&&t.forEach((function(e){["user-select","user-drag"].forEach((function(t){n.Body.style[e+t]="none"}))})),"prevent"==e["save-images"]&&sML.forEach(n.Body.querySelectorAll("img, svg, image"))((function(e){t.forEach((function(t){["user-select","user-drag"].forEach((function(n){e.style[t+n]="none"})),O.Touch&&(e.style[t+"pointer-events"]="none")})),e.draggable=!1,e.addEventListener("contextmenu",O.preventDefault)})),"prevent"==e["use-contextmenu"]&&n.contentDocument.addEventListener("contextmenu",O.preventDefault)}))}))}});

11
reader/extensions/zine.js Normal file

File diff suppressed because one or more lines are too long

42
reader/index.html Normal file
View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html id="bibi">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>This E-Book is Published with Bibi | EPUB Reader on your website.</title>
<!-- # Bibi | EPUB Reader on your website. : © Satoru Matsushima - https://bibi.epub.link or https://github.com/satorumurmur/bibi / Licensed under the MIT License - https://github.com/satorumurmur/bibi/blob/master/LICENSE -->
<!-- 「わたしのことは『ビビ』と呼んでください。『ビビ』はわたしの名前なんです」 —— エレクトラ・パブリケーヌ『ビビのみぎくるぶし』 -->
<!-- 「まあ! それじゃあやっぱり、『ビビ』はわたしの“名前”だったのですね?」 —— ソフィア・パインアイランド『ビビさんたちのこと』 -->
<!-- 「このあたりにビビさんという人がいると聞いて来たのですが、あなたですか?」 —— ビビ・ララルー『ポケットに眼鏡』 -->
<link id="bibi-style" rel="stylesheet" href="/reader/resources/styles/bibi.css" />
<link id="bibi-dress" rel="stylesheet" href="/reader/wardrobe/everyday/bibi.dress.css" />
<script id="bibi-script" src="/reader/resources/scripts/bibi.js"></script>
<script id="bibi-preset" src="/reader/presets/default.js" data-bibi-bookshelf=""></script>
</head>
<body data-bibi-book="">
<div id="bibi-info">
<h1>This E-Book is Published on the Web with Bibi | EPUB Reader on your website.</h1>
</div>
<div id="bibi-book-data" data-bibi-book-mimetype="application/epub+zip">
</div>
</body>
</html>

286
reader/presets/README.md Normal file
View file

@ -0,0 +1,286 @@
プリセット指定マニュアル
====================================================================================================
かんたんですが、プリセットについて解説します。今後マニュアルにまとめる計画ですので、読みづらさはしばしご容赦ください。
※ ときどき、実際のプリセットファイルの内容に追いついていない場合があります。申し訳ありませんがご容赦ください(もしできればご指摘ください)。
プリセットとは / つかいかた
----------------------------------------------------------------------------------------------------
プリセットファイルとは、リーダとしてのデフォルト挙動やレイアウトの初期設定を外部化したテキストファイルです。これを編集することでビビの振る舞いをカスタマイズすることができます。
bibi/presets フォルダに入れて使うのが基本ですが、じつはどこか別の場所でも(余所のサーバでも)かまいません。
配布状態の bibi/index.html は bibi/presets/default.js を呼び出しています。設定を変更したいときは、この default.js を直接編集してもいいのですが、default.js を複製・リネームして別のプリセットを作成した上で、bibi/index.html から呼び出すファイルをそちらに変更することをお勧めします。
bibi/index.html も、たとえば bibi/the-great-book.html のように複製・リネームして使い分けることができるので、本ごとに HTML とプリセットの組み合わせを使い分けることができます。
カスタマイズについて、はじめに
----------------------------------------------------------------------------------------------------
以下、挙動をカスタマイズできる具体的な指定について説明しますが、多くは、対象とする EPUB によって一長一短があります。だからこそ、ビビ側で一律に固定せず、プリセットとして編集可能にしてあるというわけです。
読者自身が読みながらボタンで変更できる項目もありますが、ご自身で作成した EPUB を読者に見せたい場合や、ご自身で見た目をカスタマイズした Bibi を読者に使ってもらいたい場合など、EPUB に合わせたスタイルやあなたらしいスタイルを予めプリセットで指定しておくと、きっとステキだと思います。
### この文書内で使用される用語の定義
アイテムとは、表示されるファイルひとつひとつのことです。
「見開き」とは、アイテムをつつむブロックです。リフロー指定のアイテムはそれ1つだけで「見開き」を構成します。固定レイアウトで左右ペアが作られている場合は、その2つが1つの「見開き」に入ります。
「長さ」は、進行方向サイズのことです。水平方向に進行しているときは左右幅、垂直なら上下高を指します。同様に「広さ」は、水平進行なら上下高、垂直なら左右幅です。そして、それらの数値が小さい状態を「短い」「狭い」ということにします。
これらの定義は EPUB もしくは電子書籍について一般に使われているわけではなく、あくまでビビ用語だと思ってください。
項目の説明1:基本設定
----------------------------------------------------------------------------------------------------
ビビのごく基本的な振る舞いを制御します。
### "bookshelf" …… bookshelf ディレクトリまでのパス
そのプリセットファイルからみた bookshelf ディレクトリのパスです。基本的には、同じウェブサーバ内の bookshelf ディレクトリまでの相対パス・ルート相対パス("../../bibi-bookshelf/" や "/bibi-bookshelf/" など)を記述します。
高度な設定として、クロスオリジンリクエストが許可されているサーバの bookshelf ディレクトリを http(s):// から書くこともできます。ただし、そのサーバのオリジンは、この文書の最後に述べる "trustworthy-origins" に含まれていなければなりません。
### "reader-view-mode" …… 表示モードの初期値(ページめくり・横スクロール・縦スクロール)
* "paged" を指定するとページめくりモード、
* "horizontal" なら横スクロールモード、
* "vertical" なら縦スクロールモード
……で表示を開始します。読者は随時変更できるので、あくまで最初にどのモードで表示するか、ということです。
### "fix-reader-view-mode" …… 表示モードを固定して変更を禁止するかどうか
"yes", "no", "desktop", "mobile" の4つから選べます。
この項目の初期値は "no" で、そのままにしておくことをオススメします。
"yes" にするといつも、"desktop" ならパソコンのとき、"mobile" ならスマートフォンのときに、ユーザが表示モードを変更できなくなり、変更ボタンも表示されなくなります。コンテンツの性質によって禁止したほうがユーザ体験を向上させられるときに使います。
以降、"yes", "no", "desktop", "mobile" の4つから選択する形式の指定がいくつか登場しますが、切り替え条件はすべて同じです
### "single-page-always" …… 2ページの見開きにせず1ページで表示させるかどうか
"yes", "no", "desktop", "mobile" から選択してください。
初期値は "no" で、その場合、横書きの本をページめくりモードまたは横スクロールモードで表示したとき、画面の横幅に余裕があれば、1画面あたり2ページの見開きで表示します。
"yes" にするといつも、"desktop" ならパソコンのとき、"mobile" ならスマートフォンのときに、画面の横幅が広くても常に1画面あたり1ページで表示させます。
### "autostart" …… 貼り付け時、再生ボタンのクリックを待たずに自動的に本を開くかどうか
ビビはウェブページに埋め込んで使えますが、データ量の大きい本を自動再生すると、親ウェブページの読み込み処理を遅くしてしまう場合があります。とはいえ、軽い本なら自動再生してしまいたいかもしれませんし、パソコンとスマートフォンで挙動を切り替えたいこともあるでしょう。そこでこれも、"yes", "no", "desktop", "mobile" の値で、切り替えられるようにしました。
"yes" なら、どんなときもいつも自動再生します。"no" は逆に、必ず再生ボタンのクリック/タップを必要とします。"desktop" は、パソコンなら自動再生、スマートフォンでは再生ボタンの操作が必要になります。"mobile" は "desktop" の逆です。
### "start-in-new-window" …… 貼り付け状態で再生ボタンを押したとき、新しいウィンドウで開くかどうか
貼り付け時、"autostart" の設定によって再生ボタンが表示された場合、その再生ボタンをクリック/タップしたとき、そのまま貼り付け状態で再生するか、新しいウィンドウで開くかどうかの設定です。これも "yes", "no", "desktop", "mobile" の4首から選べるようになっています。
"yes" はいつも別ウィンドウ、"no" はかならず埋め込み状態、"desktop" はパソコンなら別ウィンドウでスマートフォンなら埋め込み、"mobile" は "desktop" の逆、です。
ごく最近まで、ビビはいつも "mobile" と同じ挙動でした。スマートフォンでも埋め込んだまま起動したいという要望はちらほらとあったのですが、読むのに十分なパフォーマンスが出なかったためです。
が、どうやらそろそろまともに動くようになったようなので、任意で選べるようにしました。ただ、スマートフォンの場合、狭い画面内のさらに小さなフレームで開くと読者に不便を強いるかもしれません。よく気をつけて使ってみてください(ユーザは、メニュー内のボタンからいつでも別ウィンドウで開きなおせます。とはいえ)。
### "use-nombre" …… ページ番号・パーセントインジケータを使うか
ページをめくったときなどに、ビビは現在のページと全体のうちのパーセンテージを表示します。これを使うかどうか決められます。
これも "yes", "no", "desktop", "mobile" の設定で、初期値は "yes" です。
### "use-slider" …… ページスライダを使うか
画面の真ん中あたりをクリック/タップすると下端に出てくるページスライダの使用有無です。本の中の好きな位置にジャンプできる便利な UI で、有効になっていると、パソコンではページめくりモードのときに擬似的なスクロールバーの役割も兼ねます。
これも "yes", "no", "desktop", "mobile" の設定で、初期値は "yes" です。
### "use-arrows" …… 画面端のクリック/タップに反応するページめくり機能を使うか
ビビは画面左右にページめくり領域を用意して、クリック/タップで操作できるようになっています。ただ、特別なプログラムを組んで埋め込まれた親ページやアプリに独自の UI をつけて不要になったりしたときは、消せるようにしてあります。
これも "yes", "no", "desktop", "mobile" の設定で、初期値は "yes" です。これがないとめくれなくなってしまう場合がほとんどなので、基本的には "yes" のままをおすすめします。
### "use-keys" …… キーボード操作を受け付けるか
有効になっていると、キーボードのカーソルキーでもページ移動ができます。
これも "yes", "no", "desktop", "mobile" の設定で、初期値は "desktop" です。有効にしてもスマートフォンでは使えない機能なので、"desktop" か "no" をおすすめします。
### "use-cookie" …… 状態を Cookie に保存して次回開いたときに再現するか
有効になっていると、最後に開いていたときの表示モードとページ位置を保存して、次回も同じ本は同じ状態で開始します。
本の特定には、ビビのディレクトリとEPUB のメタファイルに書かれた本の IDidentifierの組み合わせが使われます。記録されるのは表示モードとページ位置だけで、この機能によってプライベートな情報が外部に漏れたりはしません。
これも "yes", "no", "desktop", "mobile" の設定で、初期値は "yes" です。パソコンとスマートフォンで挙動を分ける理由は特にないと思いますので、"yes" か "no" かで選ぶのがよいと思われます。
### "cookie-expires" …… Cookie を保存するときの有効期限(単位:ミリ秒)
上の "use-cookie" が有効になっている場合に保存される Cookie の有効期限です。
単位はミリ秒1/1000 秒)で、初期値は 1000 * 60 * 60 * 24 * 31。これは 1000 × 60 × 60 × 24 × 31 という意味で、最初の 1000 は 1/1000秒が1000なので1秒、つづけて、その60倍で1分、その60倍で1時間、その24倍で1日、その31倍なので、つまり31日間となっていますあらかじめ計算した値の 259200000 と書いておいても同じことですが、バラしたほうがわかりやすいかな、と)。
どんなに長くても1年以内にしておくのがいいと思います。たとえば読んでいる途中のリロードだけに対応したいなら数分程度でもいいのです。いろいろ試してみてください。
### "ui-font-family" …… 目次やその他の基本 UI のフォント指定
たとえば、台湾では句読点をボックス中央に配置したフォントが一般的なのでそういうフォントを使いたい、などなどの事情があるとき、デフォルトフォントを指定できます。値は CSS の font-family そのままです。
これは本文には影響しません。あくまで、ビビの UI として表示される目次などのフォントです。
項目の説明2:本の中身の表示カスタマイズ
----------------------------------------------------------------------------------------------------
### "book-background" …… 「見開き」の下の背景
「見開き」の白い箱のうしろに、暗い色のエリアがあります。そのスタイルを変更できます。値は CSS の background そのままです。つまり背景画像なども使えます。
### "spread-gap" …… 「見開き」と「見開き」の間隔
縦/横スクロールモード表示時の、「見開き」同士の間隔です。単位は px。
最初と最後の「見開き」とウィンドウ端の距離は、この値にかかわらず、ウィンドウの真ん中に来るようにウィンドウ端との距離が調節されます。
### "spread-margin" …… 「見開き」とウィンドウの間隔
「見開き」とウィンドウの、「幅」方向(本の進行方向と垂直の軸)の間隔です。単位は px。
### "spread-border-radius" …… 「見開き」のカド丸設定
「見開き」の白い箱のカドを丸めることができます。CSS の border-radius に適用する値そのままです。
### "spread-box-shadow" …… 「見開き」に影を付けるなら CSS を
「見開き」の白い箱に影をつけられます。CSS の box-shadow に適用する値そのままです。
影を付けるとすこしスクロールがもたつくかもしれませんので、ないほうがいいかもしれません。不要なら "none" もしくは "" としてください。
### "item-padding-left" / "****-right" / "****-top" / "****-bottom" …… 各アイテム内の余白
「見開き」の内側、EPUB 内の各 HTML が描画される領域までの余白です。数値の単位はすべて pxピクセル
グチですが……ホントは全部 0 でいいはずじゃないかと思うんです。EPUB 内の CSS で作者が制御できるなら、その方がいいはずだから。でも、世間には制御不能な余白をつけるリーディングシステムも多く、そうしたリーディングシステムに合わせて、余白を設定していないか狭めにしている EPUB はかなり多いです。この項目はそのためにあります。
EPUB 内の HTML に適用された背景色・背景画像もこの余白に反映されるように処理しています。ただし、本が固定レイアウトのときは無視され、ビビによる余白調整は行われません。
項目の説明3:エクステンション
----------------------------------------------------------------------------------------------------
ビビには、連携プログラムを追加して機能を拡張できる仕組みが用意されています。こういう仕組みは一般にプラグイン、エクステンション、機能拡張などといわれますが、ビビではエクステンションと呼ぶことにしました(ビビは女の子なので、アクセサリっぽいのがいいでしょう?)。
### エクステンションの基本
たとえば、example という名前のあたらしいエクステンションを手に入れたとします。そのエクステンションが example/script.js というフォルダ構成になっていれば、まず、example フォルダを bibi/extensions/ フォルダに入れます。
次に、プリセットファイル内の "extensions" で始まる行の次の行に、
```
{ "src": "../extensions/example/script.js" },
```
……と書き足します。"src" に指定するのは、そのプリセットファイルからの相対パスですbookshelf ディレクトリの項目で説明したのと同じように、bibi/extensions 以外のフォルダに置いたファイルや、許可されていれば別サーバを指定することもできます)
すると、ビビは起動時にそのエクステンションを追加で読み込み、エクステンションの機能が有効になります。
配布時にいくつか同梱されていますが、これらはどれも、必要に応じて自動で読み込まれるか、必要だと思う人が自分で有効化すればよいようにデフォルトでは読み込まないようにしてあるか、どちらかです。以下、同梱エクステンションについて説明します。
### "Unzipper" …… 展開していない(= Zip アーカイブ済みのEPUB を扱えるようにする
必要に応じて自動的に読み込まれる特殊なエクステンションです。
EPUB は ZIP フォーマットでアーカイブされており、ブラウザはふつうは ZIP アーカイブの内部にあるファイルを扱えませんが、このエクステンションによって、ビビはアーカイブ状態の EPUB も扱えるようになります。
受信したパソコンスマートフォンでビビが展開して処理する必要があるため、EPUB のファイルサイズが 10MB を超えるあたりから、読み始められるまでの処理時間の長さが顕著になってきます。そもそも重くて転送時間のかかるファイルを受信した上でにさらに展開処理が発生するので、仕方のないことです。また、古くて非力なスマートフォンなどでは、展開の処理負荷で表示以前にビビが止まってしまうこともあります。
ただし最近の改善によって、軽い本の場合は、展開済みの各ファイルをバラバラにダウンロードするよりも読み込みが効率化されて、高速・低負荷になる場合もあります。一度表示してしまえば動作速度に大きな差はありません。
ちょっと前まで、ビビを使って本を公開するときには、あらかじめ展開しておくことをおすすめしていました。が、Internet Explorer でも展開できるようになり、全般的に速度も改善し、場合によっては Zip のままのほうが速いこともあるので、「予め展開しておくほうが速い場合が多いですよ」程度の推奨に緩めることにします。
数年前のビビ開発初期はむしろアーカイブ状態のままでしか扱えなかったくらいビビの基本的な機能で、また、圧縮ファイルをドラッグ&ドロップで開けるのも、自作 EPUB のプレビューなどに便利なビビのメリットです。
### "Analytics" …… Google Analytics でユーザの行動を分析できるようになる
本をウェブで公開するとなると、どれだけの人が再生ボタンをクリックしたか、目次のどの項目がクリックされたか、最後まで読んだか、などなど、気になってくると思います。これらを、Google Analytics のイベントトラッキング機能を使って記録できるようにします。
Google Analytics の基本機能として同時に記録される OS や アクセス元言語圏などなども合わせて、読まれた状況をさまざまに分析できるようになります。
有効化する際には、"src" に加えて "tracking-id" という値で Google Analytics のトラッキング ID書式UA-XXXXXXXX-Xを書き足す必要があります。
現在記録されるのは、下に挙げるユーザ行動です。ほかに記録・分析したいことがあれば、作者にご要望をお寄せください。
* 再生ボタンのクリック/タップ
* 目次項目のクリック/タップ
* 最後のページの表示
最近、ビビを使ったお仕事の中で、非常にたくさんの情報を記録する独自拡張を開発しました。そのクライアントのご厚意で、処理自体はオープンソース化するご許可をいただいていますので、そのうち、大きく拡張するかもしれません。
### "EPUBCFI" …… EPUBCFI 仕様の位置・範囲指定を利用できるようにする
EPUBCFI は、複数ファイルで構成される EPUB 内の、特定ファイルの特定段落の何文字目から何文字目、といった位置・範囲を指定することができる仕組みです。「これこれについてはこの本のここにかいてあります」といったリンクで人に伝えたりしやすくなります。論文の引用などにも使えますね。
EPUB ビューワは EPUBCFI に対応していることが望ましい、ということになっており、実際うまくつかえば便利なのでビビも部分的に対応してみたのですが……書式が「人間の読み書きできるもんじゃねえ」という感じだからか、EPUBCFI 仕様自体があまりつかわれていません。このプラグインも、仕様に用意された機能の完全対応は諦めて、位置の指定のみに対応して開発が止まっています(範囲指定はごく部分的にしか扱えません)。
ビビには、EPUBCFI を使わなくても本の途中を指定して開く機能を別につけてあります。それは EPUB の基本仕様ではなく独自機能ですが、もうすこしわかりやすく直感的な書式で指定できるようになっています。別途解説予定ですので、おたのしみに(といってぜんぜん解説しないままですみません)
項目の説明4:高度な設定(普通の使い方をするかぎり変更しないことをおすすめします)
----------------------------------------------------------------------------------------------------
"trustworthy-origins" …… bookshelf ディレクトリの場所や Message の送信元として許可するオリジン
必要であれば外部のオリジンを列挙することで、bookshelf を外部サーバに置いたり、別サーバからの Message で動作指示を受け取ったりできるようになります。なにも書かなくても、ビビ自体が置かれたサーバのオリジンは許可されます。
たとえばここに "https://dl.dropboxusercontent.com" を加えれば、自分のウェブサーバに設置したビビから Dropbox の公開フォルダに置いた EPUB を読み込んだりできるようになります。ただし、このオリジンはどんな Dropbox ユーザの公開フォルダの URL でも共通なので、まったく知らない誰かが、その人の Dropbox 公開フォルダに置いた EPUB を、あなたのビビで、表示させることもできるようになります。
十分に注意して、ドキュメントルート以下すべてが自分の管理下にあるサーバのみを加えるのがいいと思いますその条件では、Dropbox も除外されます)。
もちろん、その外部サーバがビビの置かれたサーバまたはすべての外部サーバからのリクエストを許可していなければ、ここに加えても読み込むことはできません。

206
reader/presets/default.js Normal file
View file

@ -0,0 +1,206 @@
Bibi.preset({
//==============================================================================================================================================
//-- Bookshelf
//----------------------------------------------------------------------------------------------------------------------------------------------
"bookshelf" : "../reader/bookshelf", // Relative path from this preset file to the bookshelf directory. "/" at the end is ignored. (To use a path begins with "http(s)://", read <01> at the bottom of this preset file.)
//==============================================================================================================================================
//-- Behavior
//----------------------------------------------------------------------------------------------------------------------------------------------
"reader-view-mode" : "paged", // "paged" or "horizontal" or "vertical" ("paged" is for flipping, "horizontal" and "vertical" are for scrolling)
"full-breadth-layout-in-scroll" : "no", // "yes" or "no" or "desktop" or "mobile"
"fix-reader-view-mode" : "no", // "yes" or "no" or "desktop" or "mobile"
"keep-settings" : "yes", // "yes" or "no" or "desktop" or "mobile"
"resume-from-last-position" : "yes", // "yes" or "no" or "desktop" or "mobile"
"autostart" : "yes", // "yes" or "no" or "desktop" or "mobile"
"autostart-embedded" : "no", // "yes" or "no" or "desktop" or "mobile" (It takes priority over "autostart" when the book is embedded in a webpage)
"start-embedded-in-new-window" : "mobile", // "yes" or "no" or "desktop" or "mobile" (It is used only when "autostart" (or "autostart-embedded") is NOT enabled)
//==============================================================================================================================================
//-- UI / Design
//----------------------------------------------------------------------------------------------------------------------------------------------
"use-menubar" : "yes", // "yes" or "no" or "desktop" or "mobile"
"use-full-height" : "yes", // "yes" or "no" or "desktop" or "mobile". If "use-menubar" is interpreted as "no", "use-full-height" is always treated as "yes".
"use-arrows" : "yes", // "yes" or "no" or "desktop" or "mobile"
"flipper-width" : 0.25, // Number of ratio (less than 1) or pixel (1 or greater)
"use-keys" : "yes", // "yes" or "no" or "desktop" or "mobile"
"use-slider" : "yes", // "yes" or "no" or "desktop" or "mobile"
"flip-pages-during-sliding" : "yes", // "yes" or "no" or "desktop" or "mobile"
"use-nombre" : "yes", // "yes" or "no" or "desktop" or "mobile"
"use-font-size-changer" : "yes", // "yes" or "no" or "desktop" or "mobile"
"base-font-size" : "auto", // Number of pixel or "auto"
"font-size-scale-per-step" : 1.25, // Number of scale
"use-loupe" : "desktop", // "yes" or "no" or "desktop" or "mobile" (Note: Loupe buttons will not appear in touch-devices even if it is set "yes" or "mobile".)
"loupe-max-scale" : 4, // Number of scale (greater than 1)
"loupe-scale-per-step" : 1.6, // Number of scale (greater than 1, less than or equal to "loupe-max-scale")
"zoom-out-for-utilities" : "yes", // "yes" or "no" or "desktop" or "mobile"
"use-history" : "yes", // "yes" or "no" or "desktop" or "mobile"
"max-history" : 19, // Number (0-19). If larger than 19, treated as 19. If 0, "use-history" is treated as "no".
"use-bookmarks" : "yes", // "yes" or "no" or "desktop" or "mobile"
"max-bookmarks" : 3, // Number (0-9). If larger than 9, treated as 9. If 0, "use-bookmarks" is treated as "no" (but old data is kept in localStorage).
"orientation-border-ratio" : 1 * 2 / 1.5, // Number (Width per Height)
"ui-font-family" : "", // CSS font-family value as "'Helvetica', sans-serif" or ""
"item-padding-left" : 24, // Number of pixel (It affects only for reflowable books.)
"item-padding-right" : 24, // Number of pixel (It affects only for reflowable books.)
"item-padding-top" : 48, // Number of pixel (It affects only for reflowable books.)
"item-padding-bottom" : 24, // Number of pixel (It affects only for reflowable books.)
"spread-gap" : 48, // Number of pixel (It affects only in paged view mode.)
"spread-margin" : 0, // Number of pixel
"fix-nav-ttb" : "no", // "yes" or "no" or "desktop" or "mobile"
"on-doubletap" : "",
"on-tripletap" : "",
"content-draggable" : [true, true], // [<TF>, <TF>]
"orthogonal-arrow-keys" : ["move", "switch"], // [<S1>, <S2>]
"orthogonal-edges" : ["utilities", "utilities"], // [<S1>, <S2>]
"orthogonal-touch-moves" : ["move", "switch"], // [<S1>, <S2>]
"orthogonal-wheelings" : ["move", "across"], // [<S1>, <S3>]
// ^ Each item of the arrays corresponds to the view mode:
// * the first is for the "paged" view mode, and
// * the second is for the "horizontal"/"vertical" scroll view modes.
// ^ Types of the values:
// * <TF>: true or false
// * <S1>: "" (ignore) or "utilities" or "move"
// * <S2>: "" (ignore) or "utilities" or "move" or "switch"
// * <S3>: "" (ignore) or "utilities" or "move" or "switch" or "across"
//==============================================================================================================================================
//-- Extensions
//----------------------------------------------------------------------------------------------------------------------------------------------
// "src" is relative path from this preset file to the JavaScript file of the extension.
// "id" must be defined in each extension file.
"extensions": [
// { "src": "../extensions/FOLDER-NAME-IF-EXISTS/FILE-NAME.js" }, // <THIS LINE IS AN EXAMPLE>
""],
//==============================================================================================================================================
//-- Extra
//----------------------------------------------------------------------------------------------------------------------------------------------
"website-name-in-title" : "", // "" or name of your website replaces string "Bibi" in <title>.
"website-name-in-menu" : "", // "" or name of your website appears in setting-menu as a link. (Requires "website-href")
"website-href" : "", // "" or URL of your website to be used for the link in setting-menu. (Requires "website-name-in-menu")
"remove-bibi-website-link" : true, // true or false (if true, the link to Bibi Website is not to be added in setting-menu)
//==============================================================================================================================================
//-- System
//----------------------------------------------------------------------------------------------------------------------------------------------
"extract-if-necessary" : [".epub", ".zip"], // File extensions of the book specified in URL, which you want Bibi to try to extract first. (More info is <02> at the bottom of this preset file.)
"default-page-progression-direction" : "ltr", // "ltr" or "rtl". Most of EPUBs have right property in itself, but....
"accept-local-file" : "yes", // "yes" or "no" or "desktop" or "mobile". (If it is enabled, Bibi prepares UI for loading files. Conditions for acceptance are <03> at the bottom of this preset file.)
"accept-bibizine" : true, // true or false (If true, Bibi accepts EPUB-like bibiZine formated book. If you are interested in it, please contact the author)
"accept-blob-converted-data" : true, // true or false (If true, Bibi accepts BLOB object converted from a EPUB File. If you are interested in it, please contact the author)
"accept-base64-encoded-data" : true, // true or false (If true, Bibi accepts Base64 string encoded from a EPUB File. If you are interested in it, please contact the author)
"pagination-method" : "auto", // "auto" or "x". (It affects only for vertical-text reflowable books. More info is <04> at the bottom of this preset file.)
"allow-placeholders" : true, // true or false. (true is highly recommended.)
"prioritise-fallbacks" : false, // true or false (If true, Bibi uses <item> at the end of the fallback-chain.)
//==============================================================================================================================================
//-- DANGER ZONE
//----------------------------------------------------------------------------------------------------------------------------------------------
// If you publish Bibi online,
// * keep these options as default, or/and
// * keep your Bibi and website not to open files which you can not guarantee its security.
//----------------------------------------------------------------------------------------------------------------------------------------------
/* !!!! BE CAREFUL !!!! */ "allow-scripts-in-content" : true, // true or false (false is recommended).
// If you change its value `true`, Bibi does not remove scripts natively-included in EPUB.
// It makes Bibi to be able to open EPUBs including useful scripts.
// But on the other hand, it may also allow XSS of malicious EPUB in some cases.
/* !!!! BE CAREFUL !!!! */ "trustworthy-origins" : [], // origins you trust other than where this Bibi is installed. (blank is recommended).
// If you add origins to it, Bibi is made to open not only EPUBs in the same origin as Bibi itself is installed but also EPUBs in remote origins.
// It is useful for some cases like that you want to set directory on the other storaging server as "bookshelf".
// But note that not to set an origin where someone else also can publish files.
// If you do so, someone else can publish one's EPUB as it is on your website, and it may also allow XSS of malicious EPUB in some cases.
/*
//==============================================================================================================================================
## <01> You can use a path begins with "http(s)://" for "bookshelf" option in cases of the below:
* The origin of the path defined in the "bookshelf" option is same as the origin of this Bibi.
* [OR] The origin is included in "trustworthy-origins" option.
- [AND] The origin allows COR from the origin of this Bibi.
## <02> Bibi tries to extract at first in cases of the below:
* The "extract-if-necessary" option includes "*".
* [OR] The "extract-if-necessary" option includes one or more file extensions.
- [AND] The book name specified as a value of the `book` (or `zine`) query in URL has a file extension.
- [AND] The file extension of the book name is included in the "extract-if-necessary" option.
* [OR] The "extract-if-necessary" option is "".
- [AND] The book name specified as a value of the `book` (or `zine`) query in URL has no file extension.
### Note:
* If Bibi failed to extract it, automatically tries to load as a folder (directory).
* The "extract-if-necessary" option affects also as conditions for acceptance of local file. Read <03> at the next.
## <03> Bibi accepts user's local file in cases of the below:
* The file is an EPUB.
- [AND] The extension of the file is ".epub".
- [AND] The "extract-if-necessary" option includes ".epub" or "*".
- [AND] The MIME-Type sent from the browser is "application/epub+zip".
* [OR] The file is a bibiZine.
- [AND] The extension of the file is ".zip".
- [AND] The "extract-if-necessary" includes ".zip" or "*".
- [AND] The MIME-Type sent from the browser is "application/zip", "application/x-zip", or "application/x-zip-compressed".
### Note:
* Extension of the file is required even if "extract-if-necessary" is "" (or includes "*").
## <04> Setting "x" for "pagination-method" option
It affects only for reflowable vertical-text books.
If "x" is set for "pagination-method", Bibi tries to use an experimental layout method on modern web-browsers.
It realizes more prettier layout for simple books like novels.
But sometime causes bad result for some books with figures or floating objects.
//==============================================================================================================================================
*/
"bibi": "EPUB Reader on your website." });

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,8 @@
/*!
*
* # Polyfill for Bibi: text-encoding-utf-8
*
* * Consists of:
* - text-encoding-utf-8 : by Erik Arvidsson - https://github.com/arv/text-encoding-utf-8 / Released into the public domain under the Unlicense - https://github.com/arv/text-encoding-utf-8/blob/master/LICENSE.md
*
*/!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=41)}({1:function(e,t,r){"use strict";function n(e){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(e,t,r){return t<=e&&e<=r}function i(e){if(void 0===e)return{};if(e===Object(e))return e;throw TypeError("Could not convert argument to dictionary")}r.d(t,"a",(function(){return s}));function f(e){this.tokens=[].slice.call(e)}f.prototype={endOfStream:function(){return!this.tokens.length},read:function(){return this.tokens.length?this.tokens.shift():-1},prepend:function(e){if(Array.isArray(e))for(var t=e;t.length;)this.tokens.unshift(t.pop());else this.tokens.unshift(e)},push:function(e){if(Array.isArray(e))for(var t=e;t.length;)this.tokens.push(t.shift());else this.tokens.push(e)}};function u(e,t){if(e)throw TypeError("Decoder error");return t||65533}function s(e,t){if(!(this instanceof s))return new s(e,t);if("utf-8"!==(e=void 0!==e?String(e).toLowerCase():"utf-8"))throw new Error("Encoding not supported. Only utf-8 is supported");t=i(t),this._streaming=!1,this._BOMseen=!1,this._decoder=null,this._fatal=Boolean(t.fatal),this._ignoreBOM=Boolean(t.ignoreBOM),Object.defineProperty(this,"encoding",{value:"utf-8"}),Object.defineProperty(this,"fatal",{value:this._fatal}),Object.defineProperty(this,"ignoreBOM",{value:this._ignoreBOM})}function a(e){var t=e.fatal,r=0,n=0,i=0,f=128,s=191;this.handler=function(e,a){if(-1===a&&0!==i)return i=0,u(t);if(-1===a)return-1;if(0===i){if(o(a,0,127))return a;if(o(a,194,223))i=1,r=a-192;else if(o(a,224,239))224===a&&(f=160),237===a&&(s=159),i=2,r=a-224;else{if(!o(a,240,244))return u(t);240===a&&(f=144),244===a&&(s=143),i=3,r=a-240}return r<<=6*i,null}if(!o(a,f,s))return r=i=n=0,f=128,s=191,e.prepend(a),u(t);if(f=128,s=191,r+=a-128<<6*(i-(n+=1)),n!==i)return null;var l=r;return r=i=n=0,l}}s.prototype={decode:function(e,t){var r;r="object"===n(e)&&e instanceof ArrayBuffer?new Uint8Array(e):"object"===n(e)&&"buffer"in e&&e.buffer instanceof ArrayBuffer?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):new Uint8Array(0),t=i(t),this._streaming||(this._decoder=new a({fatal:this._fatal}),this._BOMseen=!1),this._streaming=Boolean(t.stream);for(var o,u=new f(r),s=[];!u.endOfStream()&&-1!==(o=this._decoder.handler(u,u.read()));)null!==o&&(Array.isArray(o)?s.push.apply(s,o):s.push(o));if(!this._streaming){do{if(-1===(o=this._decoder.handler(u,u.read())))break;null!==o&&(Array.isArray(o)?s.push.apply(s,o):s.push(o))}while(!u.endOfStream());this._decoder=null}return s.length&&(-1===["utf-8"].indexOf(this.encoding)||this._ignoreBOM||this._BOMseen||(65279===s[0]?(this._BOMseen=!0,s.shift()):this._BOMseen=!0)),function(e){for(var t="",r=0;r<e.length;++r){var n=e[r];n<=65535?t+=String.fromCharCode(n):(n-=65536,t+=String.fromCharCode(55296+(n>>10),56320+(1023&n)))}return t}(s)}}},41:function(e,t,r){"use strict";r.r(t);var n=r(1);self.TextDecoder=n.a}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

58
templates/app.py Normal file
View file

@ -0,0 +1,58 @@
from flask import Flask, render_template, request, send_from_directory
import os
app = Flask(__name__)
EPUBS_DIR = {
'default': './reader/bookshelf/'
}
@app.route('/')
def index():
return render_template('index.html')
@app.route('/search', methods=['GET'])
def search():
query = request.args.get('searchQuery', '').lower()
matching_files = []
for _, dir_path in EPUBS_DIR.items():
all_files = [f for f in os.listdir(dir_path) if f.lower().endswith('.epub')]
matching_files += [f for f in all_files if query in f.lower()]
# Render the results as HTML
results_html = "".join([f'<li><a href="#" onclick="loadEpubInBibi(\'/reader/bookshelf/{file}\'); return false;">{file}</a></li>' for file in matching_files])
return results_html
@app.route('/reader/bibi/<path:subpath>')
def serve_bibi_assets(subpath):
# This will serve all of Bibi's assets, such as JavaScript, CSS, etc.
return send_from_directory('./reader/bibi', subpath)
@app.route('/reader/bookshelf/<filename>')
def serve_epub(filename):
return send_from_directory('./reader/bookshelf', filename)
@app.route('/reader')
def serve_bibi_reader():
book_path = request.args.get('book')
# You might want to do some checks on `book_path` for security reasons.
return send_from_directory('./reader/bibi', 'index.html')
@app.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(app.root_path, './favicon.ico'),
'favicon.ico', mimetype='image/vnd.microsoft.icon')
if __name__ == "__main__":
app.run(debug=True)

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

BIN
templates/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

47
templates/index.html Normal file
View file

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>E Reader Upgrade</title>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" href="/favicon.ico" type="image/x-icon"></link>
<link rel="shortcut icon" href="../favicon.ico" type="image/x-icon">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
<script src="https://unpkg.com/htmx.org"></script>
</head>
<body>
<section>
<nav class="navbar navbar-light bg-light justify-content-between">
<a class="navbar-brand">Search for a book!</a>
<form class="form-inline">
<input type="text"
hx-get="/search"
hx-params="searchQuery:val"
hx-trigger="keyup delay:300ms"
hx-target="#resultsContainer"
placeholder="Search for EPUBs...">
<div id="resultsContainer"></div>
</form>
</nav>
</section>
<section>
<iframe id="bibi-frame" src="reader/bibi/index.html" width="100%" height="600px" frameborder="0"></iframe>
</section>
<script>
function loadEpubInBibi(epubUrl) {
document.getElementById('bibi-frame').src = "reader/bibi/index.html?book=" + epubUrl;
}
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,8 @@
/*!
*
* # Bibi Extension: Analytics ()
*
* * © Satoru Matsushima - https://bibi.epub.link or https://github.com/satorumurmur/bibi
* * Open source under the MIT License - https://github.com/satorumurmur/bibi/blob/master/LICENSE
*
*/!function(e){var t={};function n(i){if(t[i])return t[i].exports;var r=t[i]={i:i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(i,r,function(t){return e[t]}.bind(null,r));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=16)}({16:function(e,t){Bibi.x({id:"Analytics",description:"Utilities for Tracking and Logging with Google Analytics.",author:"Satoru Matsushima (@satorumurmur)",version:"1.2.0-demo"})((function(){"use strict";var e,t,n,i,r,a;"string"==typeof this["tracking-id"]&&this["tracking-id"]&&(e=window,t=document,n="script",i="ga",e.GoogleAnalyticsObject=i,e.ga=e.ga||function(){(e.ga.q=e.ga.q||[]).push(arguments)},e.ga.l=1*new Date,r=t.createElement(n),a=t.getElementsByTagName(n)[0],r.async=1,r.src="//www.google-analytics.com/analytics.js",a.parentNode.insertBefore(r,a),ga("create",this["tracking-id"],"auto",{allowLinker:!0}),ga("require","linker"),ga("linker:autoLink",S["trustworthy-origins"].reduce((function(e,t){return e.push(t.replace(/^\w+:\/\//,""))}),[])),E.add("bibi:loaded-navigation",(function(){return sML.forEach(I.Panel.BookInfo.Navigation.querySelectorAll("a"))((function(e){return e.addEventListener("click",(function(){ga("send",{hitType:"event",eventCategory:"Bibi: Jumped by Navigation",eventAction:B.Path,eventLabel:e.innerHTML.replace(/<[^>]*>/g,"")+' - "'.concat(e.getAttribute("data-bibi-original-href"),'"'),eventValue:void 0})}))}))})),E.add("bibi:played:by-button",(function(){ga("send",{hitType:"event",eventCategory:"Bibi: Played by Button",eventAction:B.Path,eventLabel:S["parent-uri"]?"on: "+S["parent-uri"].replace(/#.+$/,""):"",eventValue:void 0})})),E.add("bibi:scrolled",(function(){if(100!=R.Current.Percent)return!1;ga("send",{hitType:"event",eventCategory:"Bibi: Read Through",eventAction:B.Path,eventLabel:Date.now()-Bibi.TimeOrigin,eventValue:void 0})})))}))}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,8 @@
/*!
*
* # # Bibi Extension: Unaccessibilizer ("What a...")
*
* * Reluctantly coded by Satoru Matsushima - https://bibi.epub.link or https://github.com/satorumurmur/bibi
* * Released into the public domain under the Unlicense - http://unlicense.org/UNLICENSE
*
*/!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=27)}({27:function(e,t){Bibi.x({id:"Unaccessibilizer",description:"What a...",author:"Satoru Matsushima (@satorumurmur)",version:"1.2.0"})((function(){"use strict";var e=this,t=["-webkit-","-moz-","-ms-",""];E.bind("bibi:postprocessed-item",(function(n){"prevent"==e["select-elements"]&&t.forEach((function(e){["user-select","user-drag"].forEach((function(t){n.Body.style[e+t]="none"}))})),"prevent"==e["save-images"]&&sML.forEach(n.Body.querySelectorAll("img, svg, image"))((function(e){t.forEach((function(t){["user-select","user-drag"].forEach((function(n){e.style[t+n]="none"})),O.Touch&&(e.style[t+"pointer-events"]="none")})),e.draggable=!1,e.addEventListener("contextmenu",O.preventDefault)})),"prevent"==e["use-contextmenu"]&&n.contentDocument.addEventListener("contextmenu",O.preventDefault)}))}))}});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html id="bibi">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>This E-Book is Published with Bibi | EPUB Reader on your website.</title>
<!-- # Bibi | EPUB Reader on your website. : © Satoru Matsushima - https://bibi.epub.link or https://github.com/satorumurmur/bibi / Licensed under the MIT License - https://github.com/satorumurmur/bibi/blob/master/LICENSE -->
<!-- 「わたしのことは『ビビ』と呼んでください。『ビビ』はわたしの名前なんです」 —— エレクトラ・パブリケーヌ『ビビのみぎくるぶし』 -->
<!-- 「まあ! それじゃあやっぱり、『ビビ』はわたしの“名前”だったのですね?」 —— ソフィア・パインアイランド『ビビさんたちのこと』 -->
<!-- 「このあたりにビビさんという人がいると聞いて来たのですが、あなたですか?」 —— ビビ・ララルー『ポケットに眼鏡』 -->
<link id="bibi-style" rel="stylesheet" href="/reader/bibi/resources/styles/bibi.css" />
<link id="bibi-dress" rel="stylesheet" href="/reader/bibi/wardrobe/everyday/bibi.dress.css" />
<script id="bibi-script" src="/reader/bibi/resources/scripts/bibi.js"></script>
<script id="bibi-preset" src="/reader/bibi/presets/default.js" data-bibi-bookshelf=""></script>
</head>
<body data-bibi-book="">
<div id="bibi-info">
<h1>This E-Book is Published on the Web with Bibi | EPUB Reader on your website.</h1>
<input type="text"
hx-get="/search"
hx-params="searchQuery:val"
hx-trigger="keyup delay:300ms"
hx-target="#resultsContainer"
placeholder="Search for EPUBs...">
<div id="resultsContainer"></div>
</div>
<div id="bibi-book-data" data-bibi-book-mimetype="application/epub+zip">
</div>
</body>
</html>

View file

@ -0,0 +1,286 @@
プリセット指定マニュアル
====================================================================================================
かんたんですが、プリセットについて解説します。今後マニュアルにまとめる計画ですので、読みづらさはしばしご容赦ください。
※ ときどき、実際のプリセットファイルの内容に追いついていない場合があります。申し訳ありませんがご容赦ください(もしできればご指摘ください)。
プリセットとは / つかいかた
----------------------------------------------------------------------------------------------------
プリセットファイルとは、リーダとしてのデフォルト挙動やレイアウトの初期設定を外部化したテキストファイルです。これを編集することでビビの振る舞いをカスタマイズすることができます。
bibi/presets フォルダに入れて使うのが基本ですが、じつはどこか別の場所でも(余所のサーバでも)かまいません。
配布状態の bibi/index.html は bibi/presets/default.js を呼び出しています。設定を変更したいときは、この default.js を直接編集してもいいのですが、default.js を複製・リネームして別のプリセットを作成した上で、bibi/index.html から呼び出すファイルをそちらに変更することをお勧めします。
bibi/index.html も、たとえば bibi/the-great-book.html のように複製・リネームして使い分けることができるので、本ごとに HTML とプリセットの組み合わせを使い分けることができます。
カスタマイズについて、はじめに
----------------------------------------------------------------------------------------------------
以下、挙動をカスタマイズできる具体的な指定について説明しますが、多くは、対象とする EPUB によって一長一短があります。だからこそ、ビビ側で一律に固定せず、プリセットとして編集可能にしてあるというわけです。
読者自身が読みながらボタンで変更できる項目もありますが、ご自身で作成した EPUB を読者に見せたい場合や、ご自身で見た目をカスタマイズした Bibi を読者に使ってもらいたい場合など、EPUB に合わせたスタイルやあなたらしいスタイルを予めプリセットで指定しておくと、きっとステキだと思います。
### この文書内で使用される用語の定義
アイテムとは、表示されるファイルひとつひとつのことです。
「見開き」とは、アイテムをつつむブロックです。リフロー指定のアイテムはそれ1つだけで「見開き」を構成します。固定レイアウトで左右ペアが作られている場合は、その2つが1つの「見開き」に入ります。
「長さ」は、進行方向サイズのことです。水平方向に進行しているときは左右幅、垂直なら上下高を指します。同様に「広さ」は、水平進行なら上下高、垂直なら左右幅です。そして、それらの数値が小さい状態を「短い」「狭い」ということにします。
これらの定義は EPUB もしくは電子書籍について一般に使われているわけではなく、あくまでビビ用語だと思ってください。
項目の説明1:基本設定
----------------------------------------------------------------------------------------------------
ビビのごく基本的な振る舞いを制御します。
### "bookshelf" …… bookshelf ディレクトリまでのパス
そのプリセットファイルからみた bookshelf ディレクトリのパスです。基本的には、同じウェブサーバ内の bookshelf ディレクトリまでの相対パス・ルート相対パス("../../bibi-bookshelf/" や "/bibi-bookshelf/" など)を記述します。
高度な設定として、クロスオリジンリクエストが許可されているサーバの bookshelf ディレクトリを http(s):// から書くこともできます。ただし、そのサーバのオリジンは、この文書の最後に述べる "trustworthy-origins" に含まれていなければなりません。
### "reader-view-mode" …… 表示モードの初期値(ページめくり・横スクロール・縦スクロール)
* "paged" を指定するとページめくりモード、
* "horizontal" なら横スクロールモード、
* "vertical" なら縦スクロールモード
……で表示を開始します。読者は随時変更できるので、あくまで最初にどのモードで表示するか、ということです。
### "fix-reader-view-mode" …… 表示モードを固定して変更を禁止するかどうか
"yes", "no", "desktop", "mobile" の4つから選べます。
この項目の初期値は "no" で、そのままにしておくことをオススメします。
"yes" にするといつも、"desktop" ならパソコンのとき、"mobile" ならスマートフォンのときに、ユーザが表示モードを変更できなくなり、変更ボタンも表示されなくなります。コンテンツの性質によって禁止したほうがユーザ体験を向上させられるときに使います。
以降、"yes", "no", "desktop", "mobile" の4つから選択する形式の指定がいくつか登場しますが、切り替え条件はすべて同じです
### "single-page-always" …… 2ページの見開きにせず1ページで表示させるかどうか
"yes", "no", "desktop", "mobile" から選択してください。
初期値は "no" で、その場合、横書きの本をページめくりモードまたは横スクロールモードで表示したとき、画面の横幅に余裕があれば、1画面あたり2ページの見開きで表示します。
"yes" にするといつも、"desktop" ならパソコンのとき、"mobile" ならスマートフォンのときに、画面の横幅が広くても常に1画面あたり1ページで表示させます。
### "autostart" …… 貼り付け時、再生ボタンのクリックを待たずに自動的に本を開くかどうか
ビビはウェブページに埋め込んで使えますが、データ量の大きい本を自動再生すると、親ウェブページの読み込み処理を遅くしてしまう場合があります。とはいえ、軽い本なら自動再生してしまいたいかもしれませんし、パソコンとスマートフォンで挙動を切り替えたいこともあるでしょう。そこでこれも、"yes", "no", "desktop", "mobile" の値で、切り替えられるようにしました。
"yes" なら、どんなときもいつも自動再生します。"no" は逆に、必ず再生ボタンのクリック/タップを必要とします。"desktop" は、パソコンなら自動再生、スマートフォンでは再生ボタンの操作が必要になります。"mobile" は "desktop" の逆です。
### "start-in-new-window" …… 貼り付け状態で再生ボタンを押したとき、新しいウィンドウで開くかどうか
貼り付け時、"autostart" の設定によって再生ボタンが表示された場合、その再生ボタンをクリック/タップしたとき、そのまま貼り付け状態で再生するか、新しいウィンドウで開くかどうかの設定です。これも "yes", "no", "desktop", "mobile" の4首から選べるようになっています。
"yes" はいつも別ウィンドウ、"no" はかならず埋め込み状態、"desktop" はパソコンなら別ウィンドウでスマートフォンなら埋め込み、"mobile" は "desktop" の逆、です。
ごく最近まで、ビビはいつも "mobile" と同じ挙動でした。スマートフォンでも埋め込んだまま起動したいという要望はちらほらとあったのですが、読むのに十分なパフォーマンスが出なかったためです。
が、どうやらそろそろまともに動くようになったようなので、任意で選べるようにしました。ただ、スマートフォンの場合、狭い画面内のさらに小さなフレームで開くと読者に不便を強いるかもしれません。よく気をつけて使ってみてください(ユーザは、メニュー内のボタンからいつでも別ウィンドウで開きなおせます。とはいえ)。
### "use-nombre" …… ページ番号・パーセントインジケータを使うか
ページをめくったときなどに、ビビは現在のページと全体のうちのパーセンテージを表示します。これを使うかどうか決められます。
これも "yes", "no", "desktop", "mobile" の設定で、初期値は "yes" です。
### "use-slider" …… ページスライダを使うか
画面の真ん中あたりをクリック/タップすると下端に出てくるページスライダの使用有無です。本の中の好きな位置にジャンプできる便利な UI で、有効になっていると、パソコンではページめくりモードのときに擬似的なスクロールバーの役割も兼ねます。
これも "yes", "no", "desktop", "mobile" の設定で、初期値は "yes" です。
### "use-arrows" …… 画面端のクリック/タップに反応するページめくり機能を使うか
ビビは画面左右にページめくり領域を用意して、クリック/タップで操作できるようになっています。ただ、特別なプログラムを組んで埋め込まれた親ページやアプリに独自の UI をつけて不要になったりしたときは、消せるようにしてあります。
これも "yes", "no", "desktop", "mobile" の設定で、初期値は "yes" です。これがないとめくれなくなってしまう場合がほとんどなので、基本的には "yes" のままをおすすめします。
### "use-keys" …… キーボード操作を受け付けるか
有効になっていると、キーボードのカーソルキーでもページ移動ができます。
これも "yes", "no", "desktop", "mobile" の設定で、初期値は "desktop" です。有効にしてもスマートフォンでは使えない機能なので、"desktop" か "no" をおすすめします。
### "use-cookie" …… 状態を Cookie に保存して次回開いたときに再現するか
有効になっていると、最後に開いていたときの表示モードとページ位置を保存して、次回も同じ本は同じ状態で開始します。
本の特定には、ビビのディレクトリとEPUB のメタファイルに書かれた本の IDidentifierの組み合わせが使われます。記録されるのは表示モードとページ位置だけで、この機能によってプライベートな情報が外部に漏れたりはしません。
これも "yes", "no", "desktop", "mobile" の設定で、初期値は "yes" です。パソコンとスマートフォンで挙動を分ける理由は特にないと思いますので、"yes" か "no" かで選ぶのがよいと思われます。
### "cookie-expires" …… Cookie を保存するときの有効期限(単位:ミリ秒)
上の "use-cookie" が有効になっている場合に保存される Cookie の有効期限です。
単位はミリ秒1/1000 秒)で、初期値は 1000 * 60 * 60 * 24 * 31。これは 1000 × 60 × 60 × 24 × 31 という意味で、最初の 1000 は 1/1000秒が1000なので1秒、つづけて、その60倍で1分、その60倍で1時間、その24倍で1日、その31倍なので、つまり31日間となっていますあらかじめ計算した値の 259200000 と書いておいても同じことですが、バラしたほうがわかりやすいかな、と)。
どんなに長くても1年以内にしておくのがいいと思います。たとえば読んでいる途中のリロードだけに対応したいなら数分程度でもいいのです。いろいろ試してみてください。
### "ui-font-family" …… 目次やその他の基本 UI のフォント指定
たとえば、台湾では句読点をボックス中央に配置したフォントが一般的なのでそういうフォントを使いたい、などなどの事情があるとき、デフォルトフォントを指定できます。値は CSS の font-family そのままです。
これは本文には影響しません。あくまで、ビビの UI として表示される目次などのフォントです。
項目の説明2:本の中身の表示カスタマイズ
----------------------------------------------------------------------------------------------------
### "book-background" …… 「見開き」の下の背景
「見開き」の白い箱のうしろに、暗い色のエリアがあります。そのスタイルを変更できます。値は CSS の background そのままです。つまり背景画像なども使えます。
### "spread-gap" …… 「見開き」と「見開き」の間隔
縦/横スクロールモード表示時の、「見開き」同士の間隔です。単位は px。
最初と最後の「見開き」とウィンドウ端の距離は、この値にかかわらず、ウィンドウの真ん中に来るようにウィンドウ端との距離が調節されます。
### "spread-margin" …… 「見開き」とウィンドウの間隔
「見開き」とウィンドウの、「幅」方向(本の進行方向と垂直の軸)の間隔です。単位は px。
### "spread-border-radius" …… 「見開き」のカド丸設定
「見開き」の白い箱のカドを丸めることができます。CSS の border-radius に適用する値そのままです。
### "spread-box-shadow" …… 「見開き」に影を付けるなら CSS を
「見開き」の白い箱に影をつけられます。CSS の box-shadow に適用する値そのままです。
影を付けるとすこしスクロールがもたつくかもしれませんので、ないほうがいいかもしれません。不要なら "none" もしくは "" としてください。
### "item-padding-left" / "****-right" / "****-top" / "****-bottom" …… 各アイテム内の余白
「見開き」の内側、EPUB 内の各 HTML が描画される領域までの余白です。数値の単位はすべて pxピクセル
グチですが……ホントは全部 0 でいいはずじゃないかと思うんです。EPUB 内の CSS で作者が制御できるなら、その方がいいはずだから。でも、世間には制御不能な余白をつけるリーディングシステムも多く、そうしたリーディングシステムに合わせて、余白を設定していないか狭めにしている EPUB はかなり多いです。この項目はそのためにあります。
EPUB 内の HTML に適用された背景色・背景画像もこの余白に反映されるように処理しています。ただし、本が固定レイアウトのときは無視され、ビビによる余白調整は行われません。
項目の説明3:エクステンション
----------------------------------------------------------------------------------------------------
ビビには、連携プログラムを追加して機能を拡張できる仕組みが用意されています。こういう仕組みは一般にプラグイン、エクステンション、機能拡張などといわれますが、ビビではエクステンションと呼ぶことにしました(ビビは女の子なので、アクセサリっぽいのがいいでしょう?)。
### エクステンションの基本
たとえば、example という名前のあたらしいエクステンションを手に入れたとします。そのエクステンションが example/script.js というフォルダ構成になっていれば、まず、example フォルダを bibi/extensions/ フォルダに入れます。
次に、プリセットファイル内の "extensions" で始まる行の次の行に、
```
{ "src": "../extensions/example/script.js" },
```
……と書き足します。"src" に指定するのは、そのプリセットファイルからの相対パスですbookshelf ディレクトリの項目で説明したのと同じように、bibi/extensions 以外のフォルダに置いたファイルや、許可されていれば別サーバを指定することもできます)
すると、ビビは起動時にそのエクステンションを追加で読み込み、エクステンションの機能が有効になります。
配布時にいくつか同梱されていますが、これらはどれも、必要に応じて自動で読み込まれるか、必要だと思う人が自分で有効化すればよいようにデフォルトでは読み込まないようにしてあるか、どちらかです。以下、同梱エクステンションについて説明します。
### "Unzipper" …… 展開していない(= Zip アーカイブ済みのEPUB を扱えるようにする
必要に応じて自動的に読み込まれる特殊なエクステンションです。
EPUB は ZIP フォーマットでアーカイブされており、ブラウザはふつうは ZIP アーカイブの内部にあるファイルを扱えませんが、このエクステンションによって、ビビはアーカイブ状態の EPUB も扱えるようになります。
受信したパソコンスマートフォンでビビが展開して処理する必要があるため、EPUB のファイルサイズが 10MB を超えるあたりから、読み始められるまでの処理時間の長さが顕著になってきます。そもそも重くて転送時間のかかるファイルを受信した上でにさらに展開処理が発生するので、仕方のないことです。また、古くて非力なスマートフォンなどでは、展開の処理負荷で表示以前にビビが止まってしまうこともあります。
ただし最近の改善によって、軽い本の場合は、展開済みの各ファイルをバラバラにダウンロードするよりも読み込みが効率化されて、高速・低負荷になる場合もあります。一度表示してしまえば動作速度に大きな差はありません。
ちょっと前まで、ビビを使って本を公開するときには、あらかじめ展開しておくことをおすすめしていました。が、Internet Explorer でも展開できるようになり、全般的に速度も改善し、場合によっては Zip のままのほうが速いこともあるので、「予め展開しておくほうが速い場合が多いですよ」程度の推奨に緩めることにします。
数年前のビビ開発初期はむしろアーカイブ状態のままでしか扱えなかったくらいビビの基本的な機能で、また、圧縮ファイルをドラッグ&ドロップで開けるのも、自作 EPUB のプレビューなどに便利なビビのメリットです。
### "Analytics" …… Google Analytics でユーザの行動を分析できるようになる
本をウェブで公開するとなると、どれだけの人が再生ボタンをクリックしたか、目次のどの項目がクリックされたか、最後まで読んだか、などなど、気になってくると思います。これらを、Google Analytics のイベントトラッキング機能を使って記録できるようにします。
Google Analytics の基本機能として同時に記録される OS や アクセス元言語圏などなども合わせて、読まれた状況をさまざまに分析できるようになります。
有効化する際には、"src" に加えて "tracking-id" という値で Google Analytics のトラッキング ID書式UA-XXXXXXXX-Xを書き足す必要があります。
現在記録されるのは、下に挙げるユーザ行動です。ほかに記録・分析したいことがあれば、作者にご要望をお寄せください。
* 再生ボタンのクリック/タップ
* 目次項目のクリック/タップ
* 最後のページの表示
最近、ビビを使ったお仕事の中で、非常にたくさんの情報を記録する独自拡張を開発しました。そのクライアントのご厚意で、処理自体はオープンソース化するご許可をいただいていますので、そのうち、大きく拡張するかもしれません。
### "EPUBCFI" …… EPUBCFI 仕様の位置・範囲指定を利用できるようにする
EPUBCFI は、複数ファイルで構成される EPUB 内の、特定ファイルの特定段落の何文字目から何文字目、といった位置・範囲を指定することができる仕組みです。「これこれについてはこの本のここにかいてあります」といったリンクで人に伝えたりしやすくなります。論文の引用などにも使えますね。
EPUB ビューワは EPUBCFI に対応していることが望ましい、ということになっており、実際うまくつかえば便利なのでビビも部分的に対応してみたのですが……書式が「人間の読み書きできるもんじゃねえ」という感じだからか、EPUBCFI 仕様自体があまりつかわれていません。このプラグインも、仕様に用意された機能の完全対応は諦めて、位置の指定のみに対応して開発が止まっています(範囲指定はごく部分的にしか扱えません)。
ビビには、EPUBCFI を使わなくても本の途中を指定して開く機能を別につけてあります。それは EPUB の基本仕様ではなく独自機能ですが、もうすこしわかりやすく直感的な書式で指定できるようになっています。別途解説予定ですので、おたのしみに(といってぜんぜん解説しないままですみません)
項目の説明4:高度な設定(普通の使い方をするかぎり変更しないことをおすすめします)
----------------------------------------------------------------------------------------------------
"trustworthy-origins" …… bookshelf ディレクトリの場所や Message の送信元として許可するオリジン
必要であれば外部のオリジンを列挙することで、bookshelf を外部サーバに置いたり、別サーバからの Message で動作指示を受け取ったりできるようになります。なにも書かなくても、ビビ自体が置かれたサーバのオリジンは許可されます。
たとえばここに "https://dl.dropboxusercontent.com" を加えれば、自分のウェブサーバに設置したビビから Dropbox の公開フォルダに置いた EPUB を読み込んだりできるようになります。ただし、このオリジンはどんな Dropbox ユーザの公開フォルダの URL でも共通なので、まったく知らない誰かが、その人の Dropbox 公開フォルダに置いた EPUB を、あなたのビビで、表示させることもできるようになります。
十分に注意して、ドキュメントルート以下すべてが自分の管理下にあるサーバのみを加えるのがいいと思いますその条件では、Dropbox も除外されます)。
もちろん、その外部サーバがビビの置かれたサーバまたはすべての外部サーバからのリクエストを許可していなければ、ここに加えても読み込むことはできません。

View file

@ -0,0 +1,206 @@
Bibi.preset({
//==============================================================================================================================================
//-- Bookshelf
//----------------------------------------------------------------------------------------------------------------------------------------------
"bookshelf" : "../reader/bookshelf", // Relative path from this preset file to the bookshelf directory. "/" at the end is ignored. (To use a path begins with "http(s)://", read <01> at the bottom of this preset file.)
//==============================================================================================================================================
//-- Behavior
//----------------------------------------------------------------------------------------------------------------------------------------------
"reader-view-mode" : "paged", // "paged" or "horizontal" or "vertical" ("paged" is for flipping, "horizontal" and "vertical" are for scrolling)
"full-breadth-layout-in-scroll" : "no", // "yes" or "no" or "desktop" or "mobile"
"fix-reader-view-mode" : "no", // "yes" or "no" or "desktop" or "mobile"
"keep-settings" : "yes", // "yes" or "no" or "desktop" or "mobile"
"resume-from-last-position" : "yes", // "yes" or "no" or "desktop" or "mobile"
"autostart" : "yes", // "yes" or "no" or "desktop" or "mobile"
"autostart-embedded" : "no", // "yes" or "no" or "desktop" or "mobile" (It takes priority over "autostart" when the book is embedded in a webpage)
"start-embedded-in-new-window" : "mobile", // "yes" or "no" or "desktop" or "mobile" (It is used only when "autostart" (or "autostart-embedded") is NOT enabled)
//==============================================================================================================================================
//-- UI / Design
//----------------------------------------------------------------------------------------------------------------------------------------------
"use-menubar" : "yes", // "yes" or "no" or "desktop" or "mobile"
"use-full-height" : "yes", // "yes" or "no" or "desktop" or "mobile". If "use-menubar" is interpreted as "no", "use-full-height" is always treated as "yes".
"use-arrows" : "yes", // "yes" or "no" or "desktop" or "mobile"
"flipper-width" : 0.25, // Number of ratio (less than 1) or pixel (1 or greater)
"use-keys" : "yes", // "yes" or "no" or "desktop" or "mobile"
"use-slider" : "yes", // "yes" or "no" or "desktop" or "mobile"
"flip-pages-during-sliding" : "yes", // "yes" or "no" or "desktop" or "mobile"
"use-nombre" : "yes", // "yes" or "no" or "desktop" or "mobile"
"use-font-size-changer" : "yes", // "yes" or "no" or "desktop" or "mobile"
"base-font-size" : "auto", // Number of pixel or "auto"
"font-size-scale-per-step" : 1.25, // Number of scale
"use-loupe" : "desktop", // "yes" or "no" or "desktop" or "mobile" (Note: Loupe buttons will not appear in touch-devices even if it is set "yes" or "mobile".)
"loupe-max-scale" : 4, // Number of scale (greater than 1)
"loupe-scale-per-step" : 1.6, // Number of scale (greater than 1, less than or equal to "loupe-max-scale")
"zoom-out-for-utilities" : "yes", // "yes" or "no" or "desktop" or "mobile"
"use-history" : "yes", // "yes" or "no" or "desktop" or "mobile"
"max-history" : 19, // Number (0-19). If larger than 19, treated as 19. If 0, "use-history" is treated as "no".
"use-bookmarks" : "yes", // "yes" or "no" or "desktop" or "mobile"
"max-bookmarks" : 3, // Number (0-9). If larger than 9, treated as 9. If 0, "use-bookmarks" is treated as "no" (but old data is kept in localStorage).
"orientation-border-ratio" : 1 * 2 / 1.5, // Number (Width per Height)
"ui-font-family" : "", // CSS font-family value as "'Helvetica', sans-serif" or ""
"item-padding-left" : 24, // Number of pixel (It affects only for reflowable books.)
"item-padding-right" : 24, // Number of pixel (It affects only for reflowable books.)
"item-padding-top" : 48, // Number of pixel (It affects only for reflowable books.)
"item-padding-bottom" : 24, // Number of pixel (It affects only for reflowable books.)
"spread-gap" : 48, // Number of pixel (It affects only in paged view mode.)
"spread-margin" : 0, // Number of pixel
"fix-nav-ttb" : "no", // "yes" or "no" or "desktop" or "mobile"
"on-doubletap" : "",
"on-tripletap" : "",
"content-draggable" : [true, true], // [<TF>, <TF>]
"orthogonal-arrow-keys" : ["move", "switch"], // [<S1>, <S2>]
"orthogonal-edges" : ["utilities", "utilities"], // [<S1>, <S2>]
"orthogonal-touch-moves" : ["move", "switch"], // [<S1>, <S2>]
"orthogonal-wheelings" : ["move", "across"], // [<S1>, <S3>]
// ^ Each item of the arrays corresponds to the view mode:
// * the first is for the "paged" view mode, and
// * the second is for the "horizontal"/"vertical" scroll view modes.
// ^ Types of the values:
// * <TF>: true or false
// * <S1>: "" (ignore) or "utilities" or "move"
// * <S2>: "" (ignore) or "utilities" or "move" or "switch"
// * <S3>: "" (ignore) or "utilities" or "move" or "switch" or "across"
//==============================================================================================================================================
//-- Extensions
//----------------------------------------------------------------------------------------------------------------------------------------------
// "src" is relative path from this preset file to the JavaScript file of the extension.
// "id" must be defined in each extension file.
"extensions": [
// { "src": "../extensions/FOLDER-NAME-IF-EXISTS/FILE-NAME.js" }, // <THIS LINE IS AN EXAMPLE>
""],
//==============================================================================================================================================
//-- Extra
//----------------------------------------------------------------------------------------------------------------------------------------------
"website-name-in-title" : "", // "" or name of your website replaces string "Bibi" in <title>.
"website-name-in-menu" : "", // "" or name of your website appears in setting-menu as a link. (Requires "website-href")
"website-href" : "", // "" or URL of your website to be used for the link in setting-menu. (Requires "website-name-in-menu")
"remove-bibi-website-link" : true, // true or false (if true, the link to Bibi Website is not to be added in setting-menu)
//==============================================================================================================================================
//-- System
//----------------------------------------------------------------------------------------------------------------------------------------------
"extract-if-necessary" : [".epub", ".zip"], // File extensions of the book specified in URL, which you want Bibi to try to extract first. (More info is <02> at the bottom of this preset file.)
"default-page-progression-direction" : "ltr", // "ltr" or "rtl". Most of EPUBs have right property in itself, but....
"accept-local-file" : "yes", // "yes" or "no" or "desktop" or "mobile". (If it is enabled, Bibi prepares UI for loading files. Conditions for acceptance are <03> at the bottom of this preset file.)
"accept-bibizine" : true, // true or false (If true, Bibi accepts EPUB-like bibiZine formated book. If you are interested in it, please contact the author)
"accept-blob-converted-data" : true, // true or false (If true, Bibi accepts BLOB object converted from a EPUB File. If you are interested in it, please contact the author)
"accept-base64-encoded-data" : true, // true or false (If true, Bibi accepts Base64 string encoded from a EPUB File. If you are interested in it, please contact the author)
"pagination-method" : "auto", // "auto" or "x". (It affects only for vertical-text reflowable books. More info is <04> at the bottom of this preset file.)
"allow-placeholders" : true, // true or false. (true is highly recommended.)
"prioritise-fallbacks" : false, // true or false (If true, Bibi uses <item> at the end of the fallback-chain.)
//==============================================================================================================================================
//-- DANGER ZONE
//----------------------------------------------------------------------------------------------------------------------------------------------
// If you publish Bibi online,
// * keep these options as default, or/and
// * keep your Bibi and website not to open files which you can not guarantee its security.
//----------------------------------------------------------------------------------------------------------------------------------------------
/* !!!! BE CAREFUL !!!! */ "allow-scripts-in-content" : true, // true or false (false is recommended).
// If you change its value `true`, Bibi does not remove scripts natively-included in EPUB.
// It makes Bibi to be able to open EPUBs including useful scripts.
// But on the other hand, it may also allow XSS of malicious EPUB in some cases.
/* !!!! BE CAREFUL !!!! */ "trustworthy-origins" : [], // origins you trust other than where this Bibi is installed. (blank is recommended).
// If you add origins to it, Bibi is made to open not only EPUBs in the same origin as Bibi itself is installed but also EPUBs in remote origins.
// It is useful for some cases like that you want to set directory on the other storaging server as "bookshelf".
// But note that not to set an origin where someone else also can publish files.
// If you do so, someone else can publish one's EPUB as it is on your website, and it may also allow XSS of malicious EPUB in some cases.
/*
//==============================================================================================================================================
## <01> You can use a path begins with "http(s)://" for "bookshelf" option in cases of the below:
* The origin of the path defined in the "bookshelf" option is same as the origin of this Bibi.
* [OR] The origin is included in "trustworthy-origins" option.
- [AND] The origin allows COR from the origin of this Bibi.
## <02> Bibi tries to extract at first in cases of the below:
* The "extract-if-necessary" option includes "*".
* [OR] The "extract-if-necessary" option includes one or more file extensions.
- [AND] The book name specified as a value of the `book` (or `zine`) query in URL has a file extension.
- [AND] The file extension of the book name is included in the "extract-if-necessary" option.
* [OR] The "extract-if-necessary" option is "".
- [AND] The book name specified as a value of the `book` (or `zine`) query in URL has no file extension.
### Note:
* If Bibi failed to extract it, automatically tries to load as a folder (directory).
* The "extract-if-necessary" option affects also as conditions for acceptance of local file. Read <03> at the next.
## <03> Bibi accepts user's local file in cases of the below:
* The file is an EPUB.
- [AND] The extension of the file is ".epub".
- [AND] The "extract-if-necessary" option includes ".epub" or "*".
- [AND] The MIME-Type sent from the browser is "application/epub+zip".
* [OR] The file is a bibiZine.
- [AND] The extension of the file is ".zip".
- [AND] The "extract-if-necessary" includes ".zip" or "*".
- [AND] The MIME-Type sent from the browser is "application/zip", "application/x-zip", or "application/x-zip-compressed".
### Note:
* Extension of the file is required even if "extract-if-necessary" is "" (or includes "*").
## <04> Setting "x" for "pagination-method" option
It affects only for reflowable vertical-text books.
If "x" is set for "pagination-method", Bibi tries to use an experimental layout method on modern web-browsers.
It realizes more prettier layout for simple books like novels.
But sometime causes bad result for some books with figures or floating objects.
//==============================================================================================================================================
*/
"bibi": "EPUB Reader on your website." });

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,8 @@
/*!
*
* # Polyfill for Bibi: text-encoding-utf-8
*
* * Consists of:
* - text-encoding-utf-8 : by Erik Arvidsson - https://github.com/arv/text-encoding-utf-8 / Released into the public domain under the Unlicense - https://github.com/arv/text-encoding-utf-8/blob/master/LICENSE.md
*
*/!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=41)}({1:function(e,t,r){"use strict";function n(e){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(e,t,r){return t<=e&&e<=r}function i(e){if(void 0===e)return{};if(e===Object(e))return e;throw TypeError("Could not convert argument to dictionary")}r.d(t,"a",(function(){return s}));function f(e){this.tokens=[].slice.call(e)}f.prototype={endOfStream:function(){return!this.tokens.length},read:function(){return this.tokens.length?this.tokens.shift():-1},prepend:function(e){if(Array.isArray(e))for(var t=e;t.length;)this.tokens.unshift(t.pop());else this.tokens.unshift(e)},push:function(e){if(Array.isArray(e))for(var t=e;t.length;)this.tokens.push(t.shift());else this.tokens.push(e)}};function u(e,t){if(e)throw TypeError("Decoder error");return t||65533}function s(e,t){if(!(this instanceof s))return new s(e,t);if("utf-8"!==(e=void 0!==e?String(e).toLowerCase():"utf-8"))throw new Error("Encoding not supported. Only utf-8 is supported");t=i(t),this._streaming=!1,this._BOMseen=!1,this._decoder=null,this._fatal=Boolean(t.fatal),this._ignoreBOM=Boolean(t.ignoreBOM),Object.defineProperty(this,"encoding",{value:"utf-8"}),Object.defineProperty(this,"fatal",{value:this._fatal}),Object.defineProperty(this,"ignoreBOM",{value:this._ignoreBOM})}function a(e){var t=e.fatal,r=0,n=0,i=0,f=128,s=191;this.handler=function(e,a){if(-1===a&&0!==i)return i=0,u(t);if(-1===a)return-1;if(0===i){if(o(a,0,127))return a;if(o(a,194,223))i=1,r=a-192;else if(o(a,224,239))224===a&&(f=160),237===a&&(s=159),i=2,r=a-224;else{if(!o(a,240,244))return u(t);240===a&&(f=144),244===a&&(s=143),i=3,r=a-240}return r<<=6*i,null}if(!o(a,f,s))return r=i=n=0,f=128,s=191,e.prepend(a),u(t);if(f=128,s=191,r+=a-128<<6*(i-(n+=1)),n!==i)return null;var l=r;return r=i=n=0,l}}s.prototype={decode:function(e,t){var r;r="object"===n(e)&&e instanceof ArrayBuffer?new Uint8Array(e):"object"===n(e)&&"buffer"in e&&e.buffer instanceof ArrayBuffer?new Uint8Array(e.buffer,e.byteOffset,e.byteLength):new Uint8Array(0),t=i(t),this._streaming||(this._decoder=new a({fatal:this._fatal}),this._BOMseen=!1),this._streaming=Boolean(t.stream);for(var o,u=new f(r),s=[];!u.endOfStream()&&-1!==(o=this._decoder.handler(u,u.read()));)null!==o&&(Array.isArray(o)?s.push.apply(s,o):s.push(o));if(!this._streaming){do{if(-1===(o=this._decoder.handler(u,u.read())))break;null!==o&&(Array.isArray(o)?s.push.apply(s,o):s.push(o))}while(!u.endOfStream());this._decoder=null}return s.length&&(-1===["utf-8"].indexOf(this.encoding)||this._ignoreBOM||this._BOMseen||(65279===s[0]?(this._BOMseen=!0,s.shift()):this._BOMseen=!0)),function(e){for(var t="",r=0;r<e.length;++r){var n=e[r];n<=65535?t+=String.fromCharCode(n):(n-=65536,t+=String.fromCharCode(55296+(n>>10),56320+(1023&n)))}return t}(s)}}},41:function(e,t,r){"use strict";r.r(t);var n=r(1);self.TextDecoder=n.a}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long