Skip to content

Commit

Permalink
add single html output format
Browse files Browse the repository at this point in the history
  • Loading branch information
missdeer committed Nov 23, 2023
1 parent 036cf10 commit 90ff5a4
Show file tree
Hide file tree
Showing 2 changed files with 195 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ebook/ebook.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ func NewBook(bookType string) IBook {
return &kindlegenMobiBook{}
case "epub":
return &epubBook{}
case "html":
return &singleHTMLBook{}
default:
return nil
}
Expand Down
193 changes: 193 additions & 0 deletions ebook/html.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
// Package ebook generate ebook files such as .mobi or it's input,
// currently only mobi is supported
package ebook

import (
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
"time"
"unicode/utf8"

"github.com/missdeer/golib/fsutil"
pinyin "github.com/mozillazg/go-pinyin"
)

// singleHTMLBook generate files that used to make a mobi file by kindlegen
type singleHTMLBook struct {
title string
uid int64
count int
output string
dirName string
fontFilePath string
tocTmp *os.File
contentTmp *os.File
}

// Output set the output file path
func (m *singleHTMLBook) Output(o string) {
m.output = o
}

// Info output self information
func (m *singleHTMLBook) Info() {
fmt.Println("generating single HTML file...")
}

// PagesPerFile dummy funciton for interface
func (m *singleHTMLBook) PagesPerFile(int) {

}

// ChaptersPerFile dummy funciton for interface
func (m *singleHTMLBook) ChaptersPerFile(int) {

}

// SetPageSize dummy funciton for interface
func (m *singleHTMLBook) SetPageSize(width float64, height float64) {
}

// SetMargins dummy funciton for interface
func (m *singleHTMLBook) SetMargins(left float64, top float64) {

}

// SetPageType dummy funciton for interface
func (m *singleHTMLBook) SetPageType(pageType string) {

}

// SetFontSize dummy funciton for interface
func (m *singleHTMLBook) SetFontSize(titleFontSize int, contentFontSize int) {

}

// SetFontFile set custom font file
func (m *singleHTMLBook) SetFontFile(file string) {
m.fontFilePath = file
}

// SetLineSpacing dummy funciton for interface
func (m *singleHTMLBook) SetLineSpacing(float64) {

}

// Begin prepare book environment
func (m *singleHTMLBook) Begin() {
if b, e := fsutil.FileExists(m.fontFilePath); e != nil || !b {
contentHTMLTemplate = strings.Replace(contentHTMLTemplate, `@font-face{ font-family: "CustomFont"; src: url(fonts/CustomFont.ttf); }";`, "", -1)
contentHTMLTemplate = strings.Replace(contentHTMLTemplate, `font-family: "CustomFont";`, "", -1)
return
}
}

// End generate files that kindlegen needs
func (m *singleHTMLBook) End() {
m.tocTmp.Close()
m.contentTmp.Close()

m.writeContentHTML()

os.Remove(filepath.Join(m.dirName, `toc.tmp`))
os.Remove(filepath.Join(m.dirName, `content.tmp`))

fmt.Println(filepath.Join(m.dirName, m.dirName+".html"), "is generated.")
}

// AppendContent append book content
func (m *singleHTMLBook) AppendContent(articleTitle, articleURL, articleContent string) {
m.tocTmp.WriteString(fmt.Sprintf(`<li><a href="#article_%d">%s</a></li>`, m.count, articleTitle))
m.contentTmp.WriteString(fmt.Sprintf(`<div id="article_%d" class="article"><h2 class="do_article_title"><a href="%s">%s</a></h2><div><p>%s</p></div></div>`,
m.count, articleURL, articleTitle, articleContent))

m.count++
}

// SetTitle set book title
func (m *singleHTMLBook) SetTitle(title string) {
m.title = title

finalName := ""
t := m.title
isCJK := false
for len(t) > 0 {
r, size := utf8.DecodeRuneInString(t)
if size == 1 {
if isCJK {
isCJK = false
finalName += "-"
}
finalName += string(r)
} else {
isCJK = true
py := pinyin.LazyPinyin(string(r), pinyin.NewArgs())
if len(py) > 0 {
if finalName == "" {
finalName = py[0]
} else {
finalName += "-" + py[0]
}
}
}
t = t[size:]
}
m.dirName = finalName
os.Mkdir(m.dirName, 0755)

var err error
if m.tocTmp == nil {
m.tocTmp, err = os.OpenFile(filepath.Join(m.dirName, `toc.tmp`), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
log.Println("opening file toc.tmp for writing failed ", err)
return
}
}
if m.contentTmp == nil {
m.contentTmp, err = os.OpenFile(filepath.Join(m.dirName, `content.tmp`), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
log.Println("opening file content.tmp for writing failed ", err)
return
}
}
}

func (m *singleHTMLBook) writeContentHTML() {
tocTmp, err := os.OpenFile(filepath.Join(m.dirName, `toc.tmp`), os.O_RDONLY, 0644)
if err != nil {
log.Println("opening file toc.tmp for reading failed ", err)
return
}
tocC, err := io.ReadAll(tocTmp)
tocTmp.Close()
if err != nil {
log.Println("reading file toc.tmp failed ", err)
return
}

contentTmp, err := os.OpenFile(filepath.Join(m.dirName, `content.tmp`), os.O_RDONLY, 0644)
if err != nil {
log.Println("opening file content.tmp for reading failed ", err)
return
}
contentC, err := io.ReadAll(contentTmp)
contentTmp.Close()
if err != nil {
log.Println("reading file content.tmp failed ", err)
return
}

contentHTML, err := os.OpenFile(filepath.Join(m.dirName, `content.html`), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
log.Println("opening file content.html for writing failed ", err)
return
}

contentHTML.WriteString(fmt.Sprintf(contentHTMLTemplate, m.title, m.title, time.Now().String(),
string(tocC), string(contentC)))
contentHTML.Close()
}

0 comments on commit 90ff5a4

Please sign in to comment.