Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
render(tokens, idx) {
const { escapeHtml } = instance.escapeHtml
const attrs = { image: '', caption: '', citation: '' }
let result = ''
if (tokens[idx].nesting === 1) {
// opening tag
let matches
while ((matches = attrsRe.exec(tokens[idx].info.trim())) !== null) {
// eslint-disable-next-line prefer-destructuring
attrs[matches[1]] = matches[2]
}
if (!attrs.image && !attrs.caption) {
log.error(`[${context.fileName}.md] Malformed directive.`)
result = ''
} else if (!attrs.image && attrs.caption) {
const captions = attrs.caption.split('|').map(_ => _.trim())
const citations = attrs.citation.split('|').map(_ => _.trim())
result = [
'<section class="epigraph chapter">',
'<section class="subchapter">',
captions
.map(
(caption, idx2) =>
`<div class="pullquote full-width">
<p>${escapeHtml(caption)}</p>
${
citations[idx2]
? `<cite>—${escapeHtml(
citations[idx2]</cite></div></section></section>
static createSpineStringsFromTemplate() {
log.info('opf build [spine]')
const { flattened } = state.spine
// We add entries to the spine programatically, but then they're
// also found on the system, so we dedupe them here
// TODO: but also, this is super confusing ...
const generatedFiles = remove(flattened, file => file.generated === true)
generatedFiles.forEach(file => {
if (!find(flattened, { fileName: file.fileName })) {
flattened.push(file)
}
})
const spineXML = Spine.items(flattened)
if (curr.linear === false) {
if (state.build === 'mobi') {
log.info(
`opf templates/spine omitting non-linear asset [${fileName}] for mobi build`
)
return acc
}
log.info(`opf templates/spine writing non-linear asset [${fileName}]`)
}
if (fileName.match(/figure/)) {
// TODO: this should be handled more transparently, rn it feels a bit like a side-effect
// https://github.com/triplecanopy/b-ber/issues/208
log.info('opf templates/spine writing [loi]')
if (state.loi.length) {
return acc.concat(
state.loi.reduce(
(acc2, curr2) =>
acc2.concat(Spine.item({ ...curr2, linear: true })),
Spine.item(curr)
)
)
}
}
return acc.concat(Spine.item(curr))
}, '')
}
function prepare({ token, match, instance, context, fileName, lineNumber }) {
const [, type, id, attrs] = match
const figureId = htmlId(id)
const caption = token.children ? instance.renderInline(token.children) : ''
const comment = Html.comment(
`START: figure:${type}#${figureId}; ${fileName}:${lineNumber}`
)
const attrsObject = attributesObject(attrs, type, { fileName, lineNumber })
const asset = state.src.images(attrsObject.source)
const mediaType =
(type.indexOf('-') && type.substring(0, type.indexOf('-'))) || type
// make sure image exists
if (!fs.existsSync(asset)) log.error(`Image not found [${asset}]`)
// then get the dimensions
const { width, height } = sizeOf(asset)
return {
width,
height,
caption,
comment,
context,
attrsObject,
asset,
mediaType,
id: figureId,
}
}
if (coverListedInMetadata) {
// TODO: fixme, for generated covers
// @issue: https://github.com/triplecanopy/b-ber/issues/208
this.coverEntry = coverListedInMetadata.replace(/_jpg$/, '.jpg')
log.info('cover verify image [%s]', this.coverEntry)
// there's a reference to a cover image so we create a cover.xhtml file
// containing an SVG-wrapped `image` element with the appropriate cover
// dimensions, and write it to the `text` dir.
// check that the cover image file exists, throw if not
this.coverImagePath = state.src.images(this.coverEntry)
if (!fs.existsSync(this.coverImagePath)) {
log.error('cover image listed in metadata.yml cannot be found [%s]', this.coverImagePath)
}
return this.generateCoverXHTML()
} // end if cover exists
// if there's no cover referenced in the metadata.yml, we create one
// that displays the book's metadata (title, generator version, etc)
// and add it to metadata.yml
log.info('cover generated image [%s]', this.coverEntry)
const coverMetadata = { term: 'cover', value: this.coverEntry }
state.metadata.add(coverMetadata)
this.metadata = { ...coverMetadata, ...this.metadata, ...metadata }
return this.removeDefaultCovers()
let theme
if (defaultThemes[name]) {
theme = defaultThemes[name]
} else {
// check for both vendor and user paths
const userPath = path.resolve(state.config.themes_directory, name)
const vendorPath = path.resolve('node_modules', name)
// prefer the user path if both exist, since a user might've
// copied over the vendor theme and is changing it
const themePath = fs.existsSync(userPath) ? userPath : fs.existsSync(vendorPath) ? vendorPath : null
if (themes.indexOf(name) < 0 || !themePath) {
log.error(`Theme [${name}] is not installed`)
}
theme = require(themePath)
}
return createProjectThemeDirectory(name)
.then(() => copyThemeAssets(theme))
.then(() => updateConfig(name))
.then(() => !force && log.notice('Updated theme to', name))
.catch(log.error)
}
}
} else {
sources = [source]
sourceElements = createRemoteMediaSource(sources)
}
state.add('remoteAssets', source)
} else if (validateLocalMediaSource(source, mediaType)) {
sources = media.filter(a => toAlias(a) === source)
sourceElements = createLocalMediaSources(sources)
}
if (!sources.length && type !== 'iframe' && type !== 'iframe-inline') {
err = new Error(
`bber-directives: Could not find matching [${mediaType}] with the basename [${source}]`
)
log.error(err)
}
delete attrsObject.source // otherwise we get a `src` tag on our video element
if (mediaType === 'audio') {
delete attrsObject.poster // invalid attr for audio elements
}
if (mediaType === 'video') {
// TODO: needs to be done async
//
// add aspect ratio class name
// const aspecRatioClassName = isHostedRemotely(source)
// ? getVideoAspectRatio()
// : getVideoAspectRatio(path.resolve(state.src.media(head(sources))))
aspecRatioClassName = 'video--16x9'
// possibly a user defined theme, check if the directory exists
try {
if ((this.theme = require(path.resolve(userThemesPath, this.config.theme)))) {
log.info(`Loaded theme [${this.config.theme}]`)
return
}
} catch (err) {
// noop
}
// possibly a theme installed with npm, test the project root
try {
this.theme = require(path.resolve('node_modules', this.config.theme)) // require.resolve?
} catch (err) {
log.warn(`There was an error during require [${this.config.theme}]`)
log.warn('Using default theme [b-ber-theme-serif]')
log.warn(err.message)
// error loading theme, set to default
this.theme = themes['b-ber-theme-serif']
}
}
log.info(`Loaded theme [${this.config.theme}]`)
return
}
} catch (_) {
// noop
}
// possibly a theme installed with npm, test the project root
try {
set(
this,
'theme',
require(path.resolve('node_modules', this.config.theme)) // eslint-disable-line global-require, import/no-dynamic-require
) // require.resolve?
} catch (err) {
log.warn(`There was an error during require [${this.config.theme}]`)
log.warn('Using default theme [b-ber-theme-serif]')
log.warn(err.message)
// error loading theme, set to default
set(this, 'theme', themes['b-ber-theme-serif'])
}
}
}
} catch (_) {
// noop
}
// possibly a theme installed with npm, test the project root
try {
set(
this,
'theme',
require(path.resolve('node_modules', this.config.theme)) // eslint-disable-line global-require, import/no-dynamic-require
) // require.resolve?
} catch (err) {
log.warn(`There was an error during require [${this.config.theme}]`)
log.warn('Using default theme [b-ber-theme-serif]')
log.warn(err.message)
// error loading theme, set to default
set(this, 'theme', themes['b-ber-theme-serif'])
}
}