完成阅读器1.0.0
parent
71aebe5cbd
commit
6c161866da
|
@ -1 +1 @@
|
||||||
html{width:100%;height:100vh}body{overflow:hidden;display:flex;width:100%;height:100%;line-height:1.25;font-size:14px;color:var(--color-dark-1);background:rgba(255,255,255,0.3)}.app{position:relative;display:flex;height:100%}.app .category{width:200px;height:100%;background:#fff}.app .category .item{display:flex;justify-content:space-between;align-items:center;height:54px;padding:8px;border-bottom:1px solid var(--color-plain-1);background:#fff;transition:background 0.2s ease-in-out, color 0.2s ease-in-out;cursor:pointer}.app .category .item strong{max-width:150px}.app .category .item .num{display:flex;justify-content:center;align-items:center;min-width:16px;height:16px;padding:2px;line-height:1;border-radius:50%;font-size:12px;background:var(--color-grey-1);color:#fff}.app .category .item:last-child{border-bottom:0}.app .category .item:hover{color:var(--color-blue-1);background:var(--color-plain-1)}.app .category .item.active{color:var(--color-plain-1);background:var(--color-blue-1)}.app .category .item.active .num{background:#fff;color:var(--color-blue-1)}.app .books-scroll{flex:1;height:100%;border-left:1px solid var(--color-plain-2)}.app .books{display:flex;flex-wrap:wrap}.app .books .book{display:flex;flex-direction:column;width:128px;margin:24px;background:#fff;box-shadow:0 0 12px rgba(0,0,0,0.15);transition:box-shadow 0.1s ease-in;cursor:pointer}.app .books .book img{width:100%;height:160px;-o-object-fit:fill;object-fit:fill}.app .books .book:hover{box-shadow:0 0 12px rgba(0,0,0,0.35)}.app .drag-mask{display:flex;align-items:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;background:linear-gradient(to right, transparent, transparent 200px, rgba(252,232,207,0.6) 200px)}.app .drag-mask::after{font-size:46px;text-indent:360px;content:'Drop epub file here...';color:var(--color-grey-1)}.app .book-loading{display:flex;align-items:center;justify-content:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;font-size:20px;background:rgba(255,255,255,0.01);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.app .book-loading .loading{display:flex;flex-direction:column;align-items:center;justify-content:center}.app .book-loading .loading::before{content:'🌑';font-size:36px;-webkit-animation:loading 1s infinite;animation:loading 1s infinite}@-webkit-keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}}@keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}}
|
html{width:100%;height:100vh}body{overflow:hidden;display:flex;width:100%;height:100%;line-height:1.25;font-size:14px;color:var(--color-dark-1);background:rgba(255,255,255,0.3)}.app{position:relative;display:flex;width:100%;height:100%}.app .category{width:200px;height:100%;background:#fff}.app .category .item{display:flex;justify-content:space-between;align-items:center;height:54px;padding:8px;border-bottom:1px solid var(--color-plain-1);background:#fff;transition:background 0.2s ease-in-out, color 0.2s ease-in-out;cursor:pointer}.app .category .item strong{max-width:150px}.app .category .item .num{display:flex;justify-content:center;align-items:center;min-width:16px;height:16px;padding:2px;line-height:1;border-radius:50%;font-size:12px;background:var(--color-grey-1);color:#fff}.app .category .item:last-child{border-bottom:0}.app .category .item:hover{color:var(--color-blue-1);background:var(--color-plain-1)}.app .category .item.active{color:var(--color-plain-1);background:var(--color-blue-1)}.app .category .item.active .num{background:#fff;color:var(--color-blue-1)}.app .books-scroll{flex:1;height:100%;border-left:1px solid var(--color-plain-2)}.app .books{display:flex;flex-wrap:wrap}.app .books .book{display:flex;flex-direction:column;width:128px;margin:24px;background:#fff;box-shadow:0 0 12px rgba(0,0,0,0.15);transition:box-shadow 0.1s ease-in;cursor:pointer}.app .books .book img{width:100%;height:160px;-o-object-fit:fill;object-fit:fill}.app .books .book:hover{box-shadow:0 0 12px rgba(0,0,0,0.35)}.app .drag-mask{display:flex;align-items:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;background:linear-gradient(to right, transparent, transparent 200px, rgba(252,232,207,0.6) 200px)}.app .drag-mask::after{font-size:46px;text-indent:360px;content:'Drop epub file here...';color:var(--color-grey-1)}.app .book-loading{display:flex;align-items:center;justify-content:center;position:fixed;left:0;top:0;z-index:9999;width:100%;height:100%;font-size:20px;background:rgba(255,255,255,0.01);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.app .book-loading .loading{display:flex;flex-direction:column;align-items:center;justify-content:center}.app .book-loading .loading::before{content:'🌑';font-size:36px;-webkit-animation:loading 1s infinite;animation:loading 1s infinite}.app .context-menu{display:flex;flex-direction:column;width:100px;padding:5px 0;background:#fff}.app .context-menu .item{height:30px;line-height:30px;padding:0 15px;cursor:pointer}.app .context-menu .item:hover{background:#f2f5fc}.app .context-menu .item.diabled{color:var(--color-plain-2);background:#fff;cursor:default}@-webkit-keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}}@keyframes loading{1%,100%{content:'🌑'}12.5%{content:'🌒'}25%{content:'🌓'}37.5%{content:'🌔'}50%{content:'🌕'}62.5%{content:'🌖'}75%{content:'🌗'}87.5%{content:'🌘'}}
|
||||||
|
|
|
@ -24,6 +24,7 @@ body {
|
||||||
.app {
|
.app {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.category {
|
.category {
|
||||||
|
@ -163,6 +164,31 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.context-menu {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100px;
|
||||||
|
padding: 5px 0;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #f2f5fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.diabled {
|
||||||
|
color: var(--color-plain-2);
|
||||||
|
background: #fff;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes loading {
|
@keyframes loading {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
/**
|
/**
|
||||||
* 浮窗样式
|
* 阅读样式
|
||||||
* @authors yutent<yutent@doui.cc>
|
* @authors yutent<yutent@doui.cc>
|
||||||
* @date 2018/12/16 17:15:07
|
* @date 2018/12/16 17:15:07
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
<wc-scroll class="category">
|
<wc-scroll class="category">
|
||||||
<item
|
<item
|
||||||
class="item"
|
class="item"
|
||||||
|
@contextmenu="pickCtx1(it, $event)"
|
||||||
|
@click="view(it)"
|
||||||
:class="{active: curr === it.name}"
|
:class="{active: curr === it.name}"
|
||||||
:for="it in cates">
|
:for="it in cates">
|
||||||
<strong :text="it.name"></strong>
|
<strong :text="it.name"></strong>
|
||||||
|
@ -28,7 +30,12 @@
|
||||||
|
|
||||||
<wc-scroll class="books-scroll">
|
<wc-scroll class="books-scroll">
|
||||||
<list class="books">
|
<list class="books">
|
||||||
<book class="book" :for="it in books">
|
<book
|
||||||
|
class="book"
|
||||||
|
:for="it in books"
|
||||||
|
@dblclick="read(it)"
|
||||||
|
@contextmenu="pickCtx2(it, $event)"
|
||||||
|
>
|
||||||
<img :src="'book://cache/' + it.title + '/' + it.cover">
|
<img :src="'book://cache/' + it.title + '/' + it.cover">
|
||||||
</book>
|
</book>
|
||||||
</list>
|
</list>
|
||||||
|
@ -38,13 +45,28 @@
|
||||||
|
|
||||||
<div class="drag-mask" ref="mask" :visible="isDragIn"></div>
|
<div class="drag-mask" ref="mask" :visible="isDragIn"></div>
|
||||||
|
|
||||||
<div class="book-loading" ref="books" :visible="loading">
|
<div class="book-loading" :visible="loading">
|
||||||
<div class="loading">
|
<div class="loading">
|
||||||
<span>共 {{load.num}} 本书</span>
|
<span>共 {{load.num}} 本书</span>
|
||||||
<span>当前正在解析第 {{load.curr}} 本</span>
|
<span>当前正在解析第 {{load.curr}} 本</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<wc-layer ref="ctx1" left="100px" top="0" radius="0">
|
||||||
|
<ul class="context-menu noselect">
|
||||||
|
<li class="item" @click="deleteCate">删除</li>
|
||||||
|
<li class="item" @click="renameCate">重命名</li>
|
||||||
|
<li class="item" @click="createCate">新建分类</li>
|
||||||
|
</ul>
|
||||||
|
</wc-layer>
|
||||||
|
|
||||||
|
<wc-layer ref="ctx2" left="100px" top="0" radius="0">
|
||||||
|
<ul class="context-menu noselect">
|
||||||
|
<li class="item" @click="deleteBook">删除</li>
|
||||||
|
<li class="item diabled">移动到</li>
|
||||||
|
</ul>
|
||||||
|
</wc-layer>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
195
src/js/app.js
195
src/js/app.js
|
@ -9,7 +9,9 @@
|
||||||
import '/lib/anot.js'
|
import '/lib/anot.js'
|
||||||
import '/lib/scroll/index.js'
|
import '/lib/scroll/index.js'
|
||||||
|
|
||||||
import layer from '/lib/layer/index.js'
|
import '/lib/layer/index.js'
|
||||||
|
import Utils from '/lib/utils.js'
|
||||||
|
import { md5 } from '/lib/md5.js'
|
||||||
|
|
||||||
import app from '/lib/socket.js'
|
import app from '/lib/socket.js'
|
||||||
|
|
||||||
|
@ -25,7 +27,7 @@ Anot({
|
||||||
state: {
|
state: {
|
||||||
input: '',
|
input: '',
|
||||||
curr: '默认分类',
|
curr: '默认分类',
|
||||||
cates: [{ name: '默认分类', num: 12 }],
|
cates: [],
|
||||||
books: [],
|
books: [],
|
||||||
loading: false,
|
loading: false,
|
||||||
isDragIn: false,
|
isDragIn: false,
|
||||||
|
@ -33,12 +35,21 @@ Anot({
|
||||||
num: 0,
|
num: 0,
|
||||||
curr: 0
|
curr: 0
|
||||||
},
|
},
|
||||||
$db: {}
|
$db: {},
|
||||||
|
$ctx1: null,
|
||||||
|
$ctx2: null
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {},
|
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
|
Utils.outside(this.$refs.ctx1, ev => {
|
||||||
|
this.$refs.ctx1.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
Utils.outside(this.$refs.ctx2, ev => {
|
||||||
|
this.$refs.ctx2.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
/* --------------------- */
|
||||||
$doc.bind('dragover', ev => {
|
$doc.bind('dragover', ev => {
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
|
|
||||||
|
@ -50,7 +61,7 @@ Anot({
|
||||||
this.isDragIn = false
|
this.isDragIn = false
|
||||||
})
|
})
|
||||||
|
|
||||||
$doc.bind('drop', ev => {
|
$doc.bind('drop', async ev => {
|
||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
|
|
||||||
this.isDragIn = false
|
this.isDragIn = false
|
||||||
|
@ -72,17 +83,32 @@ Anot({
|
||||||
let book = files.pop()
|
let book = files.pop()
|
||||||
let res = app.dispatch('parse-book', { book, cate: this.curr })
|
let res = app.dispatch('parse-book', { book, cate: this.curr })
|
||||||
|
|
||||||
|
await sleep(500)
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
this.books.push(res)
|
this.books.push(res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let it of this.cates) {
|
||||||
|
if (it.name === this.curr) {
|
||||||
|
it.num = this.books.length
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/* --------------------- */
|
||||||
|
|
||||||
let db = app.dispatch('get-books')
|
let db = app.dispatch('get-books')
|
||||||
let cates = [],
|
let cates = [],
|
||||||
books
|
books
|
||||||
|
|
||||||
|
if (Object.keys(db).length < 1) {
|
||||||
|
db = { 默认分类: [] }
|
||||||
|
}
|
||||||
|
|
||||||
for (let k in db) {
|
for (let k in db) {
|
||||||
cates.push({ name: k, num: db[k].length })
|
cates.push({ name: k, num: db[k].length })
|
||||||
// 默认选中第一个
|
// 默认选中第一个
|
||||||
|
@ -91,10 +117,161 @@ Anot({
|
||||||
books = db[k]
|
books = db[k]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// books = books.concat(books, books, books, books, books, books)
|
|
||||||
this.$db = db
|
this.$db = db
|
||||||
this.cates = cates
|
this.cates = cates
|
||||||
this.books = books
|
this.books = books || []
|
||||||
},
|
},
|
||||||
methods: {}
|
methods: {
|
||||||
|
view(item) {
|
||||||
|
this.books = this.$db[item.name]
|
||||||
|
},
|
||||||
|
read(item) {
|
||||||
|
var params = { title: item.title }
|
||||||
|
var readCache = Anot.ls(md5(item.title))
|
||||||
|
|
||||||
|
if (readCache) {
|
||||||
|
params.chapter = readCache
|
||||||
|
}
|
||||||
|
|
||||||
|
app.dispatch(
|
||||||
|
'read',
|
||||||
|
Buffer.from(JSON.stringify(params)).toString('base64')
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
pickCtx1(item, ev) {
|
||||||
|
this.$ctx1 = item
|
||||||
|
ev.stopPropagation()
|
||||||
|
|
||||||
|
let { pageX, pageY } = ev
|
||||||
|
if (pageY + 70 > 600) {
|
||||||
|
pageY -= 70
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$refs.ctx1.close()
|
||||||
|
|
||||||
|
Anot.nextTick(_ => {
|
||||||
|
this.$refs.ctx1.moveTo({ left: pageX + 'px', top: pageY + 'px' })
|
||||||
|
this.$refs.ctx1.show()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
pickCtx2(item, ev) {
|
||||||
|
this.$ctx2 = item
|
||||||
|
|
||||||
|
ev.stopPropagation()
|
||||||
|
|
||||||
|
let { pageX, pageY } = ev
|
||||||
|
if (pageY + 70 > 600) {
|
||||||
|
pageY -= 70
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$refs.ctx2.close()
|
||||||
|
|
||||||
|
Anot.nextTick(_ => {
|
||||||
|
this.$refs.ctx2.moveTo({ left: pageX + 'px', top: pageY + 'px' })
|
||||||
|
this.$refs.ctx2.show()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
saveDB() {
|
||||||
|
app.dispatch('save-books', Anot.deepCopy(this.$db))
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteCate() {
|
||||||
|
//
|
||||||
|
this.$refs.ctx1.close()
|
||||||
|
if (this.$ctx1) {
|
||||||
|
let { name, num } = this.$ctx1
|
||||||
|
|
||||||
|
if (num > 0) {
|
||||||
|
return layer.toast(`${name} 下有书籍, 不可删除!`, 'error')
|
||||||
|
}
|
||||||
|
delete this.$db[name]
|
||||||
|
this.cates.remove(this.$ctx1)
|
||||||
|
this.saveDB()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
createCate() {
|
||||||
|
this.$ctx1 = null
|
||||||
|
this.$refs.ctx1.close()
|
||||||
|
|
||||||
|
layer
|
||||||
|
.prompt('请输入分类名', (val, done) => {
|
||||||
|
if (val.trim()) {
|
||||||
|
if (this.$db[val.trim()]) {
|
||||||
|
return layer.toast('分类已存在, 请换个名字', 'error')
|
||||||
|
}
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(v => {
|
||||||
|
v = v.trim()
|
||||||
|
this.$db[v] = []
|
||||||
|
this.cates.push({ name: v, num: 0 })
|
||||||
|
this.saveDB()
|
||||||
|
})
|
||||||
|
.catch(Anot.noop)
|
||||||
|
},
|
||||||
|
|
||||||
|
renameCate() {
|
||||||
|
//
|
||||||
|
this.$refs.ctx1.close()
|
||||||
|
if (this.$ctx1) {
|
||||||
|
let { name } = this.$ctx1
|
||||||
|
|
||||||
|
layer
|
||||||
|
.prompt(`请输入新的分类名(${name})`, (val, done) => {
|
||||||
|
val = val.trim()
|
||||||
|
if (val) {
|
||||||
|
if (this.$db[val] || val === name) {
|
||||||
|
return layer.toast('分类已存在, 请换个名字', 'error')
|
||||||
|
}
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(v => {
|
||||||
|
v = v.trim()
|
||||||
|
this.$db[v] = this.$db[name]
|
||||||
|
delete this.$db[name]
|
||||||
|
this.$ctx1.name = v
|
||||||
|
this.$ctx1 = null
|
||||||
|
this.saveDB()
|
||||||
|
})
|
||||||
|
.catch(Anot.noop)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteBook() {
|
||||||
|
this.$refs.ctx2.close()
|
||||||
|
if (this.$ctx2) {
|
||||||
|
let { title } = this.$ctx2
|
||||||
|
layer
|
||||||
|
.confirm(`是否要删除[${title}]? 该操作不可逆!`)
|
||||||
|
.then(r => {
|
||||||
|
this.books.remove(this.$ctx2)
|
||||||
|
this.$db[this.curr] = this.books
|
||||||
|
|
||||||
|
for (let it of this.cates) {
|
||||||
|
if (it.name === this.curr) {
|
||||||
|
it.num = this.books.length
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.saveDB()
|
||||||
|
app.dispatch('delete-book', title)
|
||||||
|
})
|
||||||
|
.catch(Anot.noop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// moveBook() {
|
||||||
|
// this.$refs.ctx2.close()
|
||||||
|
// if (this.$ctx2) {
|
||||||
|
// let { title } = this.$ctx2
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -8,7 +8,7 @@ import '/lib/anot.js'
|
||||||
|
|
||||||
import '/lib/scroll/index.js'
|
import '/lib/scroll/index.js'
|
||||||
import '/lib/code/index.js'
|
import '/lib/code/index.js'
|
||||||
import layer from '/lib/layer/index.js'
|
import { md5 } from '/lib/md5.js'
|
||||||
import fetch from '/lib/fetch/index.js'
|
import fetch from '/lib/fetch/index.js'
|
||||||
import app from '/lib/socket.js'
|
import app from '/lib/socket.js'
|
||||||
|
|
||||||
|
@ -16,29 +16,52 @@ Anot({
|
||||||
$id: 'app',
|
$id: 'app',
|
||||||
state: {
|
state: {
|
||||||
toc: [],
|
toc: [],
|
||||||
title: 'HTML5 canvas开发详解(第2版) (无)',
|
book: '', // 当前阅读的书名
|
||||||
curr: '',
|
curr: '', // 当前选中的章节名
|
||||||
file: '',
|
file: '', // 章节所属的文件名
|
||||||
chapter: ''
|
chapter: '' // 章节渲染html文本
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// app.on('float-visible', data => {})
|
var search = location.search
|
||||||
|
|
||||||
document.title = this.title
|
if (search) {
|
||||||
this.getToc()
|
search = JSON.parse(Buffer.from(search.slice(1), 'base64'))
|
||||||
|
|
||||||
|
document.title = this.book = search.title
|
||||||
|
this.curr = search.chapter || ''
|
||||||
|
|
||||||
|
this.getToc()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getToc() {
|
getToc() {
|
||||||
fetch('book://cache/HTML5 canvas开发详解(第2版) (无)/toc.json')
|
fetch(`book://cache/${this.book}/toc.json`)
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(list => {
|
.then(list => {
|
||||||
for (let it of list) {
|
let chapter, idx
|
||||||
|
for (let i = -1, it; (it = list[++i]); ) {
|
||||||
delete it.id
|
delete it.id
|
||||||
delete it.order
|
delete it.order
|
||||||
}
|
|
||||||
this.toc = list
|
|
||||||
|
|
||||||
this.viewChapter(list[23])
|
it.href = it.href.replace('.xhtml', '.html')
|
||||||
|
|
||||||
|
if (it.title === this.curr) {
|
||||||
|
chapter = it
|
||||||
|
idx = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chapter) {
|
||||||
|
chapter = list[0]
|
||||||
|
idx = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
this.toc = list
|
||||||
|
this.viewChapter(chapter)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$refs.toc.scrollTop = 36 * (idx - 10)
|
||||||
|
}, 100)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -49,6 +72,8 @@ Anot({
|
||||||
|
|
||||||
this.curr = item.title
|
this.curr = item.title
|
||||||
|
|
||||||
|
Anot.ls(md5(this.book), item.title)
|
||||||
|
|
||||||
if (this.file === file) {
|
if (this.file === file) {
|
||||||
if (hash) {
|
if (hash) {
|
||||||
location.hash = hash
|
location.hash = hash
|
||||||
|
@ -58,14 +83,14 @@ Anot({
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.file = file
|
this.file = file
|
||||||
fetch('book://cache/HTML5 canvas开发详解(第2版) (无)/' + file)
|
fetch(`book://cache/${this.book}/${file}`)
|
||||||
.then(r => r.text())
|
.then(r => r.text())
|
||||||
.then(txt => {
|
.then(txt => {
|
||||||
this.chapter = txt.replace(
|
this.chapter = txt.replace(
|
||||||
/<img[^>]*?src="(.*?)"[^>]*?\/?>/g,
|
/<img[^>]*?src="(.*?)"[^>]*?\/?>/g,
|
||||||
(m, s1) => {
|
(m, s1) => {
|
||||||
s1 = s1.replace('../', '')
|
s1 = s1.replace('../', '')
|
||||||
return `<img src="book://cache/${this.title}/${s1}">`
|
return `<img src="book://cache/${this.book}/${s1}">`
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
"use strict";import $ from"../utils.js";const DEF_OPT={axis:"",limit:!1,overflow:!0};export default class Drag{constructor(t){this.$elem=t,this._init()}_init(){this.$elem.style.transform="";var{x:t,y:s}=this.$elem.getBoundingClientRect();this.pos={x:t,y:s,_x:0,_y:0}}by(t,s={}){return this.$drag=t,this.opt=Object.assign(Object.create(null),DEF_OPT,s),!1!==this.opt.limit&&(this.opt.overflow=!1),t.style.cursor="move",this._handleResize=$.bind(window,"resize",this._init.bind(this)),this._handleMousedown=$.bind(t,"mousedown",t=>{if(this.disabled)return;var s=this.$elem.getBoundingClientRect();s.x-this.pos._x!==this.pos.x&&(this.pos.x=s.x-this.pos._x),s.y-this.pos._y!==this.pos.y&&(this.pos.y=s.y-this.pos._y);let e=t.pageX,i=t.pageY,o=document.documentElement.clientWidth,n=document.documentElement.clientHeight,h=s.width,p=s.height,d=[0,o-h,n-p,0];if("parent"===this.opt.limit){let t=this.$elem.parentNode.getBoundingClientRect();d=[t.top,t.right-h,t.bottom-p,t.left]}let l=$.bind(document,"mousemove",t=>{t.preventDefault();let o=t.pageX-e+(s.x-this.pos.x),n=t.pageY-i+(s.y-this.pos.y);"x"===this.opt.axis&&(n=0),"y"===this.opt.axis&&(o=0),!1===this.opt.overflow&&(o<d[3]-this.pos.x?o=d[3]-this.pos.x:o>d[1]-this.pos.x&&(o=d[1]-this.pos.x),n<d[0]-this.pos.y?n=d[0]-this.pos.y:n>d[2]-this.pos.y&&(n=d[2]-this.pos.y)),this.pos._x=o,this.pos._y=n,this.$elem.dispatchEvent(new CustomEvent("dragging",{detail:{offset:{x:this.pos.x+o,y:this.pos.y+n},move:{x:o,y:n}}})),this.$elem.style.transform=`translate(${o}px, ${n}px)`}),m=$.bind(document,"mouseup",t=>{this.$elem.dispatchEvent(new CustomEvent("dragged",{detail:{offset:{x:this.pos.x+this.pos._x,y:this.pos.y+this.pos._y},move:{x:this.pos._x,y:this.pos._y}}})),$.unbind(document,"mousemove",l),$.unbind(document,"mouseup",m)})}),this}on(t,s){if(t&&"function"==typeof s)return $.bind(this,t,s)}off(t,s){$.unbind(this,t,s)}destroy(){$.unbind(window,"resize",this._handleResize),$.unbind(this.$drag,"mousedown",this._handleMousedown),delete this.$elem,delete this.$drag}};
|
import $ from"../utils.js";const DEF_OPT={axis:"",limit:!1,overflow:!0};export default class Drag{constructor(t){this.$elem=t,this._init()}_init(){this.$elem.style.transform="";var{x:t,y:s}=this.$elem.getBoundingClientRect();this.pos={x:t,y:s,_x:0,_y:0}}by(t,s={}){return this.$drag=t,this.opt=Object.assign(Object.create(null),DEF_OPT,s),!1!==this.opt.limit&&(this.opt.overflow=!1),t.style.cursor="move",this._handleResize=$.bind(window,"resize",this._init.bind(this)),this._handleMousedown=$.bind(t,"mousedown",t=>{if(this.disabled)return;var s=this.$elem.getBoundingClientRect();s.x-this.pos._x!==this.pos.x&&(this.pos.x=s.x-this.pos._x),s.y-this.pos._y!==this.pos.y&&(this.pos.y=s.y-this.pos._y);let e=t.pageX,i=t.pageY,o=document.documentElement.clientWidth,n=document.documentElement.clientHeight,h=s.width,p=s.height,d=[0,o-h,n-p,0];if("parent"===this.opt.limit){let t=this.$elem.parentNode.getBoundingClientRect();d=[t.top,t.right-h,t.bottom-p,t.left]}let l=$.bind(document,"mousemove",t=>{t.preventDefault();let o=t.pageX-e+(s.x-this.pos.x),n=t.pageY-i+(s.y-this.pos.y);"x"===this.opt.axis&&(n=0),"y"===this.opt.axis&&(o=0),!1===this.opt.overflow&&(o<d[3]-this.pos.x?o=d[3]-this.pos.x:o>d[1]-this.pos.x&&(o=d[1]-this.pos.x),n<d[0]-this.pos.y?n=d[0]-this.pos.y:n>d[2]-this.pos.y&&(n=d[2]-this.pos.y)),this.pos._x=o,this.pos._y=n,this.$elem.dispatchEvent(new CustomEvent("dragging",{detail:{offset:{x:this.pos.x+o,y:this.pos.y+n},move:{x:o,y:n}}})),this.$elem.style.transform=`translate(${o}px, ${n}px)`}),m=$.bind(document,"mouseup",t=>{this.$elem.dispatchEvent(new CustomEvent("dragged",{detail:{offset:{x:this.pos.x+this.pos._x,y:this.pos.y+this.pos._y},move:{x:this.pos._x,y:this.pos._y}}})),$.unbind(document,"mousemove",l),$.unbind(document,"mouseup",m)})}),this}on(t,s){if(t&&"function"==typeof s)return $.bind(this,t,s)}off(t,s){$.unbind(this,t,s)}destroy(){$.unbind(window,"resize",this._handleResize),$.unbind(this.$drag,"mousedown",this._handleMousedown),delete this.$elem,delete this.$drag}}
|
|
@ -1 +1 @@
|
||||||
"use strict";import Drag from"./core.js";Anot.directive("drag",{priority:1500,init:function(e){e.expr='"'+e.expr+'"',e.overflow=!0,e.axis="xy",e.element.dataset.axis&&(e.axis=e.element.dataset.axis,delete e.element.dataset.axis),e.limit=!1,e.element.dataset.limit&&(e.limit=e.element.dataset.limit,e.overflow=!1,delete e.element.dataset.limit)},update:function(e){var t=this.element;if(e)for(t=this.element.parentNode;t;){if(t.classList||Anot.error(`${this.name}=${this.expr}, 解析异常[元素不存在]`),"WC-LAYER"===t.tagName&&"layer"===e){t=t.root.children[1];break}if(t.classList.contains(e)||t.id===e)break;t=t.parentNode}new Drag(t).by(this.element,{limit:this.limit,axis:this.axis,overflow:this.overflow})}});
|
import Drag from"./core.js";Anot.directive("drag",{priority:1500,init:function(e){e.expr='"'+e.expr+'"',e.overflow=!0,e.axis="xy",e.element.dataset.axis&&(e.axis=e.element.dataset.axis,delete e.element.dataset.axis),e.limit=!1,e.element.dataset.limit&&(e.limit=e.element.dataset.limit,e.overflow=!1,delete e.element.dataset.limit)},update:function(e){var t=this.element;if(e)for(t=this.element.parentNode;t;){if(t.classList||Anot.error(`${this.name}=${this.expr}, 解析异常[元素不存在]`),"WC-LAYER"===t.tagName&&"layer"===e){t=t.root.children[1];break}if(t.classList.contains(e)||t.id===e)break;t=t.parentNode}new Drag(t).by(this.element,{limit:this.limit,axis:this.axis,overflow:this.overflow})}});
|
|
@ -1,14 +1,12 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @authors yutent (yutent@doui.cc)
|
* @authors yutent (yutent.io@gmail.com)
|
||||||
* @date 2020-07-07 16:27:17
|
* @date 2020-12-23 15:31:02
|
||||||
* @version v2.0.1
|
* @version v1.0.0
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict'
|
import SVG_DICT from"./svg.js";let dict=SVG_DICT;window.EXT_SVG_DICT&&Object.assign(dict,EXT_SVG_DICT);export default class Icon extends HTMLElement{static get observedAttributes(){return["is"]}props={is:""};constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML="<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{--color-teal-1: #4db6ac;--color-teal-2: #26a69a;--color-teal-3: #009688;--color-green-1: #81c784;--color-green-2: #66bb6a;--color-green-3: #4caf50;--color-purple-1: #9575cd;--color-purple-2: #9575cd;--color-purple-3: #673ab7;--color-blue-1: #64b5f6;--color-blue-2: #42a5f5;--color-blue-3: #2196f3;--color-red-1: #ff5061;--color-red-2: #eb3b48;--color-red-3: #ce3742;--color-orange-1: #ffb618;--color-orange-2: #f39c12;--color-orange-3: #e67e22;--color-plain-1: #f2f5fc;--color-plain-2: #e8ebf4;--color-plain-3: #dae1e9;--color-grey-1: #bdbdbd;--color-grey-2: #9e9e9e;--color-grey-3: #757575;--color-dark-1: #62778d;--color-dark-2: #526273;--color-dark-3: #425064}:host{display:inline-block;color:inherit}:host(:not([is])){display:none}.icon{display:block;width:var(--size, 32px);height:var(--size, 32px);margin:var(--pad, auto);fill:currentColor}.icon.load{animation:load 1.5s linear infinite}.icon circle{stroke:currentColor;animation:circle 1.5s ease-in-out infinite}:host([size='large']) .icon{width:42px;height:42px}:host([size='medium']) .icon{width:38px;height:38px}:host([size='mini']) .icon{width:20px;height:20px}:host([color='red']){color:var(--color-red-1)}:host([color='blue']){color:var(--color-blue-1)}:host([color='green']){color:var(--color-green-1)}:host([color='teal']){color:var(--color-teal-1)}:host([color='orange']){color:var(--color-orange-1)}:host([color='dark']){color:var(--color-dark-1)}:host([color='purple']){color:var(--color-purple-1)}:host([color='grey']){color:var(--color-grey-1)}@keyframes circle{0%{stroke-dasharray:0, 3812px;stroke-dashoffset:0}50%{stroke-dasharray:1906px, 3812px;stroke-dashoffset:-287px}100%{stroke-dasharray:1906px, 3812px;stroke-dashoffset:-2393px}}@keyframes load{to{transform:rotate(360deg)}}</style> <svg class=\"icon\" viewBox=\"0 0 1024 1024\"></svg> ",this.__ICO__=this.root.lastElementChild,this.drawPath()}get is(){return this.props.is}set is(o){o&&this.setAttribute("is",o)}drawPath(){var{is:o}=this.props,r=dict[o];this.__ICO__&&o&&r&&(this.__ICO__.innerHTML="loading"===o?r:`<path d="${r}" />`,this.__ICO__.classList.toggle("load","loading"===o))}attributeChangedCallback(o,r,e){if(null!==e&&r!==e)switch(o){case"is":this.props.is=e,e?this.drawPath():this.removeAttribute("is")}}}
|
||||||
|
|
||||||
import SVG_DICT from"./svg.js";let dict=SVG_DICT;window.EXT_SVG_DICT&&Object.assign(dict,EXT_SVG_DICT);export default class Icon extends HTMLElement{static get observedAttributes(){return["is"]}constructor(){super(),Object.defineProperty(this,"root",{value:this.attachShadow({mode:"open"}),writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(this,"props",{value:{is:""},writable:!0,enumerable:!1,configurable:!0}),this.root.innerHTML="<style>*{box-sizing:border-box;margin:0;padding:0}::before,::after{box-sizing:border-box}:host{display:inline-block;color:inherit}:host(:not([is])){display:none}.icon{display:block;width:var(--size, 32px);height:var(--size, 32px);margin:var(--pad, auto);fill:currentColor}.icon.load{animation:load 1.5s linear infinite}.icon circle{stroke:currentColor;animation:circle 1.5s ease-in-out infinite}:host([size='large']) .icon{width:42px;height:42px}:host([size='medium']) .icon{width:38px;height:38px}:host([size='mini']) .icon{width:20px;height:20px}:host([color='red']){color:#ff5061}:host([color='blue']){color:#64b5f6}:host([color='green']){color:#81c784}:host([color='teal']){color:#4db6ac}:host([color='orange']){color:#ffb618}:host([color='dark']){color:#62778d}:host([color='purple']){color:#9575cd}:host([color='grey']){color:#bdbdbd}@keyframes circle{0%{stroke-dasharray:0, 3812px;stroke-dashoffset:0}50%{stroke-dasharray:1906px, 3812px;stroke-dashoffset:-287px}100%{stroke-dasharray:1906px, 3812px;stroke-dashoffset:-2393px}}@keyframes load{to{transform:rotate(360deg)}}</style> <svg class=\"icon\" viewBox=\"0 0 1024 1024\"></svg> ",this.__ICO__=this.root.lastElementChild,this.drawPath()}get is(){return this.props.is}set is(o){o&&this.setAttribute("is",o)}drawPath(){var{is:o}=this.props,t=dict[o];this.__ICO__&&o&&t&&(this.__ICO__.innerHTML="loading"===o?t:`<path d="${t}" />`,this.__ICO__.classList.toggle("load","loading"===o))}attributeChangedCallback(o,t,e){if(null!==e&&t!==e)switch(o){case"is":this.props.is=e,e?this.drawPath():this.removeAttribute("is")}}};
|
|
||||||
|
|
||||||
if(!customElements.get('wc-icon')){
|
if(!customElements.get('wc-icon')){
|
||||||
customElements.define('wc-icon', Icon)
|
customElements.define('wc-icon', Icon)
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,764 @@
|
||||||
|
/*
|
||||||
|
* Fastest md5 implementation around (JKM md5).
|
||||||
|
* Credits: Joseph Myers
|
||||||
|
*
|
||||||
|
* @see http://www.myersdaily.org/joseph/javascript/md5-text.html
|
||||||
|
* @see http://jsperf.com/md5-shootout/7
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* this function is much faster,
|
||||||
|
so if possible we use it. Some IEs
|
||||||
|
are the only ones I know of that
|
||||||
|
need the idiotic second function,
|
||||||
|
generated by an if clause. */
|
||||||
|
var add32 = function(a, b) {
|
||||||
|
return (a + b) & 0xffffffff
|
||||||
|
},
|
||||||
|
hex_chr = [
|
||||||
|
'0',
|
||||||
|
'1',
|
||||||
|
'2',
|
||||||
|
'3',
|
||||||
|
'4',
|
||||||
|
'5',
|
||||||
|
'6',
|
||||||
|
'7',
|
||||||
|
'8',
|
||||||
|
'9',
|
||||||
|
'a',
|
||||||
|
'b',
|
||||||
|
'c',
|
||||||
|
'd',
|
||||||
|
'e',
|
||||||
|
'f'
|
||||||
|
]
|
||||||
|
|
||||||
|
function cmn(q, a, b, x, s, t) {
|
||||||
|
a = add32(add32(a, q), add32(x, t))
|
||||||
|
return add32((a << s) | (a >>> (32 - s)), b)
|
||||||
|
}
|
||||||
|
|
||||||
|
function md5cycle(x, k) {
|
||||||
|
var a = x[0],
|
||||||
|
b = x[1],
|
||||||
|
c = x[2],
|
||||||
|
d = x[3]
|
||||||
|
|
||||||
|
a += (((b & c) | (~b & d)) + k[0] - 680876936) | 0
|
||||||
|
a = (((a << 7) | (a >>> 25)) + b) | 0
|
||||||
|
d += (((a & b) | (~a & c)) + k[1] - 389564586) | 0
|
||||||
|
d = (((d << 12) | (d >>> 20)) + a) | 0
|
||||||
|
c += (((d & a) | (~d & b)) + k[2] + 606105819) | 0
|
||||||
|
c = (((c << 17) | (c >>> 15)) + d) | 0
|
||||||
|
b += (((c & d) | (~c & a)) + k[3] - 1044525330) | 0
|
||||||
|
b = (((b << 22) | (b >>> 10)) + c) | 0
|
||||||
|
a += (((b & c) | (~b & d)) + k[4] - 176418897) | 0
|
||||||
|
a = (((a << 7) | (a >>> 25)) + b) | 0
|
||||||
|
d += (((a & b) | (~a & c)) + k[5] + 1200080426) | 0
|
||||||
|
d = (((d << 12) | (d >>> 20)) + a) | 0
|
||||||
|
c += (((d & a) | (~d & b)) + k[6] - 1473231341) | 0
|
||||||
|
c = (((c << 17) | (c >>> 15)) + d) | 0
|
||||||
|
b += (((c & d) | (~c & a)) + k[7] - 45705983) | 0
|
||||||
|
b = (((b << 22) | (b >>> 10)) + c) | 0
|
||||||
|
a += (((b & c) | (~b & d)) + k[8] + 1770035416) | 0
|
||||||
|
a = (((a << 7) | (a >>> 25)) + b) | 0
|
||||||
|
d += (((a & b) | (~a & c)) + k[9] - 1958414417) | 0
|
||||||
|
d = (((d << 12) | (d >>> 20)) + a) | 0
|
||||||
|
c += (((d & a) | (~d & b)) + k[10] - 42063) | 0
|
||||||
|
c = (((c << 17) | (c >>> 15)) + d) | 0
|
||||||
|
b += (((c & d) | (~c & a)) + k[11] - 1990404162) | 0
|
||||||
|
b = (((b << 22) | (b >>> 10)) + c) | 0
|
||||||
|
a += (((b & c) | (~b & d)) + k[12] + 1804603682) | 0
|
||||||
|
a = (((a << 7) | (a >>> 25)) + b) | 0
|
||||||
|
d += (((a & b) | (~a & c)) + k[13] - 40341101) | 0
|
||||||
|
d = (((d << 12) | (d >>> 20)) + a) | 0
|
||||||
|
c += (((d & a) | (~d & b)) + k[14] - 1502002290) | 0
|
||||||
|
c = (((c << 17) | (c >>> 15)) + d) | 0
|
||||||
|
b += (((c & d) | (~c & a)) + k[15] + 1236535329) | 0
|
||||||
|
b = (((b << 22) | (b >>> 10)) + c) | 0
|
||||||
|
|
||||||
|
a += (((b & d) | (c & ~d)) + k[1] - 165796510) | 0
|
||||||
|
a = (((a << 5) | (a >>> 27)) + b) | 0
|
||||||
|
d += (((a & c) | (b & ~c)) + k[6] - 1069501632) | 0
|
||||||
|
d = (((d << 9) | (d >>> 23)) + a) | 0
|
||||||
|
c += (((d & b) | (a & ~b)) + k[11] + 643717713) | 0
|
||||||
|
c = (((c << 14) | (c >>> 18)) + d) | 0
|
||||||
|
b += (((c & a) | (d & ~a)) + k[0] - 373897302) | 0
|
||||||
|
b = (((b << 20) | (b >>> 12)) + c) | 0
|
||||||
|
a += (((b & d) | (c & ~d)) + k[5] - 701558691) | 0
|
||||||
|
a = (((a << 5) | (a >>> 27)) + b) | 0
|
||||||
|
d += (((a & c) | (b & ~c)) + k[10] + 38016083) | 0
|
||||||
|
d = (((d << 9) | (d >>> 23)) + a) | 0
|
||||||
|
c += (((d & b) | (a & ~b)) + k[15] - 660478335) | 0
|
||||||
|
c = (((c << 14) | (c >>> 18)) + d) | 0
|
||||||
|
b += (((c & a) | (d & ~a)) + k[4] - 405537848) | 0
|
||||||
|
b = (((b << 20) | (b >>> 12)) + c) | 0
|
||||||
|
a += (((b & d) | (c & ~d)) + k[9] + 568446438) | 0
|
||||||
|
a = (((a << 5) | (a >>> 27)) + b) | 0
|
||||||
|
d += (((a & c) | (b & ~c)) + k[14] - 1019803690) | 0
|
||||||
|
d = (((d << 9) | (d >>> 23)) + a) | 0
|
||||||
|
c += (((d & b) | (a & ~b)) + k[3] - 187363961) | 0
|
||||||
|
c = (((c << 14) | (c >>> 18)) + d) | 0
|
||||||
|
b += (((c & a) | (d & ~a)) + k[8] + 1163531501) | 0
|
||||||
|
b = (((b << 20) | (b >>> 12)) + c) | 0
|
||||||
|
a += (((b & d) | (c & ~d)) + k[13] - 1444681467) | 0
|
||||||
|
a = (((a << 5) | (a >>> 27)) + b) | 0
|
||||||
|
d += (((a & c) | (b & ~c)) + k[2] - 51403784) | 0
|
||||||
|
d = (((d << 9) | (d >>> 23)) + a) | 0
|
||||||
|
c += (((d & b) | (a & ~b)) + k[7] + 1735328473) | 0
|
||||||
|
c = (((c << 14) | (c >>> 18)) + d) | 0
|
||||||
|
b += (((c & a) | (d & ~a)) + k[12] - 1926607734) | 0
|
||||||
|
b = (((b << 20) | (b >>> 12)) + c) | 0
|
||||||
|
|
||||||
|
a += ((b ^ c ^ d) + k[5] - 378558) | 0
|
||||||
|
a = (((a << 4) | (a >>> 28)) + b) | 0
|
||||||
|
d += ((a ^ b ^ c) + k[8] - 2022574463) | 0
|
||||||
|
d = (((d << 11) | (d >>> 21)) + a) | 0
|
||||||
|
c += ((d ^ a ^ b) + k[11] + 1839030562) | 0
|
||||||
|
c = (((c << 16) | (c >>> 16)) + d) | 0
|
||||||
|
b += ((c ^ d ^ a) + k[14] - 35309556) | 0
|
||||||
|
b = (((b << 23) | (b >>> 9)) + c) | 0
|
||||||
|
a += ((b ^ c ^ d) + k[1] - 1530992060) | 0
|
||||||
|
a = (((a << 4) | (a >>> 28)) + b) | 0
|
||||||
|
d += ((a ^ b ^ c) + k[4] + 1272893353) | 0
|
||||||
|
d = (((d << 11) | (d >>> 21)) + a) | 0
|
||||||
|
c += ((d ^ a ^ b) + k[7] - 155497632) | 0
|
||||||
|
c = (((c << 16) | (c >>> 16)) + d) | 0
|
||||||
|
b += ((c ^ d ^ a) + k[10] - 1094730640) | 0
|
||||||
|
b = (((b << 23) | (b >>> 9)) + c) | 0
|
||||||
|
a += ((b ^ c ^ d) + k[13] + 681279174) | 0
|
||||||
|
a = (((a << 4) | (a >>> 28)) + b) | 0
|
||||||
|
d += ((a ^ b ^ c) + k[0] - 358537222) | 0
|
||||||
|
d = (((d << 11) | (d >>> 21)) + a) | 0
|
||||||
|
c += ((d ^ a ^ b) + k[3] - 722521979) | 0
|
||||||
|
c = (((c << 16) | (c >>> 16)) + d) | 0
|
||||||
|
b += ((c ^ d ^ a) + k[6] + 76029189) | 0
|
||||||
|
b = (((b << 23) | (b >>> 9)) + c) | 0
|
||||||
|
a += ((b ^ c ^ d) + k[9] - 640364487) | 0
|
||||||
|
a = (((a << 4) | (a >>> 28)) + b) | 0
|
||||||
|
d += ((a ^ b ^ c) + k[12] - 421815835) | 0
|
||||||
|
d = (((d << 11) | (d >>> 21)) + a) | 0
|
||||||
|
c += ((d ^ a ^ b) + k[15] + 530742520) | 0
|
||||||
|
c = (((c << 16) | (c >>> 16)) + d) | 0
|
||||||
|
b += ((c ^ d ^ a) + k[2] - 995338651) | 0
|
||||||
|
b = (((b << 23) | (b >>> 9)) + c) | 0
|
||||||
|
|
||||||
|
a += ((c ^ (b | ~d)) + k[0] - 198630844) | 0
|
||||||
|
a = (((a << 6) | (a >>> 26)) + b) | 0
|
||||||
|
d += ((b ^ (a | ~c)) + k[7] + 1126891415) | 0
|
||||||
|
d = (((d << 10) | (d >>> 22)) + a) | 0
|
||||||
|
c += ((a ^ (d | ~b)) + k[14] - 1416354905) | 0
|
||||||
|
c = (((c << 15) | (c >>> 17)) + d) | 0
|
||||||
|
b += ((d ^ (c | ~a)) + k[5] - 57434055) | 0
|
||||||
|
b = (((b << 21) | (b >>> 11)) + c) | 0
|
||||||
|
a += ((c ^ (b | ~d)) + k[12] + 1700485571) | 0
|
||||||
|
a = (((a << 6) | (a >>> 26)) + b) | 0
|
||||||
|
d += ((b ^ (a | ~c)) + k[3] - 1894986606) | 0
|
||||||
|
d = (((d << 10) | (d >>> 22)) + a) | 0
|
||||||
|
c += ((a ^ (d | ~b)) + k[10] - 1051523) | 0
|
||||||
|
c = (((c << 15) | (c >>> 17)) + d) | 0
|
||||||
|
b += ((d ^ (c | ~a)) + k[1] - 2054922799) | 0
|
||||||
|
b = (((b << 21) | (b >>> 11)) + c) | 0
|
||||||
|
a += ((c ^ (b | ~d)) + k[8] + 1873313359) | 0
|
||||||
|
a = (((a << 6) | (a >>> 26)) + b) | 0
|
||||||
|
d += ((b ^ (a | ~c)) + k[15] - 30611744) | 0
|
||||||
|
d = (((d << 10) | (d >>> 22)) + a) | 0
|
||||||
|
c += ((a ^ (d | ~b)) + k[6] - 1560198380) | 0
|
||||||
|
c = (((c << 15) | (c >>> 17)) + d) | 0
|
||||||
|
b += ((d ^ (c | ~a)) + k[13] + 1309151649) | 0
|
||||||
|
b = (((b << 21) | (b >>> 11)) + c) | 0
|
||||||
|
a += ((c ^ (b | ~d)) + k[4] - 145523070) | 0
|
||||||
|
a = (((a << 6) | (a >>> 26)) + b) | 0
|
||||||
|
d += ((b ^ (a | ~c)) + k[11] - 1120210379) | 0
|
||||||
|
d = (((d << 10) | (d >>> 22)) + a) | 0
|
||||||
|
c += ((a ^ (d | ~b)) + k[2] + 718787259) | 0
|
||||||
|
c = (((c << 15) | (c >>> 17)) + d) | 0
|
||||||
|
b += ((d ^ (c | ~a)) + k[9] - 343485551) | 0
|
||||||
|
b = (((b << 21) | (b >>> 11)) + c) | 0
|
||||||
|
|
||||||
|
x[0] = (a + x[0]) | 0
|
||||||
|
x[1] = (b + x[1]) | 0
|
||||||
|
x[2] = (c + x[2]) | 0
|
||||||
|
x[3] = (d + x[3]) | 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function md5blk(s) {
|
||||||
|
var md5blks = [],
|
||||||
|
i /* Andy King said do it this way. */
|
||||||
|
|
||||||
|
for (i = 0; i < 64; i += 4) {
|
||||||
|
md5blks[i >> 2] =
|
||||||
|
s.charCodeAt(i) +
|
||||||
|
(s.charCodeAt(i + 1) << 8) +
|
||||||
|
(s.charCodeAt(i + 2) << 16) +
|
||||||
|
(s.charCodeAt(i + 3) << 24)
|
||||||
|
}
|
||||||
|
return md5blks
|
||||||
|
}
|
||||||
|
|
||||||
|
function md5blk_array(a) {
|
||||||
|
var md5blks = [],
|
||||||
|
i /* Andy King said do it this way. */
|
||||||
|
|
||||||
|
for (i = 0; i < 64; i += 4) {
|
||||||
|
md5blks[i >> 2] =
|
||||||
|
a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24)
|
||||||
|
}
|
||||||
|
return md5blks
|
||||||
|
}
|
||||||
|
|
||||||
|
function md51(s) {
|
||||||
|
var n = s.length,
|
||||||
|
state = [1732584193, -271733879, -1732584194, 271733878],
|
||||||
|
i,
|
||||||
|
length,
|
||||||
|
tail,
|
||||||
|
tmp,
|
||||||
|
lo,
|
||||||
|
hi
|
||||||
|
|
||||||
|
for (i = 64; i <= n; i += 64) {
|
||||||
|
md5cycle(state, md5blk(s.substring(i - 64, i)))
|
||||||
|
}
|
||||||
|
s = s.substring(i - 64)
|
||||||
|
length = s.length
|
||||||
|
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3)
|
||||||
|
}
|
||||||
|
tail[i >> 2] |= 0x80 << (i % 4 << 3)
|
||||||
|
if (i > 55) {
|
||||||
|
md5cycle(state, tail)
|
||||||
|
for (i = 0; i < 16; i += 1) {
|
||||||
|
tail[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Beware that the final length might not fit in 32 bits so we take care of that
|
||||||
|
tmp = n * 8
|
||||||
|
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/)
|
||||||
|
lo = parseInt(tmp[2], 16)
|
||||||
|
hi = parseInt(tmp[1], 16) || 0
|
||||||
|
|
||||||
|
tail[14] = lo
|
||||||
|
tail[15] = hi
|
||||||
|
|
||||||
|
md5cycle(state, tail)
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
function md51_array(a) {
|
||||||
|
var n = a.length,
|
||||||
|
state = [1732584193, -271733879, -1732584194, 271733878],
|
||||||
|
i,
|
||||||
|
length,
|
||||||
|
tail,
|
||||||
|
tmp,
|
||||||
|
lo,
|
||||||
|
hi
|
||||||
|
|
||||||
|
for (i = 64; i <= n; i += 64) {
|
||||||
|
md5cycle(state, md5blk_array(a.subarray(i - 64, i)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not sure if it is a bug, however IE10 will always produce a sub array of length 1
|
||||||
|
// containing the last element of the parent array if the sub array specified starts
|
||||||
|
// beyond the length of the parent array - weird.
|
||||||
|
// https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
|
||||||
|
a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0)
|
||||||
|
|
||||||
|
length = a.length
|
||||||
|
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
tail[i >> 2] |= a[i] << (i % 4 << 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
tail[i >> 2] |= 0x80 << (i % 4 << 3)
|
||||||
|
if (i > 55) {
|
||||||
|
md5cycle(state, tail)
|
||||||
|
for (i = 0; i < 16; i += 1) {
|
||||||
|
tail[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Beware that the final length might not fit in 32 bits so we take care of that
|
||||||
|
tmp = n * 8
|
||||||
|
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/)
|
||||||
|
lo = parseInt(tmp[2], 16)
|
||||||
|
hi = parseInt(tmp[1], 16) || 0
|
||||||
|
|
||||||
|
tail[14] = lo
|
||||||
|
tail[15] = hi
|
||||||
|
|
||||||
|
md5cycle(state, tail)
|
||||||
|
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
function rhex(n) {
|
||||||
|
var s = '',
|
||||||
|
j
|
||||||
|
for (j = 0; j < 4; j += 1) {
|
||||||
|
s += hex_chr[(n >> (j * 8 + 4)) & 0x0f] + hex_chr[(n >> (j * 8)) & 0x0f]
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
function hex(x) {
|
||||||
|
var i
|
||||||
|
for (i = 0; i < x.length; i += 1) {
|
||||||
|
x[i] = rhex(x[i])
|
||||||
|
}
|
||||||
|
return x.join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
// In some cases the fast add32 function cannot be used..
|
||||||
|
if (hex(md51('hello')) !== '5d41402abc4b2a76b9719d911017c592') {
|
||||||
|
add32 = function(x, y) {
|
||||||
|
var lsw = (x & 0xffff) + (y & 0xffff),
|
||||||
|
msw = (x >> 16) + (y >> 16) + (lsw >> 16)
|
||||||
|
return (msw << 16) | (lsw & 0xffff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ArrayBuffer slice polyfill.
|
||||||
|
*
|
||||||
|
* @see https://github.com/ttaubert/node-arraybuffer-slice
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {
|
||||||
|
;(function() {
|
||||||
|
function clamp(val, length) {
|
||||||
|
val = val | 0 || 0
|
||||||
|
|
||||||
|
if (val < 0) {
|
||||||
|
return Math.max(val + length, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.min(val, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayBuffer.prototype.slice = function(from, to) {
|
||||||
|
var length = this.byteLength,
|
||||||
|
begin = clamp(from, length),
|
||||||
|
end = length,
|
||||||
|
num,
|
||||||
|
target,
|
||||||
|
targetArray,
|
||||||
|
sourceArray
|
||||||
|
|
||||||
|
if (to !== undefined) {
|
||||||
|
end = clamp(to, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (begin > end) {
|
||||||
|
return new ArrayBuffer(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
num = end - begin
|
||||||
|
target = new ArrayBuffer(num)
|
||||||
|
targetArray = new Uint8Array(target)
|
||||||
|
|
||||||
|
sourceArray = new Uint8Array(this, begin, num)
|
||||||
|
targetArray.set(sourceArray)
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helpers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function toUtf8(str) {
|
||||||
|
str += ''
|
||||||
|
if (/[\u0080-\uFFFF]/.test(str)) {
|
||||||
|
str = unescape(encodeURIComponent(str))
|
||||||
|
}
|
||||||
|
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
function utf8Str2ArrayBuffer(str, returnUInt8Array) {
|
||||||
|
var length = str.length,
|
||||||
|
buff = new ArrayBuffer(length),
|
||||||
|
arr = new Uint8Array(buff),
|
||||||
|
i
|
||||||
|
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
arr[i] = str.charCodeAt(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnUInt8Array ? arr : buff
|
||||||
|
}
|
||||||
|
|
||||||
|
function arrayBuffer2Utf8Str(buff) {
|
||||||
|
return String.fromCharCode.apply(null, new Uint8Array(buff))
|
||||||
|
}
|
||||||
|
|
||||||
|
function concatenateArrayBuffers(first, second, returnUInt8Array) {
|
||||||
|
var result = new Uint8Array(first.byteLength + second.byteLength)
|
||||||
|
|
||||||
|
result.set(new Uint8Array(first))
|
||||||
|
result.set(new Uint8Array(second), first.byteLength)
|
||||||
|
|
||||||
|
return returnUInt8Array ? result : result.buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
function hexToBinaryString(hex) {
|
||||||
|
var bytes = [],
|
||||||
|
length = hex.length,
|
||||||
|
x
|
||||||
|
|
||||||
|
for (x = 0; x < length - 1; x += 2) {
|
||||||
|
bytes.push(parseInt(hex.substr(x, 2), 16))
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.fromCharCode.apply(String, bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SparkMD5 OOP implementation.
|
||||||
|
*
|
||||||
|
* Use this class to perform an incremental md5, otherwise use the
|
||||||
|
* static methods instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function SparkMD5() {
|
||||||
|
// call reset to init the instance
|
||||||
|
this.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a string.
|
||||||
|
* A conversion will be applied if an utf8 string is detected.
|
||||||
|
*
|
||||||
|
* @param {String} str The string to be appended
|
||||||
|
*
|
||||||
|
* @return {SparkMD5} The instance itself
|
||||||
|
*/
|
||||||
|
SparkMD5.prototype.append = function(str) {
|
||||||
|
// Converts the string to utf8 bytes if necessary
|
||||||
|
// Then append as binary
|
||||||
|
this.appendBinary(toUtf8(str))
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends a binary string.
|
||||||
|
*
|
||||||
|
* @param {String} contents The binary string to be appended
|
||||||
|
*
|
||||||
|
* @return {SparkMD5} The instance itself
|
||||||
|
*/
|
||||||
|
SparkMD5.prototype.appendBinary = function(contents) {
|
||||||
|
this._buff += contents
|
||||||
|
this._length += contents.length
|
||||||
|
|
||||||
|
var length = this._buff.length,
|
||||||
|
i
|
||||||
|
|
||||||
|
for (i = 64; i <= length; i += 64) {
|
||||||
|
md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)))
|
||||||
|
}
|
||||||
|
|
||||||
|
this._buff = this._buff.substring(i - 64)
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finishes the incremental computation, reseting the internal state and
|
||||||
|
* returning the result.
|
||||||
|
*
|
||||||
|
* @param {Boolean} raw True to get the raw string, false to get the hex string
|
||||||
|
*
|
||||||
|
* @return {String} The result
|
||||||
|
*/
|
||||||
|
SparkMD5.prototype.end = function(raw) {
|
||||||
|
var buff = this._buff,
|
||||||
|
length = buff.length,
|
||||||
|
i,
|
||||||
|
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
ret
|
||||||
|
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
this._finish(tail, length)
|
||||||
|
ret = hex(this._hash)
|
||||||
|
|
||||||
|
if (raw) {
|
||||||
|
ret = hexToBinaryString(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.reset()
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the internal state of the computation.
|
||||||
|
*
|
||||||
|
* @return {SparkMD5} The instance itself
|
||||||
|
*/
|
||||||
|
SparkMD5.prototype.reset = function() {
|
||||||
|
this._buff = ''
|
||||||
|
this._length = 0
|
||||||
|
this._hash = [1732584193, -271733879, -1732584194, 271733878]
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the internal state of the computation.
|
||||||
|
*
|
||||||
|
* @return {Object} The state
|
||||||
|
*/
|
||||||
|
SparkMD5.prototype.getState = function() {
|
||||||
|
return {
|
||||||
|
buff: this._buff,
|
||||||
|
length: this._length,
|
||||||
|
hash: this._hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the internal state of the computation.
|
||||||
|
*
|
||||||
|
* @param {Object} state The state
|
||||||
|
*
|
||||||
|
* @return {SparkMD5} The instance itself
|
||||||
|
*/
|
||||||
|
SparkMD5.prototype.setState = function(state) {
|
||||||
|
this._buff = state.buff
|
||||||
|
this._length = state.length
|
||||||
|
this._hash = state.hash
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases memory used by the incremental buffer and other additional
|
||||||
|
* resources. If you plan to use the instance again, use reset instead.
|
||||||
|
*/
|
||||||
|
SparkMD5.prototype.destroy = function() {
|
||||||
|
delete this._hash
|
||||||
|
delete this._buff
|
||||||
|
delete this._length
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish the final calculation based on the tail.
|
||||||
|
*
|
||||||
|
* @param {Array} tail The tail (will be modified)
|
||||||
|
* @param {Number} length The length of the remaining buffer
|
||||||
|
*/
|
||||||
|
SparkMD5.prototype._finish = function(tail, length) {
|
||||||
|
var i = length,
|
||||||
|
tmp,
|
||||||
|
lo,
|
||||||
|
hi
|
||||||
|
|
||||||
|
tail[i >> 2] |= 0x80 << (i % 4 << 3)
|
||||||
|
if (i > 55) {
|
||||||
|
md5cycle(this._hash, tail)
|
||||||
|
for (i = 0; i < 16; i += 1) {
|
||||||
|
tail[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the final computation based on the tail and length
|
||||||
|
// Beware that the final length may not fit in 32 bits so we take care of that
|
||||||
|
tmp = this._length * 8
|
||||||
|
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/)
|
||||||
|
lo = parseInt(tmp[2], 16)
|
||||||
|
hi = parseInt(tmp[1], 16) || 0
|
||||||
|
|
||||||
|
tail[14] = lo
|
||||||
|
tail[15] = hi
|
||||||
|
md5cycle(this._hash, tail)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the md5 hash on a string.
|
||||||
|
* A conversion will be applied if utf8 string is detected.
|
||||||
|
*
|
||||||
|
* @param {String} str The string
|
||||||
|
* @param {Boolean} [raw] True to get the raw string, false to get the hex string
|
||||||
|
*
|
||||||
|
* @return {String} The result
|
||||||
|
*/
|
||||||
|
SparkMD5.hash = function(str, raw) {
|
||||||
|
// Converts the string to utf8 bytes if necessary
|
||||||
|
// Then compute it using the binary function
|
||||||
|
return SparkMD5.hashBinary(toUtf8(str), raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the md5 hash on a binary string.
|
||||||
|
*
|
||||||
|
* @param {String} content The binary string
|
||||||
|
* @param {Boolean} [raw] True to get the raw string, false to get the hex string
|
||||||
|
*
|
||||||
|
* @return {String} The result
|
||||||
|
*/
|
||||||
|
SparkMD5.hashBinary = function(content, raw) {
|
||||||
|
var hash = md51(content),
|
||||||
|
ret = hex(hash)
|
||||||
|
|
||||||
|
return raw ? hexToBinaryString(ret) : ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SparkMD5 OOP implementation for array buffers.
|
||||||
|
*
|
||||||
|
* Use this class to perform an incremental md5 ONLY for array buffers.
|
||||||
|
*/
|
||||||
|
SparkMD5.ArrayBuffer = function() {
|
||||||
|
// call reset to init the instance
|
||||||
|
this.reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends an array buffer.
|
||||||
|
*
|
||||||
|
* @param {ArrayBuffer} arr The array to be appended
|
||||||
|
*
|
||||||
|
* @return {SparkMD5.ArrayBuffer} The instance itself
|
||||||
|
*/
|
||||||
|
SparkMD5.ArrayBuffer.prototype.append = function(arr) {
|
||||||
|
var buff = concatenateArrayBuffers(this._buff.buffer, arr, true),
|
||||||
|
length = buff.length,
|
||||||
|
i
|
||||||
|
|
||||||
|
this._length += arr.byteLength
|
||||||
|
|
||||||
|
for (i = 64; i <= length; i += 64) {
|
||||||
|
md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)))
|
||||||
|
}
|
||||||
|
|
||||||
|
this._buff =
|
||||||
|
i - 64 < length
|
||||||
|
? new Uint8Array(buff.buffer.slice(i - 64))
|
||||||
|
: new Uint8Array(0)
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finishes the incremental computation, reseting the internal state and
|
||||||
|
* returning the result.
|
||||||
|
*
|
||||||
|
* @param {Boolean} raw True to get the raw string, false to get the hex string
|
||||||
|
*
|
||||||
|
* @return {String} The result
|
||||||
|
*/
|
||||||
|
SparkMD5.ArrayBuffer.prototype.end = function(raw) {
|
||||||
|
var buff = this._buff,
|
||||||
|
length = buff.length,
|
||||||
|
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
i,
|
||||||
|
ret
|
||||||
|
|
||||||
|
for (i = 0; i < length; i += 1) {
|
||||||
|
tail[i >> 2] |= buff[i] << (i % 4 << 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
this._finish(tail, length)
|
||||||
|
ret = hex(this._hash)
|
||||||
|
|
||||||
|
if (raw) {
|
||||||
|
ret = hexToBinaryString(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.reset()
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the internal state of the computation.
|
||||||
|
*
|
||||||
|
* @return {SparkMD5.ArrayBuffer} The instance itself
|
||||||
|
*/
|
||||||
|
SparkMD5.ArrayBuffer.prototype.reset = function() {
|
||||||
|
this._buff = new Uint8Array(0)
|
||||||
|
this._length = 0
|
||||||
|
this._hash = [1732584193, -271733879, -1732584194, 271733878]
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the internal state of the computation.
|
||||||
|
*
|
||||||
|
* @return {Object} The state
|
||||||
|
*/
|
||||||
|
SparkMD5.ArrayBuffer.prototype.getState = function() {
|
||||||
|
var state = SparkMD5.prototype.getState.call(this)
|
||||||
|
|
||||||
|
// Convert buffer to a string
|
||||||
|
state.buff = arrayBuffer2Utf8Str(state.buff)
|
||||||
|
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the internal state of the computation.
|
||||||
|
*
|
||||||
|
* @param {Object} state The state
|
||||||
|
*
|
||||||
|
* @return {SparkMD5.ArrayBuffer} The instance itself
|
||||||
|
*/
|
||||||
|
SparkMD5.ArrayBuffer.prototype.setState = function(state) {
|
||||||
|
// Convert string to buffer
|
||||||
|
state.buff = utf8Str2ArrayBuffer(state.buff, true)
|
||||||
|
|
||||||
|
return SparkMD5.prototype.setState.call(this, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy
|
||||||
|
|
||||||
|
SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the md5 hash on an array buffer.
|
||||||
|
*
|
||||||
|
* @param {ArrayBuffer} arr The array buffer
|
||||||
|
* @param {Boolean} [raw] True to get the raw string, false to get the hex one
|
||||||
|
*
|
||||||
|
* @return {String} The result
|
||||||
|
*/
|
||||||
|
SparkMD5.ArrayBuffer.hash = function(arr, raw) {
|
||||||
|
var hash = md51_array(new Uint8Array(arr)),
|
||||||
|
ret = hex(hash)
|
||||||
|
|
||||||
|
return raw ? hexToBinaryString(ret) : ret
|
||||||
|
}
|
||||||
|
|
||||||
|
var _sparkIns = new SparkMD5()
|
||||||
|
|
||||||
|
export function md5(str) {
|
||||||
|
_sparkIns.append(str)
|
||||||
|
return _sparkIns.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function md5Sum(binStr) {
|
||||||
|
_sparkIns.appendBinary(binStr)
|
||||||
|
return _sparkIns.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
export default _sparkIns
|
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
function noop(){}export default{nextTick:function(){let t=[];let e=document.createTextNode("\x3c!-- --\x3e");new MutationObserver(function(){let e=t.length;for(let n=0;n<e;n++)t[n]();t=t.slice(e)}).observe(e,{characterData:!0});let n=!1;return function(i){t.push(i),n=!n,e.data=n}}(),each(t,e){if(t)if(Array.isArray(t))for(let n,i=0;(n=t[i++])&&!1!==e(n,i-1););else for(let n in t)if(t.hasOwnProperty(n)&&!1===e(t[n],n))break},bind(t,e,n=noop,i=!1){let o=e.split(",");return this.each(o,function(e){e=e.trim(),t.addEventListener(e,n,i)}),n},catch(t,e,n,i){return this.bind(t,e,function(t){t.stopPropagation(),n&&n(t)},i)},unbind(t,e,n=noop,i=!1){let o=e.split(",");this.each(o,function(e){e=e.trim(),t.removeEventListener(e,n,i)})},outside(t,e=noop){return this.bind(document,"mousedown",n=>{if(n)if(n.path){for(var i=n.path.concat();i.length>3;)if(i.shift()===t)return}else{var o=n.explicitOriginalTarget||n.target;if(t===o||t.contains(o)||t.root&&t.root.contains(o))return}e(n)})},clearOutside(t=noop){this.unbind(document,"mousedown",t)}};
|
function noop(){}export default{nextTick:function(){let t=[];let e=document.createTextNode("\x3c!-- --\x3e");new MutationObserver((function(){let e=t.length;for(let n=0;n<e;n++)t[n]();t=t.slice(e)})).observe(e,{characterData:!0});let n=!1;return function(i){t.push(i),n=!n,e.data=n}}(),offset(t){try{var e=t.getBoundingClientRect();if(e.width||e.height||t.getClientRects().length){var n=t.ownerDocument,i=n.documentElement,o=n.defaultView;return{top:e.top+o.pageYOffset-i.clientTop,left:e.left+o.pageXOffset-i.clientLeft}}}catch(t){return{left:0,top:0}}},each(t,e){if(t)if(Array.isArray(t))for(let n,i=0;(n=t[i++])&&!1!==e(n,i-1););else for(let n in t)if(t.hasOwnProperty(n)&&!1===e(t[n],n))break},bind(t,e,n=noop,i=!1){let o=e.split(",");return this.each(o,(function(e){e=e.trim(),t.addEventListener(e,n,i)})),n},catch(t,e,n,i){return this.bind(t,e,(function(t){t.stopPropagation(),n&&n(t)}),i)},unbind(t,e,n=noop,i=!1){let o=e.split(",");this.each(o,(function(e){e=e.trim(),t.removeEventListener(e,n,i)}))},outside(t,e=noop){return this.bind(document,"mousedown",n=>{if(n)if(n.path){for(var i=n.path.concat();i.length>3;)if(i.shift()===t)return}else{var o=n.explicitOriginalTarget||n.target;if(t===o||t.contains(o)||t.root&&t.root.contains(o))return}e(n)})},clearOutside(t=noop){this.unbind(document,"mousedown",t)}};
|
10
src/main.js
10
src/main.js
|
@ -50,9 +50,9 @@ protocol.registerSchemesAsPrivileged([
|
||||||
app.once('ready', () => {
|
app.once('ready', () => {
|
||||||
// 注册协议
|
// 注册协议
|
||||||
protocol.registerStreamProtocol('app', function(req, cb) {
|
protocol.registerStreamProtocol('app', function(req, cb) {
|
||||||
var file = decodeURIComponent(
|
var file = decodeURIComponent(req.url.replace(/^app:\/\/local\//, ''))
|
||||||
req.url.replace(/^app:\/\/local\//, '')
|
.replace(/\#.*$/, '')
|
||||||
).replace(/\#.*$/, '')
|
.replace(/\?.*$/, '')
|
||||||
var ext = path.extname(file)
|
var ext = path.extname(file)
|
||||||
|
|
||||||
file = path.resolve(ROOT, file)
|
file = path.resolve(ROOT, file)
|
||||||
|
@ -71,6 +71,7 @@ app.once('ready', () => {
|
||||||
var ext = path.extname(file)
|
var ext = path.extname(file)
|
||||||
|
|
||||||
file = path.resolve(CACHE_DIR, file)
|
file = path.resolve(CACHE_DIR, file)
|
||||||
|
|
||||||
cb({
|
cb({
|
||||||
data: fs.origin.createReadStream(file),
|
data: fs.origin.createReadStream(file),
|
||||||
mimeType: MIME_TYPES[ext] || MIME_TYPES.all,
|
mimeType: MIME_TYPES[ext] || MIME_TYPES.all,
|
||||||
|
@ -82,10 +83,9 @@ app.once('ready', () => {
|
||||||
|
|
||||||
// 创建浏览器窗口
|
// 创建浏览器窗口
|
||||||
app.__main__ = createMainWindow(path.resolve(ROOT, './images/app.png'))
|
app.__main__ = createMainWindow(path.resolve(ROOT, './images/app.png'))
|
||||||
app.__view__ = createViewWindow()
|
|
||||||
|
|
||||||
createMenu(app.__main__)
|
createMenu(app.__main__)
|
||||||
Socket(app)
|
Socket(app, createViewWindow)
|
||||||
|
|
||||||
app.__main__.on('closed', () => {
|
app.__main__.on('closed', () => {
|
||||||
app.__main__ = null
|
app.__main__ = null
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* @date 2021/01/04 14:58:46
|
* @date 2021/01/04 14:58:46
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { app, ipcMain, net } = require('electron')
|
const { app, ipcMain } = require('electron')
|
||||||
const fs = require('iofs')
|
const fs = require('iofs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const Epub = require('epub')
|
const Epub = require('epub')
|
||||||
|
@ -13,42 +13,39 @@ const HOME = path.resolve(app.getPath('userData'))
|
||||||
const DB_FILE = path.join(HOME, 'app.cache')
|
const DB_FILE = path.join(HOME, 'app.cache')
|
||||||
const CACHE_DIR = path.join(HOME, 'book_cache')
|
const CACHE_DIR = path.join(HOME, 'book_cache')
|
||||||
|
|
||||||
function fetch(url) {
|
module.exports = function(app, createViewWindow) {
|
||||||
return new Promise((y, n) => {
|
|
||||||
var conn = net.request(url)
|
|
||||||
var r = []
|
|
||||||
|
|
||||||
conn.on('response', res => {
|
|
||||||
res.on('data', c => {
|
|
||||||
r.push(c)
|
|
||||||
})
|
|
||||||
|
|
||||||
res.on('end', _ => {
|
|
||||||
y(Buffer.concat(r).toString())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
conn.on('error', e => {
|
|
||||||
n(e)
|
|
||||||
})
|
|
||||||
|
|
||||||
conn.end()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = function(app) {
|
|
||||||
ipcMain.on('app', (ev, conn) => {
|
ipcMain.on('app', (ev, conn) => {
|
||||||
switch (conn.type) {
|
switch (conn.type) {
|
||||||
case 'fetch':
|
|
||||||
fetch(conn.data).then(r => {
|
|
||||||
ev.returnValue = r
|
|
||||||
})
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'get-books':
|
case 'get-books':
|
||||||
ev.returnValue = JSON.parse(fs.cat(DB_FILE))
|
ev.returnValue = JSON.parse(fs.cat(DB_FILE))
|
||||||
break
|
break
|
||||||
|
|
||||||
|
case 'save-books':
|
||||||
|
fs.echo(JSON.stringify(conn.data), DB_FILE)
|
||||||
|
ev.returnValue = true
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'read':
|
||||||
|
if (app.__view__) {
|
||||||
|
// 打开同一个文档, 直接忽略
|
||||||
|
if (app.__view__.__title__ === conn.data.title) {
|
||||||
|
app.__view__.focus()
|
||||||
|
ev.returnValue = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
app.__view__.destroy()
|
||||||
|
}
|
||||||
|
app.__view__ = createViewWindow(conn.data)
|
||||||
|
app.__view__.__title__ = conn.data.title
|
||||||
|
ev.returnValue = true
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'delete-book':
|
||||||
|
let dir = path.join(CACHE_DIR, conn.data)
|
||||||
|
fs.rm(dir, true)
|
||||||
|
ev.returnValue = true
|
||||||
|
break
|
||||||
|
|
||||||
case 'parse-book':
|
case 'parse-book':
|
||||||
let { book, cate } = conn.data
|
let { book, cate } = conn.data
|
||||||
let eb = new Epub(book.path)
|
let eb = new Epub(book.path)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* @date 2020/12/10 14:57:49
|
* @date 2020/12/10 14:57:49
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { BrowserWindow } = require('electron')
|
const { app, BrowserWindow } = require('electron')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用主窗口
|
* 应用主窗口
|
||||||
|
@ -27,21 +27,23 @@ exports.createMainWindow = function(icon) {
|
||||||
|
|
||||||
win.loadURL('app://local/index.html')
|
win.loadURL('app://local/index.html')
|
||||||
|
|
||||||
// win.on('ready-to-show', _ => {
|
win.on('ready-to-show', _ => {
|
||||||
// win.show()
|
win.show()
|
||||||
// win.openDevTools()
|
// win.openDevTools()
|
||||||
// })
|
})
|
||||||
|
|
||||||
win.on('close', ev => {
|
win.on('close', ev => {
|
||||||
ev.preventDefault()
|
if (app.__view__) {
|
||||||
win.hide()
|
ev.preventDefault()
|
||||||
|
win.hide()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return win
|
return win
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建悬浮窗口
|
// 创建悬浮窗口
|
||||||
exports.createViewWindow = function() {
|
exports.createViewWindow = function(params) {
|
||||||
var win = new BrowserWindow({
|
var win = new BrowserWindow({
|
||||||
width: 1024,
|
width: 1024,
|
||||||
height: 768,
|
height: 768,
|
||||||
|
@ -56,9 +58,13 @@ exports.createViewWindow = function() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
win.openDevTools()
|
// win.openDevTools()
|
||||||
|
|
||||||
win.loadURL('app://local/view.html')
|
win.loadURL('app://local/view.html?' + params)
|
||||||
|
|
||||||
|
win.on('closed', ev => {
|
||||||
|
app.__view__ = null
|
||||||
|
})
|
||||||
|
|
||||||
return win
|
return win
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="app" anot="app">
|
<div class="app" anot="app">
|
||||||
<wc-scroll class="toc noselect">
|
<wc-scroll class="toc noselect" ref="toc">
|
||||||
<item
|
<item
|
||||||
:for="it in toc"
|
:for="it in toc"
|
||||||
:class="{['lev-' + it.level]: 1, active: it.title === curr}"
|
:class="{['lev-' + it.level]: 1, active: it.title === curr}"
|
||||||
|
|
Loading…
Reference in New Issue