Archive for the ‘EPUB’ Tag
newLISP で EPUB を表示させる(改良編)
Googleの電子書籍サービス「Google eBooks」が開始されたとのこと。
日本は、まだ対応外なのですが、google アカウントを使って、無料の本を見ることができます。
試しに、Charles Dickens の “Bleak House” を EPUB 形式でダウンロードして、EPUB を zip 解凍すると、
META-INF - container.xml OEBPS - content - data - _toc_ncx_.ncx - volume.opf mimetype
こんな感じに展開されます。ブクログにある拙作の書籍の構造とは、少し違うようです。
また、書籍の本体は、content フォルダの下に content-XXXX.xml というファイル名になっていました。
ということで、さっそく、拙作 EPUB-Viewer を対応させました。
; utility
(define *newlispDir* (env "NEWLISPDIR"))
(load (append *newlispDir* "/guiserver.lsp"))
; define macro
(module "macro.lsp")
(macro (parse-path P) (parse P {\\|/} 0))
; define handler
(define *fileDir* (real-path))
(define *fileNames* '())
(define *index* 0)
(define *filemask* "html xhtml xml")
(define *description* "HTML file")
(define (book-display file)
(when (file? file)
(let (ptmp (parse-path file)
book (replace {<\?.+\?>} (read-file file) "" 0))
(gs:set-text 'fileLabel (ptmp -1))
(unless (null? book)
(replace {<meta http-equiv[^>]*>} book "" 4)
(replace {src="../}
book
(string {src="file:///} (join (chop ptmp 2) "/" true)))
(gs:set-text 'OutputArea book)))))
(define (next-action id)
(let (f-max (length *fileNames*))
((if (starts-with ((parse id) -1) "pre") -- ++) *index*)
(if (< *index*) (setq *index* (i- f-max))
(< *index* f-max) nil
(setq *index* 0))
(book-display (append *fileDir* (*fileNames* *index*)))))
(define (openfile-action id op file)
(when file
(setq *fileDir* (base64-dec file))
(if (directory? *fileDir*)
(setq *fileDir* (append *fileDir* "/"))
(let (tmp (parse-path *fileDir*))
(setq *fileDir* (append (join (chop tmp) "/" true)))
(setq *fileName* (tmp -1))))
(gs:set-text 'Status *fileDir*)
(setq *fileNames* (sort (directory *fileDir* "html*$|xml$" 1)))
(setq *index* 0)
(if *fileName* (setq *index* (find *fileName* *fileNames*))
(setq *fileName* (*fileNames* 0)))
(book-display (append *fileDir* (*fileNames* *index*)))))
(define (open-file-dialog)
(gs:open-file-dialog 'Frame 'openfile-action *fileDir* *filemask* *description*))
; initialization
(gs:init)
(define FPosX 100)
(define FPosY 50)
(define FWidth 640)
(define FHeight 480)
(gs:frame 'Frame FPosX FPosY FWidth FHeight "Simple EPUB Viewer")
(gs:panel 'ButtonPanel)
(gs:panel 'StatusPanel)
(gs:label 'Status (real-path))
(gs:label 'fileLabel "")
(gs:button 'preBtn 'next-action "<")
(gs:button 'nextBtn 'next-action ">")
(gs:button 'fileButton 'open-file-dialog "File")
(gs:text-pane 'OutputArea 'gs:no-action "text/html")
(gs:add-to 'ButtonPanel 'preBtn 'fileLabel 'nextBtn)
(gs:add-to 'StatusPanel 'fileButton 'Status)
; mount all on frame
(gs:set-border-layout 'Frame)
(gs:set-flow-layout 'ButtonPanel "center")
(gs:set-flow-layout 'StatusPanel "left")
(gs:add-to 'Frame 'ButtonPanel "north" 'OutputArea "center" 'StatusPanel "south")
(gs:set-visible 'Frame true)
; main routine
(gs:listen)
(exit)
主な変更点は、対応ファイル拡張子(xml)の追加です(笑)。ついでに、画像の表示も。
これを実行し、File ボタンを押して、zip 解凍しておいた先程の content フォルダを指定すれば、
一応、対応している画像ファイルはずが、、、何故か、うまく表示されません。
でも、本文を読むだけなら、
問題なさそうです。
あとは、zip 解凍か、、、(汗)
以上、如何でしょうか?
newLISP で GUI する。。。または、EPUB を表示させる?(解説編)
newLISP で GUI する。。。または、EPUB を表示させる?(解説編)
前回の EPUB Viewer は、如何だったでしょうか?
EPUB の本体は、XHTML のサブセットですが、そのままでは、gs:text-pane で表示できません。
<head></head> タグが邪魔しているようなのです。
そのためスクリプトでは、
(letn (str (read-file file)
book ((find {} str) str))
(gs:set-text 'OutputArea (0 (+ (find {} book) 7) book)))
こんな感じで、本文が入っている <body></body> を抜き出して表示させています。
本来に立ち戻って、<head></head> タグだけを削除するなら、
(letn (str (replace {} (read-file file) "" 0)
book1 (aif (find {} str) (0 it str) str)
book2 (aif (find {} str) ((+ it 7) str) "")
book (append book1 book2))
(gs:set-text 'OutputArea book))
こうすべきでした。先頭の削除宣言文は、xhtml の宣言文(?)の削除です。gs:text-pane では、そのまま表示されてしまうので。
また、ファイル名を取得するには、組込directory の正規表現オプションを使って、
(directory *fileDir* "[^.+]" 1)
としていました。これは、"." と ".." 以外のファイル名を取り込みます。
HTMLファイルだけを取り込むようにするには、
(directory *fileDir* "html*$" 1)
こんな感じ。ドットを付加しなかったのは、をEPUB の拡張子が .xhtml だから。
私の場合、あんまり、正規表現にこだわると、失敗するので(汗)。
これらを、前回の EPUB Viewer に適用すると、
(include は init.lsp に、aif は newlisp-utility.lsp に定義してあります。)
; utility
(define *newlispDir* (env "NEWLISPDIR"))
(load (append *newlispDir* "/guiserver.lsp"))
(include "macro.lsp")
; define sub-routine
(macro (parse-path P)
(parse P {\\|/} 0))
; define handler
(define *fileDir* (real-path))
(define *fileNames* '())
(define *index* 0)
(define *filemask* "html xhtml")
(define *description* "HTML file")
(define (book-display file)
(when (file? file)
(gs:set-text 'fileLabel ((parse-path file) -1))
(letn (str (replace {<\?.+\?>} (read-file file) "" 0)
book1 (aif (find {<head>} str) (0 it str) str)
book2 (aif (find {</head>} str) ((+ it 7) str) "")
book (append book1 book2))
(replace {src="../}
book
(string {src="file:///} (join (chop (parse-path *fileDir*)) "/" true)))
(gs:set-text 'OutputArea book))))
(define (next-action id)
(let (f-max (length *fileNames*))
((if (starts-with ((parse id) -1) "pre") -- ++) *index*)
(if (< *index*) (setq *index* (i- f-max))
(< *index* f-max) nil
(setq *index* 0))
(book-display (append *fileDir* (*fileNames* *index*)))))
(define (openfile-action id op file)
(when file
(setq *fileDir* (base64-dec file))
(if (directory? *fileDir*)
(setq *fileDir* (append *fileDir* "/"))
(let (tmp (parse-path *fileDir*))
(setq *fileDir* (append (join (chop tmp) "/" true)))
(setq *fileName* (tmp -1))))
(gs:set-text 'Status *fileDir*)
(setq *fileNames* (sort (directory *fileDir* "html*$" 1)))
(setq *index* 0)
(if *fileName* (setq *index* (find *fileName* *fileNames*))
(setq *fileName* (*fileNames* 0)))
(book-display (append *fileDir* (*fileNames* *index*)))))
(define (open-file-dialog)
(gs:open-file-dialog 'Frame 'openfile-action *fileDir* *filemask* *description*))
; initialization
(gs:init)
(define FPosX 100)
(define FPosY 50)
(define FWidth 640)
(define FHeight 480)
(gs:frame 'Frame FPosX FPosY FWidth FHeight "EPUB Viewer")
(gs:panel 'ButtonPanel)
(gs:panel 'StatusPanel)
(gs:label 'Status (real-path))
(gs:label 'fileLabel "")
(gs:button 'preBtn 'next-action "<")
(gs:button 'nextBtn 'next-action ">")
(gs:button 'fileButton 'open-file-dialog "File")
;(gs:text-pane 'OutputArea 'gs:no-action "text/plain")
(gs:text-pane 'OutputArea 'gs:no-action "text/html")
(gs:add-to 'ButtonPanel 'preBtn 'fileLabel 'nextBtn)
(gs:add-to 'StatusPanel 'fileButton 'Status)
; mount all on frame
(gs:set-border-layout 'Frame)
(gs:set-flow-layout 'ButtonPanel "center")
(gs:set-flow-layout 'StatusPanel "left")
(gs:add-to 'Frame 'ButtonPanel "north" 'OutputArea "center" 'StatusPanel "south")
(gs:set-visible 'Frame true)
; main routine
(gs:listen)
(exit)
こうなります。
これなら、EPUB Viewer としてだけではなく、簡易 HTML Viewer としても使える?
以上、如何でしょうか?
newLISP で GUI する。。。または、EPUB を表示させる?
手前味噌ですが、前の blog で short short story として書きためたものをブクログで紹介しています。
そこから、ダウンロードできるフォーマットの一つが、EPUB。
調べてみると EPUB は、最近話題(?)の電子書籍の一種で、XHTMLのサブセット的なファイル・フォーマットで ZIP 圧縮されたもの。
これなら、newLISP で表示できそうだと始めてみました。
本来なら、zip 解凍から始めるべきですが、まだ目処が付いていないので、解凍後のファイルの表示用です。
EPUB を zip 解凍すると、
META-INF - container.xml OEBPS - css - image - text - content.opf - toc.ncx mimetype
こんな感じに展開されます。
お目当て(笑)の short short story は、text フォルダの下に XXX.xhtml のファイル名であります。
今回のスクリプトは、この text フォルダを指定して、中のファイルを表示するスクリプトです。
; utility
(define *newlispDir* (env "NEWLISPDIR"))
(load (append *newlispDir* "/guiserver.lsp"))
; define sub-routine
; define handler
(define *fileDir* (real-path))
(define *fileNames* '())
(define *index* 0)
(define *filemask* "html xhtml")
(define *description* "HTML file")
(define (book-display file)
(when (file? file)
(gs:set-text 'Status file)
(letn (str (read-file file)
book ((find {<body>} str) str))
(gs:set-text 'OutputArea (0 (+ (find {</body>} book) 7) book)))))
(define (next-action id)
(let (f-max (length *fileNames*))
((if (starts-with ((parse id) -1) "pre") -- ++) *index*)
(if (< *index*) (setq *index* (i- f-max))
(< *index* f-max) nil
(setq *index* 0))
(book-display (append *fileDir* (*fileNames* *index*)))))
(define (openfile-action id op file)
(when file
(setq *fileDir* (base64-dec file))
(if (directory? *fileDir*)
(setq *fileDir* (append *fileDir* "\\"))
(let (tmp (parse *fileDir* {\\|/} 0))
(setq *fileDir* (append (join (chop tmp) "/" true)))
(setq *fileName* (tmp -1))))
(setq *fileNames* (sort (directory *fileDir* "[^.+]" 1)))
(setq *index* 0)
(if *fileName* (setq *index* (find *fileName* *fileNames*))
(setq *fileName* (*fileNames* 0)))
(book-display (append *fileDir* (*fileNames* *index*)))))
(define (open-file-dialog)
(gs:open-file-dialog 'Frame 'openfile-action *fileDir* *filemask* *description*))
; initialization
(gs:init)
(define FPosX 100)
(define FPosY 50)
(define FWidth 640)
(define FHeight 480)
(gs:frame 'Frame FPosX FPosY FWidth FHeight "EPUB Viewer")
(gs:panel 'ButtonPanel)
(gs:panel 'StatusPanel)
(gs:label 'Status (real-path))
(gs:button 'preBtn 'next-action "<")
(gs:button 'nextBtn 'next-action ">")
(gs:button 'fileButton 'open-file-dialog "File")
;(gs:text-pane 'OutputArea 'gs:no-action "text/plain")
(gs:text-pane 'OutputArea 'gs:no-action "text/html")
(gs:add-to 'ButtonPanel 'preBtn 'nextBtn)
(gs:add-to 'StatusPanel 'fileButton 'Status)
; mount all on frame
(gs:set-border-layout 'Frame)
(gs:set-flow-layout 'ButtonPanel "center")
(gs:set-flow-layout 'StatusPanel "left")
(gs:add-to 'Frame 'ButtonPanel "north" 'OutputArea "center" 'StatusPanel "south")
(gs:set-visible 'Frame true)
; main routine
(gs:listen)
(exit)
これを実行し、File ボタンを押して、解凍しておいた先程の text フォルダを指定すれば、
といった具合に表示されます。
ただし、テキスト・コードは、UTF-8です。つまり、UTF-8 版 newLISP で実行する必要があります。
まだ、テキスト内容だけで、イメージ・ファイルまでは、表示できませんが(汗)。
それに、zip 解凍も、、、
以上、如何でしょうか?