diff --git a/extension/manifest.json b/extension/manifest.json index 15b3424..b43c18f 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -4,7 +4,7 @@ "name": "fimfic2epub", "short_name": "fimfic2epub", "description": "Improved EPUB exporter for Fimfiction", - "version": "1.5.0", + "version": "1.6.0", "icons": { "128": "icon-128.png" diff --git a/package.json b/package.json index e2787cd..0147435 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fimfic2epub", - "version": "1.5.0", + "version": "1.6.0", "description": "Tool to generate improved EPUB ebooks from Fimfiction stories", "author": "djazz", "repository": { @@ -32,7 +32,6 @@ "pretty-data": "^0.40.0", "request": "^2.74.0", "sanitize-filename": "^1.6.0", - "tidy-html5": "^0.1.1", "zero-fill": "^2.2.3" }, "devDependencies": { diff --git a/src/FimFic2Epub.js b/src/FimFic2Epub.js index f650da3..dfc4f31 100644 --- a/src/FimFic2Epub.js +++ b/src/FimFic2Epub.js @@ -10,7 +10,7 @@ import fileType from 'file-type' import sizeOf from 'image-size' import Emitter from 'es6-event-emitter' -import { styleCss, coverstyleCss, titlestyleCss } from './styles' +import { styleCss, coverstyleCss, titlestyleCss, paragraphsCss } from './styles' import { cleanMarkup } from './cleanMarkup' import htmlWordCount from './html-wordcount' @@ -91,7 +91,7 @@ class FimFic2Epub extends Emitter { useAuthorNotesIndex: false, addChapterHeadings: true, includeExternal: true, - + paragraphStyle: 'spaced', joinSubjects: false } @@ -386,7 +386,7 @@ class FimFic2Epub extends Emitter { } } - this.zip.file('OEBPS/Styles/style.css', styleCss) + this.zip.file('OEBPS/Styles/style.css', styleCss + '\n\n' + (paragraphsCss[this.options.paragraphStyle] || '')) this.remoteResources.forEach((r) => { if (r.dest) { @@ -532,36 +532,49 @@ class FimFic2Epub extends Emitter { } extractTitlePageInfo (html) { - let descPos = html.indexOf('
', '') @@ -101,13 +104,7 @@ export function cleanMarkup (html) { } function continueParsing () { - html = tidy(html, tidyOptions).trim() - - // replace HTML non-breaking spaces with normal spaces - html = html.replace(/ /g, ' ') - html = html.replace(/ /g, ' ') - - html = fixDoubleSpacing(html) + // html = tidy(html, tidyOptions).trim() resolve(html) } diff --git a/src/fetch.js b/src/fetch.js index 140f0c4..fd15899 100644 --- a/src/fetch.js +++ b/src/fetch.js @@ -37,7 +37,7 @@ export default function fetch (url, responseType) { window.fetch(url, { method: 'GET', mode: 'cors', - credentials: 'omit', + credentials: 'include', cache: 'default', redirect: 'follow' }).then((response) => { diff --git a/src/main.js b/src/main.js index 702d056..eadcfdc 100644 --- a/src/main.js +++ b/src/main.js @@ -33,11 +33,11 @@ let logoUrl = chrome.extension.getURL('fimfic2epub-logo.png') let ffc -let stories = document.querySelectorAll('.story_container .story_content_box') +let stories = document.querySelectorAll('.story_container') stories.forEach((story) => { - let id = story.id.substring(6) - let epubButton = story.querySelector('ul.chapters li.bottom a[title="Download Story (.epub)"]') + let id = story.dataset.story + let epubButton = story.querySelector('.story-top-toolbar .button-group .drop-down ul li a[title="Download Story (.epub)"]') if (!epubButton) return epubButton.addEventListener('click', function (e) { e.preventDefault() @@ -47,7 +47,7 @@ stories.forEach((story) => { logo.className = 'fimfic2epub-logo' logo.title = 'Download EPUB with fimfic2epub' logo.src = logoUrl - story.querySelector('.title').appendChild(logo) + story.querySelector('.story_content_box .title').appendChild(logo) logo.addEventListener('click', function (e) { e.preventDefault() openStory(id) @@ -89,6 +89,15 @@ let checkbox = { } } +function selectOptions (list, selected = '') { + return list.map((item) => { + return m('option', { + value: item[0], + selected: selected === item[0] + }, item[1]) + }) +} + let ffcProgress = m.prop(0) let ffcStatus = m.prop('') @@ -117,6 +126,7 @@ let dialog = { this.addChapterHeadings = m.prop(ffc.options.addChapterHeadings) this.includeExternal = m.prop(ffc.options.includeExternal) this.joinSubjects = m.prop(ffc.options.joinSubjects) + this.paragraphStyle = m.prop(ffc.options.paragraphStyle) this.onOpen = function (el, isInitialized) { if (!isInitialized) { @@ -219,6 +229,7 @@ let dialog = { ffc.options.useAuthorNotesIndex = this.useAuthorNotesIndex() ffc.options.addChapterHeadings = this.addChapterHeadings() ffc.options.includeExternal = this.includeExternal() + ffc.options.paragraphStyle = this.paragraphStyle() ffc.subjects = this.subjects() ffc.options.joinSubjects = this.joinSubjects() m.redraw() @@ -240,7 +251,7 @@ let dialog = { }, view (ctrl, args, extras) { - return m('.drop-down-pop-up-container', {config: ctrl.onOpen.bind(ctrl)}, m('.drop-down-pop-up', [ + return m('.drop-down-pop-up-container', {config: ctrl.onOpen.bind(ctrl)}, m('.drop-down-pop-up', {style: {'min-width': '700px'}}, [ m('h1', {onmousedown: ctrl.ondown}, m('i.fa.fa-book'), 'Export to EPUB', m('a.close_button', {onclick: closeDialog})), m('.drop-down-pop-up-content', [ ctrl.isLoading() ? m('div', {style: 'text-align:center;'}, m('i.fa.fa-spin.fa-spinner', {style: 'font-size:50px; margin:20px; color:#777;'})) : m('table.properties', [ @@ -253,6 +264,14 @@ let dialog = { ), m('td', {style: 'width: 1px'}, m(checkbox, {checked: ctrl.checkboxCoverUrl(), onchange: m.withAttr('checked', ctrl.checkboxCoverUrl)}, 'Use image URL')) ), + m('tr', m('td.label', 'Paragraph style'), m('td', {colspan: 2}, + m('select', {onchange: m.withAttr('value', ctrl.paragraphStyle)}, selectOptions([ + ['indented', 'Indent first line in all paragraphs except the first (Traditional Paperback)'], + ['spaced', 'Separate each paragraph with double space (Traditional Web)'], + ['both', 'Double space and indent all paragraphs except first (Fusion)'], + ['indentedall', 'Indent all paragraphs including the first (Modified Traditional)'] + ], ctrl.paragraphStyle())) + )), m('tr', m('td.label', ''), m('td', {colspan: 2}, m(checkbox, {checked: ctrl.addChapterHeadings(), onchange: m.withAttr('checked', ctrl.addChapterHeadings)}, 'Add chapter headings'), m(checkbox, {checked: ctrl.addCommentsLink(), onchange: m.withAttr('checked', ctrl.addCommentsLink)}, 'Add link to online comments (at the end of chapters)'), diff --git a/src/coverstyle.styl b/src/style/coverstyle.styl similarity index 100% rename from src/coverstyle.styl rename to src/style/coverstyle.styl diff --git a/src/mixins.styl b/src/style/mixins.styl similarity index 100% rename from src/mixins.styl rename to src/style/mixins.styl diff --git a/src/style/paragraphs-indented.styl b/src/style/paragraphs-indented.styl new file mode 100644 index 0000000..b8175cd --- /dev/null +++ b/src/style/paragraphs-indented.styl @@ -0,0 +1,8 @@ + +p + p { + text-indent: 1em; +} + +.chapter-title + p.indented { + text-indent: 0; +} diff --git a/src/style/paragraphs-indentedall.styl b/src/style/paragraphs-indentedall.styl new file mode 100644 index 0000000..482ab17 --- /dev/null +++ b/src/style/paragraphs-indentedall.styl @@ -0,0 +1,4 @@ + +p { + text-indent: 1em; +} diff --git a/src/style/paragraphs-spaced.styl b/src/style/paragraphs-spaced.styl new file mode 100644 index 0000000..9ba6602 --- /dev/null +++ b/src/style/paragraphs-spaced.styl @@ -0,0 +1,12 @@ + +p { + margin-top: 1em; +} + +.chapter-title + p { + margin-top: 0; +} + +.bbcode-center, .bbcode-right { + margin-top: 1em; +} diff --git a/src/style.styl b/src/style/style.styl similarity index 92% rename from src/style.styl rename to src/style/style.styl index bc67743..714618c 100644 --- a/src/style.styl +++ b/src/style/style.styl @@ -8,26 +8,39 @@ body { } p { - margin-top: 0.0em; - margin-bottom: 0.0em; - text-indent: 0.0em; + margin-top: 0; + margin-bottom: 0; + text-indent: 0; &.double { - margin-top: 1.0em; + margin-top: 1em; } &.double2 { - margin-top: 1.0em; - margin-bottom: 1.0em; + margin-top: 1em; + margin-bottom: 1em; } &.indented { - text-indent: 1.0em; + text-indent: 1em; } + &:first-child { + margin-top: 0; + } +} +div p { + text-indent: 0; } h1, h2, h3, h4, h5, h6 { text-align: left; } +em { + font-style: italic; +} +em em { + font-style: normal; +} + .chapter-title { margin-top: 1.5em; margin-bottom: 1.5em; @@ -37,9 +50,6 @@ h1, h2, h3, h4, h5, h6 { font-weight: normal; margin: 0; } - & + p.indented { - text-indent: 0; - } } img { diff --git a/src/titlestyle.styl b/src/style/titlestyle.styl similarity index 96% rename from src/titlestyle.styl rename to src/style/titlestyle.styl index b52ae60..a1c3f0c 100644 --- a/src/titlestyle.styl +++ b/src/style/titlestyle.styl @@ -52,6 +52,7 @@ .characters { margin-top: 0.5em; text-align: left; + font-size: .875em; } // Last Modified and First Published @@ -172,6 +173,18 @@ span.character_icon { font-family: sans-serif; } +.story_character { + display: inline-block; + padding: 0.3em 0.5em; + line-height: 1.0em; + bgcolor(#23b974); + textcolor(#fff); + text-decoration: none; + border-radius: 0.3em; + border: 1px solid #1e9d63; + font-family: sans-serif; +} + .story_category_sex { bgcolor(#992584); box-shadow: 0px 1px 0px #b82c9e inset; diff --git a/src/styles.js b/src/styles.js index 3cd2d29..4affcb2 100644 --- a/src/styles.js +++ b/src/styles.js @@ -1,8 +1,15 @@ let styleCss, coverstyleCss, titlestyleCss -styleCss = require('./style') -coverstyleCss = require('./coverstyle') -titlestyleCss = require('./titlestyle') +styleCss = require('./style/style') +coverstyleCss = require('./style/coverstyle') +titlestyleCss = require('./style/titlestyle') +let paragraphsCss = { + spaced: require('./style/paragraphs-spaced'), + indented: require('./style/paragraphs-indented'), + indentedall: require('./style/paragraphs-indentedall') +} -export { styleCss, coverstyleCss, titlestyleCss } +paragraphsCss.both = paragraphsCss.indented + '\n' + paragraphsCss.spaced + +export { styleCss, coverstyleCss, titlestyleCss, paragraphsCss } diff --git a/src/templates.js b/src/templates.js index 6facd82..86e6221 100644 --- a/src/templates.js +++ b/src/templates.js @@ -351,7 +351,8 @@ export function createTitlePage (ffc) { // m('hr'), m('.characters', [ ffc.tags.map((t) => - m('span', {className: 'character_icon', title: t.name}, m('img', {src: t.image, className: 'character_icon'})) + // m('span', {className: 'character_icon', title: t.name}, m('img', {src: t.image, className: 'character_icon'})) + m('span.story_character', t.name) ) ]) ]) diff --git a/webpack.config.babel.js b/webpack.config.babel.js index d79fb91..c1b1afa 100644 --- a/webpack.config.babel.js +++ b/webpack.config.babel.js @@ -30,9 +30,6 @@ const bundleExtensionConfig = { test: /\.styl$/, use: ['raw-loader', 'stylus-loader'] } - ], - noParse: [ - /[/\\]node_modules[/\\]tidy-html5[/\\]tidy\.js$/ ] }, @@ -47,7 +44,7 @@ const bundleExtensionConfig = { } }, - externals: ['request', 'tidy-html5'], + externals: ['request'], plugins: [], devtool: 'source-map' @@ -79,9 +76,6 @@ const bundleNpmModuleConfig = { test: /\.styl$/, use: ['raw-loader', 'stylus-loader'] } - ], - noParse: [ - /[/\\]node_modules[/\\]tidy-html5[/\\]tidy\.js$/ ] }, @@ -93,7 +87,7 @@ const bundleNpmModuleConfig = { ] }, - externals: [nodeExternals({whitelist: ['es6-event-emitter', /^babel-runtime/]}), 'exports?tidy_html5!tidy-html5'], + externals: [nodeExternals({whitelist: ['es6-event-emitter', /^babel-runtime/]})], plugins: [], devtool: 'source-map'