Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • sethetter/pubsweet-components
  • yld/pubsweet-components
2 results
Show changes
Commits on Source (45)
Showing
with 6710 additions and 42 deletions
const HTMLEPUB = require('html-epub')
const fs = require('fs')
const indexOf = require('lodash/indexOf')
const sorter = require('./sorter')
const converters = require('./converters')
const processFragment = require('./process')
const output = require('./output')
const config = require('config')
const EpubBackend = function (app) {
app.use('/api/collections/:id/epub', async function (req, res, next) {
......@@ -22,22 +26,48 @@ const EpubBackend = function (app) {
// chapters
const fragments = await collection.getFragments()
// styles
const styles = [req.query.style].filter(name => name)
// CSS Theme
// TODO: change it from array to the name of the selected theme
let styles = [req.query.style].filter(name => name)
// TODO: to be desided where the per applications themes should live
let stylesRoot = process.cwd() + '/static'
if (styles.length === 0 || !fs.existsSync(`${stylesRoot}/${styles[0]}`)) {
styles = ['default.css']
stylesRoot = `${__dirname}/themes`
}
let fontsRoot = config.epub && config.epub.fontsPath
? process.cwd() + config.epub.fontsPath
: null
if (!fs.existsSync(fontsRoot)) fontsRoot = ''
// converters
const activeConverters = [req.query.converter]
.filter(name => name && converters[name])
.map(name => converters[name])
const parts = fragments.sort(sorter).map(
processFragment({ styles, activeConverters })
const sortedFragments = fragments.sort(sorter)
const partsIds = sortedFragments
.filter(fragment => fragment.division === 'body' && fragment.subCategory === 'part') // HACK -- to remove
.map(fragment => fragment.id)
sortedFragments.forEach(fragment => {
let found = indexOf(partsIds, fragment.id)
if (found !== -1) {
fragment.number = found + 1
}
})
const parts = sortedFragments.map(
processFragment({ styles, activeConverters, book })
)
// TODO: read the path to the uploads folder from config
const resourceRoot = process.cwd() + '/uploads'
const epub = new HTMLEPUB(book, {resourceRoot})
const epub = new HTMLEPUB(book, {resourceRoot, stylesRoot, fontsRoot})
await epub.load(parts)
......
module.exports = $ => {
module.exports = ($, fragmentTitle, bookTitle, fragmentDivision, fragmentSubcategory, fragmentNumber) => {
const body = $('body')
const replaceWithBlockquote = (i, elem) => {
let outerContainer = $('<div/>').attr('class', fragmentDivision)
let innerContainer
if (fragmentDivision === 'front') {
innerContainer = $('<section/>').attr('data-type', 'fm-body')
} else if (fragmentDivision === 'back') {
innerContainer = $('<section/>').attr('data-type', 'bm-body')
} else {
innerContainer = $('<section/>').attr('data-type', fragmentSubcategory)
}
$('<p/>').attr('class', 'ch-start').html('beginning').appendTo(innerContainer)
$('<div/>').attr('class', 'folio').appendTo(innerContainer)
$('<div/>').attr('class', 'booktitle').html(bookTitle).appendTo(innerContainer)
$('<div/>').attr('class', 'dup').html(fragmentTitle).appendTo(innerContainer)
if (fragmentSubcategory === 'part') {
$('<p/>').attr('class', 'part-number').html(fragmentNumber).appendTo(innerContainer)
} else if (fragmentSubcategory === 'chapter') {
$('<p/>').attr('class', 'chapter-number').html(fragmentNumber).appendTo(innerContainer)
}
$('<h1/>').attr('class', 'ct').html(fragmentTitle).appendTo(innerContainer)
const replaceWithBlockquote = className => (i, elem) => {
const $elem = $(elem)
const blockquote = $('<blockquote class="sc-blockquote"/>')
const blockquote = $(`<blockquote class="${className}"/>`)
.append($elem.contents())
$elem.replaceWith(blockquote)
......@@ -43,14 +65,19 @@ module.exports = $ => {
})
// replace custom HTML elements
$('extract-prose, extract-poetry, epigraph-poetry, epigraph-prose').each(replaceWithBlockquote)
$('extract').each(replaceWithBlockquote('ex')) // delete when xsweet is updated
$('extract-prose').each(replaceWithBlockquote('ex'))
$('extract-poetry').each(replaceWithBlockquote('px'))
$('epigraph-poetry').each(replaceWithBlockquote('sepo'))
$('epigraph-prose').each(replaceWithBlockquote('sep'))
$('bibliography-entry').each(replaceWithParagraph('bibliography-entry'))
$('comment').each(replaceWithText)
$('chapter-number').each(replaceWithParagraph('sc-chapter-number'))
$('chapter-title').each(replaceWithParagraph('sc-chapter-title'))
$('chapter-subtitle').each(replaceWithParagraph('sc-chapter-subtitle'))
$('source-note').each(replaceWithParagraph('source-note'))
$('ol[styling="qa"]').each(replaceWithList('sc-list-ol-qa'))
$('ol[styling="unstyled"]').each(replaceWithList('sc-list-ol-unstyled'))
// $('chapter-number').each(replaceWithParagraph('sc-chapter-number'))
$('chapter-title').each(replaceWithParagraph('ct'))
$('chapter-subtitle').each(replaceWithParagraph('cst'))
$('source-note').each(replaceWithParagraph('exsn'))
$('ol[styling="qa"]').each(replaceWithList('di'))
$('ol[styling="unstyled"]').each(replaceWithList('none'))
// remove "uploads" from the start of each src attribute
$('[src]').each((i, elem) => {
......@@ -77,17 +104,24 @@ module.exports = $ => {
const $elem = $(elem)
const id = $elem.attr('data-id')
const content = `${i + 1}. ${$elem.attr('note-content')}`
$('<aside epub:type="footnote" class="footnote"/>')
.attr('id', id)
.html(content)
.appendTo(body)
const callout = $('<a epub:type="noteref" class="note-callout"/>')
.attr('href', '#' + id)
.text(`[${i + 1}]`)
const noteNumber = `${i + 1}.`
const content = `${$elem.attr('note-content')}`
const callout = $(`
<a class="inline-note-callout" href="#${id}">
<sup>${i + 1}</sup>
</a>
<span class="inline-note-footer" data-note-num="${id}">
<span class="inline-note-number"> ${noteNumber} </span>
<span class="inline-note-content"> ${content} </span>
</span>
`)
$elem.replaceWith(callout)
})
let bodyContent = body.contents()
innerContainer.append(bodyContent)
outerContainer.append(innerContainer)
body.replaceWith(outerContainer)
}
This diff is collapsed.
{
"name": "pubsweet-component-epub",
"version": "0.1.0",
"version": "0.2.0",
"description": "Backend EPUB export component for PubSweet",
"main": "index.js",
"scripts": {
......@@ -11,7 +11,7 @@
"dependencies": {
"@pubsweet/logger": "^0.0.1",
"cheerio": "^1.0.0-rc.2",
"html-epub": "^0.4.0",
"html-epub": "^0.5.1",
"mkdirp": "^0.5.1",
"unzipper": "^0.8.9"
},
......
const cheerio = require('cheerio')
module.exports = ({ styles, activeConverters }) => fragment => {
module.exports = ({ styles, activeConverters, book }) => fragment => {
const $ = cheerio.load(fragment.source)
const fragmentTitle = fragment.title || 'Untitled'
const bookTitle = book.title
const fragmentDivision = fragment.division
const fragmentSubcategory = fragment.subCategory
const fragmentNumber = fragment.hasOwnProperty('number') ? fragment.number : -1
activeConverters.forEach(converter => converter($))
activeConverters.forEach(converter => converter($, fragmentTitle, bookTitle, fragmentDivision, fragmentSubcategory, fragmentNumber))
styles.forEach(uri => {
$('<link rel="stylesheet"/>').attr('href', uri).appendTo('head')
......
......@@ -5,18 +5,27 @@ const processFragment = require('./process')
test('converts source to html', () => {
const fragment = {
title: 'A Test',
division: 'body',
subCategory: 'part',
number: 3,
source: `
<div>
<h1>A Test</h1>
<p>Test</p>
</div>
`
`,
id: '1'
}
const book = {
title: 'Test Book',
identifier: '65ac5abe353ef4d32f1ce55abfe665185d58d811883b1715032b8ed70a8cc1e1'
}
const styles = ['test.css']
const activeConverters = [converters['wax']]
const { title, content } = processFragment({styles, activeConverters})(fragment)
const { title, content } = processFragment({styles, activeConverters, book})(fragment)
expect(title).toBe('A Test')
......
This diff is collapsed.
......@@ -173,7 +173,7 @@ const downloadFromInk = ([auth, response]) => {
}
var InkBackend = function (app) {
app.use('/ink', (req, res, next) => {
app.use('/api/ink', (req, res, next) => {
var fileStream = new Busboy({ headers: req.headers })
const handleErr = err => {
......
{
"name": "pubsweet-component-ink-backend",
"version": "0.0.13",
"version": "0.1.0",
"description": "Backend INK component for PubSweet",
"main": "index.js",
"scripts": {
......
......@@ -21,7 +21,7 @@ export default class Login extends Component {
<Grid>
<Row>
<Col md={2} mdOffset={5}>
<img src="/assets/pubsweet-rgb-small.jpg" className="auth-logo" alt="pubsweet-logo" style={{maxWidth: '100%'}}/>
<img src="/assets/pubsweet-rgb-small.jpg" className={styles.loginLogo} alt="pubsweet-logo" style={{maxWidth: '100%'}}/>
</Col>
</Row>
......@@ -30,7 +30,7 @@ export default class Login extends Component {
{error && <Alert bsStyle="warning"><i className="fa fa-exclamation-circle" />&nbsp; {error}</Alert>}
</Col>
<Col xs={12} md={4}>
<Col xs={12} md={4} className={styles.login}>
<h1>Login</h1>
<form>
<div className="form-group">
......
{
"name": "pubsweet-component-login",
"version": "0.5.3",
"version": "0.5.5",
"description": "Basic login component for PubSweet",
"main": "index.js",
"scripts": {
......
......@@ -4,6 +4,7 @@ import PropTypes from 'prop-types'
import { Grid, Row, Col, Alert, FormGroup, ControlLabel, Button, FormControl } from 'react-bootstrap'
import queryString from 'query-string'
import * as api from 'pubsweet-client/src/helpers/api'
import styles from './PasswordReset.local.scss'
class PasswordReset extends React.Component {
constructor (props) {
......@@ -212,7 +213,7 @@ class PasswordReset extends React.Component {
<Grid>
<Row>
<Col md={2} mdOffset={5}>
<img src="/assets/pubsweet-rgb-small.jpg" className="auth-logo" alt="pubsweet-logo" style={{maxWidth: '100%'}}/>
<img src="/assets/pubsweet-rgb-small.jpg" className={styles.logo} alt="pubsweet-logo" style={{maxWidth: '100%'}}/>
</Col>
</Row>
......@@ -222,7 +223,7 @@ class PasswordReset extends React.Component {
{buildError(passwordErrorMessage)}
</Col>
<Col xs={12} md={4}>
<Col xs={12} md={4} className={styles.passwordReset}>
<h1>Password reset</h1>
{buildForm()}
......
{
"name": "pubsweet-component-password-reset-frontend",
"version": "0.2.0",
"version": "0.2.1",
"description": "Password reset frontend component for PubSweet",
"main": "index.js",
"scripts": {
......
{
"name": "pubsweet-component-posts-manager",
"version": "0.6.0",
"version": "0.6.2",
"description": "Basic Posts manager component for PubSweet",
"main": "index.js",
"scripts": {
......
......@@ -20,7 +20,7 @@ export default class Signup extends Component {
<Grid>
<Row>
<Col md={2} mdOffset={5}>
<img src="/assets/pubsweet-rgb-small.jpg" className="auth-logo" alt="pubsweet-logo" style={{maxWidth: '100%'}}/>
<img src="/assets/pubsweet-rgb-small.jpg" className={styles.logo} alt="pubsweet-logo" style={{maxWidth: '100%'}}/>
</Col>
</Row>
......
{
"name": "pubsweet-component-signup",
"version": "0.4.0",
"version": "0.4.1",
"description": "Basic signup form component for PubSweet",
"main": "index.js",
"scripts": {
......