Skip to content

Commit

Permalink
fix: fix issue #18
Browse files Browse the repository at this point in the history
  • Loading branch information
gaoxiaoliangz committed Jul 2, 2020
1 parent f38c220 commit d979ff4
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 56 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"scripts": {
"prebuild": "yarn clean",
"build": "tsc",
"watch": "tsc --watch",
"clean": "rimraf lib",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,md,css,scss}\"",
"test": "jest",
Expand Down Expand Up @@ -36,7 +37,6 @@
"lodash": "^4.17.15",
"node-zip": "^1.1.1",
"to-markdown": "^3.1.1",
"typescript": "^3.5.3",
"xml2js": "^0.4.19"
},
"devDependencies": {
Expand All @@ -56,6 +56,7 @@
"ts-jest": "^24.0.2",
"ts-node": "^8.3.0",
"tslint": "^5.19.0",
"typescript": "^3.9.6",
"vrsource-tslint-rules": "^6.0.0"
}
}
16 changes: 8 additions & 8 deletions src/mdConverters.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import parseLink from './parseLink'

export const resolveInlineNavHref = (href) => {
export const resolveInlineNavHref = (href: string) => {
if (href && href.indexOf('http://') === -1) {
const parsed = parseLink(href)

Expand All @@ -17,7 +17,7 @@ export const resolveInlineNavHref = (href) => {
export const h = {
filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],

replacement: function (innerHTML, node: HTMLElement) {
replacement: function (innerHTML: string, node: HTMLElement) {
let hLevel = node.tagName.charAt(1) as any
let hPrefix = ''

Expand All @@ -41,32 +41,32 @@ export const h = {
export const span = {
filter: ['span'],

replacement: function (innerHTML, node) {
replacement: function (innerHTML: string) {
return innerHTML
},
}

export const a = {
filter: ['a'],

replacement: function (innerHTML, node: HTMLEmbedElement) {
replacement: function (innerHTML: string, node: HTMLEmbedElement) {
const href = node.getAttribute('href')
return `\n[${innerHTML}](${resolveInlineNavHref(href)})\n\n`
return `\n[${innerHTML}](${resolveInlineNavHref(href!)})\n\n`
},
}

export const div = {
filter: ['div'],

replacement: function (innerHTML, node) {
replacement: function (innerHTML: string) {
return `\n${innerHTML}\n\n`
},
}

export const img = {
filter: ['img'],

replacement: function (innerHTML, node) {
return `\n[]\n\n`
replacement: function (innerHTML: string) {
return `\n[PIC]\n\n`
},
}
2 changes: 1 addition & 1 deletion src/parseEpub.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as path from 'path'
const baseDir = process.cwd()
const filesToBeTested = ['file-1', 'file-2', 'file-3', 'file-4', 'file-1-no-toc']

const testFile = (filename) => {
const testFile = (filename: string) => {
describe(`parser 测试 ${filename}.epub`, () => {
const fileContent = parser(path.join(baseDir, `fixtures/${filename}.epub`), {
type: 'path',
Expand Down
58 changes: 32 additions & 26 deletions src/parseEpub.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import fs from 'fs'
import xml2js from 'xml2js'
import _ from 'lodash'
// @ts-ignore
import nodeZip from 'node-zip'
import parseLink from './parseLink'
import parseSection, { Section } from './parseSection'
import { GeneralObject } from './types'

const xmlParser = new xml2js.Parser()

const xmlToJs = (xml) => {
const xmlToJs = (xml: string) => {
return new Promise<any>((resolve, reject) => {
xmlParser.parseString(xml, (err, object) => {
xmlParser.parseString(xml, (err: Error, object: GeneralObject) => {
if (err) {
reject(err)
} else {
Expand All @@ -19,7 +21,7 @@ const xmlToJs = (xml) => {
})
}

const determineRoot = (opfPath) => {
const determineRoot = (opfPath: string) => {
let root = ''
// set the opsRoot for resolving paths
if (opfPath.match(/\//)) {
Expand All @@ -36,7 +38,7 @@ const determineRoot = (opfPath) => {
return root
}

const parseMetadata = (metadata) => {
const parseMetadata = (metadata: GeneralObject[]) => {
const title = _.get(metadata[0], ['dc:title', 0]) as string
let author = _.get(metadata[0], ['dc:creator', 0]) as string

Expand All @@ -55,22 +57,22 @@ const parseMetadata = (metadata) => {

export class Epub {
private _zip: any // nodeZip instance
private _opfPath: string
private _root: string
private _content: GeneralObject
private _manifest: any[]
private _spine: string[] // array of ids defined in manifest
private _toc: GeneralObject
private _metadata: GeneralObject
structure: GeneralObject
info: {
private _opfPath?: string
private _root?: string
private _content?: GeneralObject
private _manifest?: any[]
private _spine?: string[] // array of ids defined in manifest
private _toc?: GeneralObject
private _metadata?: GeneralObject
structure?: GeneralObject
info?: {
title: string
author: string
publisher: string
}
sections: Section[]
sections?: Section[]

constructor(buffer) {
constructor(buffer: Buffer) {
this._zip = new nodeZip(buffer, { binary: true, base64: false, checkCRC32: true })
}

Expand All @@ -94,7 +96,7 @@ export class Epub {
}
}

async _resolveXMLAsJsObject(path) {
async _resolveXMLAsJsObject(path: string) {
const xml = this.resolve(path).asText()
return xmlToJs(xml)
}
Expand All @@ -105,11 +107,13 @@ export class Epub {
return opfPath
}

_getManifest(content) {
return _.get(content, ['package', 'manifest', 0, 'item'], []).map((item) => item.$) as any[]
_getManifest(content: GeneralObject) {
return _.get(content, ['package', 'manifest', 0, 'item'], []).map(
(item: any) => item.$,
) as any[]
}

_resolveIdFromLink(href) {
_resolveIdFromLink(href: string) {
const { name: tarName } = parseLink(href)
const tarItem = _.find(this._manifest, (item) => {
const { name } = parseLink(item.href)
Expand All @@ -119,15 +123,17 @@ export class Epub {
}

_getSpine() {
return _.get(this._content, ['package', 'spine', 0, 'itemref'], []).map((item) => {
return item.$.idref
})
return _.get(this._content, ['package', 'spine', 0, 'itemref'], []).map(
(item: GeneralObject) => {
return item.$.idref
},
)
}

_genStructure(tocObj, resolveNodeId = false) {
_genStructure(tocObj: GeneralObject, resolveNodeId = false) {
const rootNavPoints = _.get(tocObj, ['ncx', 'navMap', '0', 'navPoint'], [])

const parseNavPoint = (navPoint) => {
const parseNavPoint = (navPoint: GeneralObject) => {
// link to section
const path = _.get(navPoint, ['content', '0', '$', 'src'], '')
const name = _.get(navPoint, ['navLabel', '0', 'text', '0'])
Expand All @@ -152,7 +158,7 @@ export class Epub {
}
}

const parseNavPoints = (navPoints) => {
const parseNavPoints = (navPoints: GeneralObject[]) => {
return navPoints.map((point) => {
return parseNavPoint(point)
})
Expand Down Expand Up @@ -222,5 +228,5 @@ export default function parserWrapper(target: string | Buffer, options: ParserOp
if (type === 'path' || (typeof target === 'string' && fs.existsSync(target))) {
_target = fs.readFileSync(target as string, 'binary')
}
return new Epub(_target).parse(expand)
return new Epub(_target as Buffer).parse(expand)
}
13 changes: 9 additions & 4 deletions src/parseHTML.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { JSDOM } from 'jsdom'
import _ from 'lodash'
import { traverseNestedObject } from './utils'
import { HtmlNodeObject, GeneralObject } from './types'

const OMITTED_TAGS = ['head', 'input', 'textarea', 'script', 'style', 'svg']
const UNWRAP_TAGS = ['body', 'html', 'div', 'span']
Expand All @@ -12,8 +13,12 @@ const PICKED_ATTRS = ['href', 'src', 'id']
* @param callback invoke every time a parent node is read, return truthy value to stop the reading process
* @param final callback when reaching the root
*/
const recursivelyReadParent = (node, callback, final?) => {
const _read = (_node) => {
const recursivelyReadParent = (
node: GeneralObject,
callback: (node: GeneralObject) => GeneralObject | null,
final?: () => GeneralObject,
) => {
const _read = (_node: GeneralObject): GeneralObject => {
const parent = _node.parentNode
if (parent) {
const newNode = callback(parent)
Expand All @@ -35,7 +40,7 @@ export interface ParseHTMLConfig {
resolveSrc?: (src: string) => string
resolveHref?: (href: string) => string
}
const parseHTML = (HTMLString, config: ParseHTMLConfig = {}) => {
const parseHTML = (HTMLString: string, config: ParseHTMLConfig = {}) => {
const rootNode = new JSDOM(HTMLString).window.document.documentElement
const { resolveHref, resolveSrc } = config

Expand Down Expand Up @@ -90,7 +95,7 @@ const parseHTML = (HTMLString, config: ParseHTMLConfig = {}) => {
(parent) => {
const tag = parent.tagName && parent.tagName.toLowerCase()
if (!tag || UNWRAP_TAGS.indexOf(tag) !== -1) {
return false
return null
}
return makeTextObject()
},
Expand Down
2 changes: 1 addition & 1 deletion src/parseLink.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import _ from 'lodash'

export default function parseHref(href) {
export default function parseHref(href: string) {
const hash = href.split('#')[1]
const url = href.split('#')[0]
const prefix = url.split('/').slice(0, -1).join('/')
Expand Down
10 changes: 6 additions & 4 deletions src/parseSection.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import path from 'path'
// @ts-ignore
import toMarkdown from 'to-markdown'
import parseLink from './parseLink'
import parseHTML from './parseHTML'
import * as mdConverters from './mdConverters'
import { HtmlNodeObject } from './types'

const isInternalUri = (uri) => {
const isInternalUri = (uri: string) => {
return uri.indexOf('http://') === -1 && uri.indexOf('https://') === -1
}

Expand All @@ -29,7 +31,7 @@ export class Section {
this._resourceResolver = resourceResolver
this._idResolver = idResolver
if (expand) {
this.htmlObjects = this.toHtmlObjects()
this.htmlObjects = this.toHtmlObjects?.()
}
}

Expand All @@ -51,7 +53,7 @@ export class Section {
if (isInternalUri(href)) {
const { hash } = parseLink(href)
// todo: what if a link only contains hash part?
const sectionId = this._idResolver(href)
const sectionId = this._idResolver?.(href)
if (hash) {
return `#${sectionId},${hash}`
}
Expand All @@ -63,7 +65,7 @@ export class Section {
if (isInternalUri(src)) {
// todo: may have bugs
const absolutePath = path.resolve('/', src).substr(1)
const buffer = this._resourceResolver(absolutePath).asNodeBuffer()
const buffer = this._resourceResolver?.(absolutePath)?.asNodeBuffer()
const base64 = buffer.toString('base64')
return `data:image/png;base64,${base64}`
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib.d.ts → src/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
interface GeneralObject {
export interface GeneralObject {
[key: string]: any
}

interface HtmlNodeObject {
export interface HtmlNodeObject {
tag?: string
type: 1 | 3
text?: string
Expand Down
9 changes: 5 additions & 4 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import _ from 'lodash'
import { GeneralObject } from './types'

export interface TraverseNestedObject {
preFilter?: (node) => boolean
postFilter?: (node) => boolean
preFilter?: (node: GeneralObject) => boolean
postFilter?: (node: GeneralObject) => boolean

// children must be returned from transformer
// or it may not work as expected
transformer?: (node, children) => any
finalTransformer?: (node) => any
transformer?: (node: GeneralObject, children?: GeneralObject[]) => any
finalTransformer?: (node: GeneralObject) => any

childrenKey: string
}
Expand Down
4 changes: 3 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
"allowJs": false,
"jsx": "react",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
"esModuleInterop": true,
"preserveWatchOutput": true,
"strict": true
},
"include": [
"src"
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4001,10 +4001,10 @@ type-is@~1.6.17, type-is@~1.6.18:
media-typer "0.3.0"
mime-types "~2.1.24"

typescript@^3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
typescript@^3.9.6:
version "3.9.6"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a"
integrity sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==

uglify-js@^3.1.4:
version "3.7.3"
Expand Down

0 comments on commit d979ff4

Please sign in to comment.