2019-11-29 22:07:31 +01:00
|
|
|
|
2019-11-24 20:33:14 +01:00
|
|
|
class BookletEntry
|
2020-06-06 23:49:13 +02:00
|
|
|
constructor: (@text) ->
|
2019-11-29 22:07:31 +01:00
|
|
|
@loaded = true
|
2019-11-28 18:35:55 +01:00
|
|
|
|
2019-11-24 20:33:14 +01:00
|
|
|
save: () ->
|
|
|
|
|
|
|
|
remove: () ->
|
|
|
|
|
|
|
|
toc: () ->
|
2019-11-28 18:35:55 +01:00
|
|
|
|
2019-11-26 22:35:25 +01:00
|
|
|
|
2019-11-28 18:35:55 +01:00
|
|
|
updateName:() ->
|
2020-06-06 23:49:13 +02:00
|
|
|
# return @text unless @descFile.dirty
|
2019-11-28 23:11:46 +01:00
|
|
|
t = (new RegExp "^\s*#+(.*)\n", "g").exec @descFile.cache
|
2020-06-06 23:49:13 +02:00
|
|
|
return @text unless t and t.length is 2
|
2019-11-29 22:07:31 +01:00
|
|
|
@metaFile.dirty = true if @hasMeta and @metaFile
|
|
|
|
@parent.metaFile.dirty = true if @parent and @parent.hasMeta and @parent.metaFile
|
2020-06-06 23:49:13 +02:00
|
|
|
@text = t[1].trim()
|
2019-11-28 23:11:46 +01:00
|
|
|
|
|
|
|
remove: () ->
|
2020-06-06 23:49:13 +02:00
|
|
|
return new Promise (r, e) =>
|
|
|
|
f = @path.asFileHandle()
|
|
|
|
f.meta().then (d) =>
|
|
|
|
f.remove().then (ret) =>
|
|
|
|
return r() unless @parent
|
|
|
|
@parent.removeChild(@).then () ->
|
2019-11-28 23:11:46 +01:00
|
|
|
r()
|
2020-06-06 23:49:13 +02:00
|
|
|
.catch (msg) -> e __e msg
|
|
|
|
.catch (msg) -> e __e msg
|
|
|
|
.catch (msg) =>
|
|
|
|
return r() unless @parent
|
|
|
|
return @parent.removeChild(@).then () ->
|
|
|
|
r()
|
|
|
|
.catch (msg) -> e __e msg
|
2019-11-24 20:33:14 +01:00
|
|
|
|
|
|
|
class BookletFolder extends BookletEntry
|
2019-11-28 18:35:55 +01:00
|
|
|
constructor: (@type, @path, @hasMeta) ->
|
2019-11-29 22:07:31 +01:00
|
|
|
super "Untitle"
|
|
|
|
@init()
|
|
|
|
|
|
|
|
init: () ->
|
2019-11-28 23:11:46 +01:00
|
|
|
@cnt = 0
|
2019-11-28 18:35:55 +01:00
|
|
|
@nodes = []
|
2020-06-06 23:49:13 +02:00
|
|
|
@metaFile = "#{@path}/meta.json".asFileHandle() if @hasMeta
|
|
|
|
@descFile = "#{@path}/INTRO.md".asFileHandle()
|
2019-11-24 20:33:14 +01:00
|
|
|
|
2020-07-10 14:01:52 +02:00
|
|
|
up: (node) ->
|
|
|
|
return unless node
|
|
|
|
idx = @nodes.indexOf node
|
|
|
|
return unless idx > 0
|
|
|
|
@nodes.splice idx, 1
|
|
|
|
@nodes.splice idx-1, 0, node
|
|
|
|
|
|
|
|
down: (node) ->
|
|
|
|
return unless node
|
|
|
|
idx = @nodes.indexOf node
|
|
|
|
return unless idx >= 0 and idx < @nodes.length - 1
|
|
|
|
@nodes.splice idx, 1
|
|
|
|
@nodes.splice idx + 1, 0, node
|
|
|
|
|
|
|
|
|
2019-11-28 18:35:55 +01:00
|
|
|
add: (chap) ->
|
|
|
|
chap.parent = @
|
2020-09-15 12:40:06 +02:00
|
|
|
chap.root = @root
|
2019-11-28 18:35:55 +01:00
|
|
|
@nodes.push chap
|
2019-11-28 23:11:46 +01:00
|
|
|
@metaFile.dirty = true if @hasMeta and @metaFile
|
|
|
|
chap.metaFile.dirty = true if chap.metaFile and chap.hasMeta
|
|
|
|
@cnt = @cnt + 1
|
|
|
|
|
|
|
|
removeChild: (child) ->
|
2020-06-06 23:49:13 +02:00
|
|
|
|
2019-11-28 23:11:46 +01:00
|
|
|
#v.treepath = v.path for v in @nodes if @nodes
|
2020-06-06 23:49:13 +02:00
|
|
|
return new Promise (r, e) =>
|
|
|
|
@nodes.splice (@nodes.indexOf child), 1
|
|
|
|
#if @nodes.includes child
|
|
|
|
return r() unless @hasMeta and @metaFile
|
|
|
|
@metaFile.dirty = true
|
|
|
|
@updateMeta().then () ->
|
2019-11-28 23:11:46 +01:00
|
|
|
r()
|
2020-06-06 23:49:13 +02:00
|
|
|
.catch (msg) -> e __e msg
|
|
|
|
|
2019-11-29 22:07:31 +01:00
|
|
|
read: (folderPath) ->
|
2020-06-06 23:49:13 +02:00
|
|
|
|
|
|
|
return new Promise (r, e) =>
|
|
|
|
@path = folderPath
|
|
|
|
@init()
|
|
|
|
@loaded = false
|
|
|
|
@metaFile.meta().then (d) =>
|
|
|
|
@metaFile.read("json").then (data) =>
|
2019-11-29 22:07:31 +01:00
|
|
|
# load all child
|
2020-06-06 23:49:13 +02:00
|
|
|
@text = data.name
|
2019-11-29 22:07:31 +01:00
|
|
|
list = []
|
|
|
|
list[i] = v for v,i in data.entries
|
2020-06-06 23:49:13 +02:00
|
|
|
fn = (l) =>
|
2019-11-29 22:07:31 +01:00
|
|
|
if l.length is 0
|
2020-06-06 23:49:13 +02:00
|
|
|
@cnt = data.cnt
|
2019-11-29 22:07:31 +01:00
|
|
|
return r()
|
|
|
|
el = (l.splice 0, 1)[0]
|
2020-06-06 23:49:13 +02:00
|
|
|
obj = new NS[el.type]( @ )
|
2019-11-29 22:07:31 +01:00
|
|
|
obj.name = el.name
|
2020-09-15 12:40:06 +02:00
|
|
|
obj.read(el.path.replace("book://", @root)).then () =>
|
2019-11-29 22:07:31 +01:00
|
|
|
fn l
|
2020-06-06 23:49:13 +02:00
|
|
|
.catch (msg) =>
|
2019-11-29 22:07:31 +01:00
|
|
|
fn l
|
|
|
|
|
|
|
|
return fn list
|
2020-06-06 23:49:13 +02:00
|
|
|
.catch (msg) -> e __e msg
|
|
|
|
.catch (msg) -> e __e msg
|
2019-11-24 20:33:14 +01:00
|
|
|
|
|
|
|
size: () ->
|
2019-11-28 18:35:55 +01:00
|
|
|
return @nodes.length
|
2019-11-26 20:23:28 +01:00
|
|
|
|
2019-11-28 18:35:55 +01:00
|
|
|
mkdir: () ->
|
2020-06-06 23:49:13 +02:00
|
|
|
|
|
|
|
return new Promise (r, e) =>
|
|
|
|
dir = @path.asFileHandle()
|
|
|
|
dir.meta().then (d) =>
|
|
|
|
return r()
|
|
|
|
.catch (ex) =>
|
2019-11-28 18:35:55 +01:00
|
|
|
bname = dir.basename
|
2020-06-06 23:49:13 +02:00
|
|
|
dir = dir.parent().asFileHandle()
|
|
|
|
dir.mk bname
|
|
|
|
.then (result) => r()
|
|
|
|
.catch (msg) -> e __e msg
|
2019-11-28 18:35:55 +01:00
|
|
|
|
|
|
|
mkdirs: () ->
|
2020-06-06 23:49:13 +02:00
|
|
|
|
|
|
|
return new Promise (r, e) =>
|
2019-11-28 18:35:55 +01:00
|
|
|
list = []
|
2020-06-06 23:49:13 +02:00
|
|
|
list[i] = v for v, i in @nodes if @type isnt 'Section'
|
|
|
|
@mkdir().then () =>
|
|
|
|
fn = (l) =>
|
2019-11-28 18:35:55 +01:00
|
|
|
return r() if l.length is 0
|
|
|
|
el = (l.splice 0, 1)[0]
|
2020-06-06 23:49:13 +02:00
|
|
|
el.mkdirs().then () =>
|
2019-11-28 18:35:55 +01:00
|
|
|
fn l
|
2020-06-06 23:49:13 +02:00
|
|
|
.catch (msg) -> e __e msg
|
2019-11-28 18:35:55 +01:00
|
|
|
return fn list
|
2020-06-06 23:49:13 +02:00
|
|
|
.catch (msg) -> e __e msg
|
2019-11-28 18:35:55 +01:00
|
|
|
|
|
|
|
|
2019-11-28 23:11:46 +01:00
|
|
|
updateMeta: () ->
|
2020-06-06 23:49:13 +02:00
|
|
|
|
|
|
|
return new Promise (r, e) =>
|
|
|
|
return r() unless @metaFile.dirty
|
2019-11-28 23:11:46 +01:00
|
|
|
entries = []
|
2020-09-15 12:40:06 +02:00
|
|
|
entries[i] = {name: v.name, path:v.path.replace( @root, "book://" ), type:v.type} for v,i in @nodes
|
2019-11-29 22:07:31 +01:00
|
|
|
data = {
|
2020-06-06 23:49:13 +02:00
|
|
|
name: @text,
|
2019-11-29 22:07:31 +01:00
|
|
|
entries: entries,
|
2020-06-06 23:49:13 +02:00
|
|
|
cnt: @cnt,
|
|
|
|
meta: @hasMeta
|
2019-11-29 22:07:31 +01:00
|
|
|
}
|
2020-06-06 23:49:13 +02:00
|
|
|
@metaFile.cache = data
|
|
|
|
@metaFile.write "object"
|
|
|
|
.then (d) =>
|
|
|
|
@metaFile.dirty = false
|
|
|
|
r()
|
|
|
|
.catch (msg) -> e __e msg
|
2019-11-28 23:11:46 +01:00
|
|
|
|
|
|
|
|
|
|
|
update: () ->
|
2020-06-06 23:49:13 +02:00
|
|
|
|
|
|
|
return new Promise (r, e) =>
|
|
|
|
@updateMeta().then () =>
|
|
|
|
return r() unless @descFile.dirty
|
|
|
|
@descFile.write "text/plain"
|
|
|
|
.then (d) =>
|
|
|
|
@descFile.dirty = false
|
|
|
|
#console.log "saved " + @descFile.path
|
|
|
|
r()
|
|
|
|
.catch (msg) -> e __e msg
|
|
|
|
.catch (msg) -> e __e msg
|
2019-11-28 23:11:46 +01:00
|
|
|
|
|
|
|
|
|
|
|
updateAll: () ->
|
2020-06-06 23:49:13 +02:00
|
|
|
|
|
|
|
return new Promise (r, e) =>
|
2019-11-28 23:11:46 +01:00
|
|
|
list = []
|
2020-06-06 23:49:13 +02:00
|
|
|
list[i] = v for v, i in @nodes
|
|
|
|
@update().then () =>
|
|
|
|
fn = (l) =>
|
2019-11-28 23:11:46 +01:00
|
|
|
return r() if l.length is 0
|
|
|
|
el = (l.splice 0, 1)[0]
|
2020-06-06 23:49:13 +02:00
|
|
|
el.updateAll().then () =>
|
2019-11-28 23:11:46 +01:00
|
|
|
fn l
|
2020-06-06 23:49:13 +02:00
|
|
|
.catch (msg) -> e __e msg
|
2019-11-28 23:11:46 +01:00
|
|
|
return fn list
|
2020-06-06 23:49:13 +02:00
|
|
|
.catch (msg) -> e __e msg
|
2019-11-24 20:33:14 +01:00
|
|
|
|
|
|
|
toc: () ->
|
2019-11-28 18:35:55 +01:00
|
|
|
@updateName()
|
|
|
|
v.toc() for v in @nodes
|
|
|
|
@
|
2019-11-24 20:33:14 +01:00
|
|
|
|
2019-11-28 18:35:55 +01:00
|
|
|
|
2019-11-29 22:07:31 +01:00
|
|
|
class BookletBook extends BookletFolder
|
2019-11-28 18:35:55 +01:00
|
|
|
constructor: (path) ->
|
2019-11-29 22:07:31 +01:00
|
|
|
super 'Book', path, true
|
2020-09-15 12:40:06 +02:00
|
|
|
|
|
|
|
init: () ->
|
|
|
|
super.init()
|
|
|
|
@root = @path
|
2019-11-28 23:11:46 +01:00
|
|
|
|
|
|
|
save:() ->
|
2020-06-06 23:49:13 +02:00
|
|
|
|
|
|
|
return new Promise (r, e) =>
|
|
|
|
@mkdirs().then () =>
|
|
|
|
@updateAll().then () =>
|
2019-11-28 23:11:46 +01:00
|
|
|
r()
|
2020-06-06 23:49:13 +02:00
|
|
|
.catch (msg) -> e __e msg
|
|
|
|
. catch (msg) -> e __e msg
|
2019-11-28 18:35:55 +01:00
|
|
|
|
|
|
|
|
|
|
|
class BookletChapter extends BookletFolder
|
|
|
|
constructor: (book) ->
|
2019-11-28 23:11:46 +01:00
|
|
|
path = "#{book.path}/c_#{book.cnt}"
|
2019-11-29 22:07:31 +01:00
|
|
|
super 'Chapter', path, true
|
2019-11-28 18:35:55 +01:00
|
|
|
book.add @
|
2019-11-26 22:35:25 +01:00
|
|
|
|
2019-11-24 20:33:14 +01:00
|
|
|
|
|
|
|
class BookletSection extends BookletFolder
|
2019-11-28 18:35:55 +01:00
|
|
|
constructor: (chapter) ->
|
2019-11-28 23:11:46 +01:00
|
|
|
path = "#{chapter.path}/s_#{chapter.cnt}"
|
2019-11-29 22:07:31 +01:00
|
|
|
super "Section", path, true
|
2019-11-28 18:35:55 +01:00
|
|
|
chapter.add @
|
|
|
|
|
2019-11-24 20:33:14 +01:00
|
|
|
|
|
|
|
class BookletFile extends BookletEntry
|
|
|
|
constructor: (@section) ->
|
2019-11-29 22:07:31 +01:00
|
|
|
super "Untitle file"
|
2019-11-28 23:11:46 +01:00
|
|
|
@hasMeta = false
|
2019-11-29 22:07:31 +01:00
|
|
|
@type = "File"
|
2019-11-28 23:11:46 +01:00
|
|
|
@path = "#{@section.path}/f_#{@section.cnt}.md"
|
2020-06-06 23:49:13 +02:00
|
|
|
@descFile = @path.asFileHandle()
|
2019-11-28 23:11:46 +01:00
|
|
|
@section.add @
|
2019-11-24 20:33:14 +01:00
|
|
|
|
2019-11-28 23:11:46 +01:00
|
|
|
updateAll: ()->
|
2020-06-06 23:49:13 +02:00
|
|
|
|
|
|
|
return new Promise (r, e) =>
|
|
|
|
return r() unless @descFile.dirty
|
|
|
|
@descFile.write "text/plain"
|
|
|
|
.then (d) =>
|
|
|
|
@descFile.dirty = false
|
|
|
|
#console.log "saved" + @descFile.path
|
|
|
|
r()
|
|
|
|
.catch (msg) => e __e msg
|
2019-11-28 23:11:46 +01:00
|
|
|
|
2019-11-29 22:07:31 +01:00
|
|
|
read: (p) ->
|
2020-06-06 23:49:13 +02:00
|
|
|
return new Promise (r, e) =>
|
|
|
|
@loaded = false
|
|
|
|
@treepath = p
|
|
|
|
@path = p
|
|
|
|
@descFile = @path.asFileHandle()
|
2019-11-29 22:07:31 +01:00
|
|
|
r()
|
|
|
|
|
2019-11-24 20:33:14 +01:00
|
|
|
toc: () ->
|
2019-11-28 18:35:55 +01:00
|
|
|
@updateName()
|
2019-11-29 22:07:31 +01:00
|
|
|
@
|
|
|
|
|
|
|
|
NS =
|
|
|
|
Book: BookletBook
|
|
|
|
Chapter: BookletChapter
|
|
|
|
Section: BookletSection
|
|
|
|
File: BookletFile
|