rittenhop-ghost/versions/5.94.2/core/server/lib/lexical.js

168 lines
5.4 KiB
JavaScript

const path = require('path');
const errors = require('@tryghost/errors');
const urlUtils = require('../../shared/url-utils');
const config = require('../../shared/config');
const labs = require('../../shared/labs');
const storage = require('../adapters/storage');
let nodes;
let lexicalHtmlRenderer;
let urlTransformMap;
let postsService;
let serializePosts;
function populateNodes() {
const {DEFAULT_NODES} = require('@tryghost/kg-default-nodes');
nodes = DEFAULT_NODES;
}
module.exports = {
get blankDocument() {
return {
root: {
children: [
{
children: [],
direction: null,
format: '',
indent: 0,
type: 'paragraph',
version: 1
}
],
direction: null,
format: '',
indent: 0,
type: 'root',
version: 1
}
};
},
get lexicalHtmlRenderer() {
if (!lexicalHtmlRenderer) {
if (!nodes) {
populateNodes();
}
const LexicalHtmlRenderer = require('@tryghost/kg-lexical-html-renderer');
lexicalHtmlRenderer = new LexicalHtmlRenderer({nodes});
}
return lexicalHtmlRenderer;
},
async render(lexical, userOptions = {}) {
if (!postsService) {
const getPostServiceInstance = require('../services/posts/posts-service');
postsService = getPostServiceInstance();
}
if (!serializePosts) {
serializePosts = require('../api/endpoints/utils/serializers/output/posts').all;
}
const getCollectionPosts = async (collectionSlug, postCount) => {
const frame = {
options: {
columns: ['url','excerpt','reading_time']
},
original: {
context: {
member: {
status: 'paid'
}
}
},
apiType: 'content',
response: {}
};
const transacting = userOptions.transacting;
const response = await postsService.browsePosts({
context: {public: true}, // mimic Content API request
collection: collectionSlug,
limit: postCount,
transacting
});
await serializePosts(response, null, frame);
return frame.response.posts;
};
const options = Object.assign({
siteUrl: config.get('url'),
imageOptimization: config.get('imageOptimization'),
canTransformImage(storagePath) {
const imageTransform = require('@tryghost/image-transform');
const {ext} = path.parse(storagePath);
// NOTE: the "saveRaw" check is smelly
return imageTransform.canTransformFiles()
&& imageTransform.shouldResizeFileExtension(ext)
&& typeof storage.getStorage('images').saveRaw === 'function';
},
getCollectionPosts,
feature: {
contentVisibility: labs.isSet('contentVisibility')
}
}, userOptions);
return await this.lexicalHtmlRenderer.render(lexical, options);
},
get nodes() {
if (!nodes) {
populateNodes();
}
return nodes;
},
get urlTransformMap() {
if (!urlTransformMap) {
urlTransformMap = {
absoluteToRelative: {
url: urlUtils.absoluteToRelative.bind(urlUtils),
html: urlUtils.htmlAbsoluteToRelative.bind(urlUtils),
markdown: urlUtils.markdownAbsoluteToRelative.bind(urlUtils)
},
relativeToAbsolute: {
url: urlUtils.relativeToAbsolute.bind(urlUtils),
html: urlUtils.htmlRelativeToAbsolute.bind(urlUtils),
markdown: urlUtils.markdownRelativeToAbsolute.bind(urlUtils)
},
toTransformReady: {
url: urlUtils.toTransformReady.bind(urlUtils),
html: urlUtils.htmlToTransformReady.bind(urlUtils),
markdown: urlUtils.markdownToTransformReady.bind(urlUtils)
}
};
}
return urlTransformMap;
},
get htmlToLexicalConverter() {
try {
if (process.env.CI) {
console.time('require @tryghost/kg-html-to-lexical'); // eslint-disable-line no-console
}
const htmlToLexical = require('@tryghost/kg-html-to-lexical').htmlToLexical;
if (process.env.CI) {
console.timeEnd('require @tryghost/kg-html-to-lexical'); // eslint-disable-line no-console
}
return htmlToLexical;
} catch (err) {
throw new errors.InternalServerError({
message: 'Unable to convert from source HTML to Lexical',
context: 'The html-to-lexical package was not installed',
help: 'Please review any errors from the install process by checking the Ghost logs',
code: 'HTML_TO_LEXICAL_INSTALLATION',
err: err
});
}
}
};