Cleaned up lexicalEditor labs flag, switched Post model to lexical-by-default (#18607)

no issue

- flag is no longer used in Admin so we can clean it up in Core too
- updated Post model to set blank document to `lexical` field rather than `mobiledoc` as a default value
- switched over to returning `mobiledoc,lexical` as default formats in Admin API
This commit is contained in:
Kevin Ansfield 2023-10-23 17:51:34 +01:00 committed by GitHub
parent aabeb64a38
commit 9b1f79f601
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 191 additions and 395 deletions

View File

@ -58,7 +58,6 @@ let defaultLabFlags = {
outboundLinkTagging: false,
announcementBar: false,
signupForm: false,
lexicalEditor: false,
members: false
};

View File

@ -6,7 +6,6 @@ const slugFilterOrder = require('./utils/slug-filter-order');
const localUtils = require('../../index');
const postsMetaSchema = require('../../../../../data/schema').tables.posts_meta;
const clean = require('./utils/clean');
const labs = require('../../../../../../shared/labs');
const lexical = require('../../../../../lib/lexical');
function removeSourceFormats(frame) {
@ -57,7 +56,7 @@ function defaultFormat(frame) {
return;
}
frame.options.formats = 'mobiledoc';
frame.options.formats = 'mobiledoc,lexical';
}
function handlePostsMeta(frame) {
@ -138,11 +137,9 @@ module.exports = {
// normally we don't allow both mobiledoc+lexical but the model layer will remove lexical
// if mobiledoc is already present to avoid migrating formats outside of an explicit conversion
if (labs.isSet('lexicalEditor')) {
frame.data.pages[0].lexical = JSON.stringify(lexical.htmlToLexicalConverter(html));
}
}
}
frame.data.pages[0] = url.forPost(Object.assign({}, frame.data.pages[0]), frame.options);

View File

@ -6,7 +6,6 @@ const localUtils = require('../../index');
const mobiledoc = require('../../../../../lib/mobiledoc');
const postsMetaSchema = require('../../../../../data/schema').tables.posts_meta;
const clean = require('./utils/clean');
const labs = require('../../../../../../shared/labs');
const lexical = require('../../../../../lib/lexical');
function removeSourceFormats(frame) {
@ -74,7 +73,7 @@ function defaultFormat(frame) {
return;
}
frame.options.formats = 'mobiledoc';
frame.options.formats = 'mobiledoc,lexical';
}
function handlePostsMeta(frame) {
@ -172,11 +171,9 @@ module.exports = {
// normally we don't allow both mobiledoc+lexical but the model layer will remove lexical
// if mobiledoc is already present to avoid migrating formats outside of an explicit conversion
if (labs.isSet('lexicalEditor')) {
frame.data.posts[0].lexical = JSON.stringify(lexical.htmlToLexicalConverter(html));
}
}
}
frame.data.posts[0] = url.forPost(Object.assign({}, frame.data.posts[0]), frame.options);

View File

@ -16,6 +16,28 @@ function populateNodes() {
}
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) {

View File

@ -392,6 +392,11 @@ Post = ghostBookshelf.Model.extend({
const html = await lexicalLib.render(model.get('lexical'));
const plaintext = htmlToPlaintext.excerpt(html);
// avoid a DB query if we have no html - knex will set it to an empty string rather than NULL
if (!html && !model.get('plaintext')) {
return model;
}
// set model attributes so they are available immediately in code that uses the returned model
model.set('html', html);
model.set('plaintext', plaintext);
@ -716,7 +721,7 @@ Post = ghostBookshelf.Model.extend({
}
if (!this.get('mobiledoc') && !this.get('lexical')) {
this.set('mobiledoc', JSON.stringify(mobiledocLib.blankDocument));
this.set('lexical', JSON.stringify(lexicalLib.blankDocument));
}
// If we're force re-rendering we want to make sure that all image cards
@ -984,7 +989,7 @@ Post = ghostBookshelf.Model.extend({
}
// CASE: Convert post to lexical on the fly
if (labs.isSet('lexicalEditor') && options.convert_to_lexical) {
if (options.convert_to_lexical) {
ops.push(async function convertToLexical() {
const mobiledoc = model.get('mobiledoc');
if (mobiledoc !== null) { // only run conversion when there is a mobiledoc string

View File

@ -19,8 +19,7 @@ const GA_FEATURES = [
'themeErrorsNotification',
'outboundLinkTagging',
'announcementBar',
'signupForm',
'lexicalEditor'
'signupForm'
];
// NOTE: this allowlist is meant to be used to filter out any unexpected

File diff suppressed because one or more lines are too long

View File

@ -788,10 +788,10 @@ Object {
"frontmatter": null,
"html": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
@ -878,10 +878,10 @@ Object {
"featured": false,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
@ -947,113 +947,7 @@ exports[`Pages API Copy Can copy a page 3: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "3779",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/pages\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
"vary": "Accept-Version, Origin, Accept-Encoding",
"x-powered-by": "Express",
}
`;
exports[`Pages API Create Can create a page with html (labs.lexicalEditor) 1: [body] 1`] = `
Object {
"pages": Array [
Object {
"authors": Any<Array>,
"canonical_url": null,
"codeinjection_foot": null,
"codeinjection_head": null,
"comment_id": Any<String>,
"count": Object {
"negative_feedback": 0,
"paid_conversions": 0,
"positive_feedback": 0,
"signups": 0,
},
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"custom_excerpt": null,
"custom_template": null,
"excerpt": "Testing page creation with html",
"feature_image": null,
"feature_image_alt": null,
"feature_image_caption": null,
"featured": false,
"frontmatter": null,
"html": "<p>Testing page creation with html</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[{\\"detail\\":0,\\"format\\":0,\\"mode\\":\\"normal\\",\\"style\\":\\"\\",\\"text\\":\\"Testing page creation with html\\",\\"type\\":\\"extended-text\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"primary_author": Any<Object>,
"primary_tag": Any<Object>,
"published_at": null,
"reading_time": 0,
"show_title_and_feature_image": Any<Boolean>,
"slug": "html-test-2",
"status": "draft",
"tags": Any<Array>,
"tiers": Array [
Object {
"active": true,
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"currency": null,
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"monthly_price": null,
"monthly_price_id": null,
"name": "Free",
"slug": "free",
"trial_days": 0,
"type": "free",
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"visibility": "public",
"welcome_page_url": null,
"yearly_price": null,
"yearly_price_id": null,
},
Object {
"active": true,
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"currency": "usd",
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"monthly_price": 500,
"monthly_price_id": null,
"name": "Default Product",
"slug": "default-product",
"trial_days": 0,
"type": "paid",
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"visibility": "public",
"welcome_page_url": null,
"yearly_price": 5000,
"yearly_price_id": null,
},
],
"title": "HTML test",
"twitter_description": null,
"twitter_image": null,
"twitter_title": null,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"url": Any<String>,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"visibility": "public",
},
],
}
`;
exports[`Pages API Create Can create a page with html (labs.lexicalEditor) 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "4091",
"content-length": "3859",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
@ -1089,10 +983,10 @@ Object {
"frontmatter": null,
"html": "<p>Testing page creation with html</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[{\\"detail\\":0,\\"format\\":0,\\"mode\\":\\"normal\\",\\"style\\":\\"\\",\\"text\\":\\"Testing page creation with html\\",\\"type\\":\\"extended-text\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"atoms\\":[],\\"cards\\":[],\\"markups\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"Testing page creation with html\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
@ -1159,7 +1053,7 @@ exports[`Pages API Create Can create a page with html 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "3867",
"content-length": "4089",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
@ -1289,10 +1183,10 @@ Object {
"frontmatter": null,
"html": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
@ -1358,7 +1252,7 @@ exports[`Pages API Update Can modify show_title_and_feature_image property 2: [h
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "3780",
"content-length": "3860",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,

View File

@ -38,6 +38,7 @@ Object {
"featured": false,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[[\\"markdown\\",{\\"markdown\\":\\"<h1>Welcome to my invisible post!</h1>\\"}]],\\"sections\\":[[10,0]]}",
@ -126,6 +127,7 @@ Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac tu
"featured": false,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"meta_description": "meta description for draft post",
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[[\\"markdown\\",{\\"markdown\\":\\"<h1>HTML Ipsum Presents</h1><p><strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em> Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. <a href=\\\\\\"#\\\\\\">Donec non enim</a> in turpis pulvinar facilisis. Ut felis.</p><h2>Header Level 2</h2><ol><li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li><li>Aliquam tincidunt mauris eu risus.</li></ol><blockquote><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est.</p></blockquote><h3>Header Level 3</h3><ul><li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li><li>Aliquam tincidunt mauris eu risus.</li></ul><pre><code>#header h1 a{display: block;width: 300px;height: 80px;}</code></pre>\\"}]],\\"sections\\":[[10,0]]}",
@ -195,7 +197,7 @@ exports[`Posts API Can browse 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "10706",
"content-length": "10736",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
@ -253,6 +255,7 @@ Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut
"featured": true,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[[\\"markdown\\",{\\"markdown\\":\\"<p><nav><ul><li><a href=\\\\\\"#nowhere\\\\\\" title=\\\\\\"Anchor URL\\\\\\">Lorem</a></li><li><a href=\\\\\\"http://127.0.0.1:2369/about#nowhere\\\\\\" title=\\\\\\"Relative URL\\\\\\">Aliquam</a></li><li><a href=\\\\\\"//somewhere.com/link#nowhere\\\\\\" title=\\\\\\"Protocol Relative URL\\\\\\">Tortor</a></li><li><a href=\\\\\\"http://somewhere.com/link#nowhere\\\\\\" title=\\\\\\"Absolute URL\\\\\\">Morbi</a></li><li><a href=\\\\\\"#nowhere\\\\\\" title=\\\\\\"Praesent dapibus, neque id cursus faucibus\\\\\\">Praesent</a></li><li><a href=\\\\\\"#nowhere\\\\\\" title=\\\\\\"Pellentesque fermentum dolor\\\\\\">Pellentesque</a></li></ul></nav><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p><table><thead><tr><th>1</th><th>2</th><th>3</th><th>4</th></tr></thead><tbody><tr><td>a</td><td>b</td><td>c</td><td>d</td></tr><tr><td>e</td><td>f</td><td>g</td><td>h</td></tr><tr><td>i</td><td>j</td><td>k</td><td>l</td></tr></tbody></table><dl><dt>Definition list</dt><dd>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</dd><dt>Lorem ipsum dolor sit amet</dt><dd>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</dd></dl><ul><li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</li><li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.</li><li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.</li><li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.</li></ul></p>\\"}]],\\"sections\\":[[10,0]]}",
@ -348,6 +351,7 @@ mctesters
"featured": true,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"meta_description": "meta description for short and sweet",
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[[\\"markdown\\",{\\"markdown\\":\\"## testing\\\\n\\\\nmctesters\\\\n\\\\n- test\\\\n- line\\\\n- items\\"}]],\\"sections\\":[[10,0]]}",
@ -417,7 +421,7 @@ exports[`Posts API Can browse filtering by a collection 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "11701",
"content-length": "11731",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
@ -464,6 +468,7 @@ Object {
"featured": false,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"atoms\\":[],\\"cards\\":[[\\"image\\",{\\"src\\":\\"https://static.ghost.org/v4.0.0/images/portalsettings.png\\",\\"width\\":2924,\\"height\\":1810,\\"cardWidth\\":\\"wide\\"}],[\\"hr\\",{}]],\\"markups\\":[[\\"em\\"],[\\"a\\",[\\"href\\",\\"#/portal\\"]],[\\"a\\",[\\"href\\",\\"http://127.0.0.1:2369/sell/\\"]]],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"What sets Ghost apart from other products is that you can publish content and grow your audience using the same platform. Rather than just endlessly posting and hoping someone is listening, you can track real signups against your work and have them subscribe to be notified of future posts. The feature that makes all this possible is called \\"],[0,[0],1,\\"Portal\\"],[0,[],0,\\".\\"]]],[1,\\"p\\",[[0,[],0,\\"Portal is an embedded interface for your audience to sign up to your site. It works on every Ghost site, with every theme, and for any type of publisher. \\"]]],[1,\\"p\\",[[0,[],0,\\"You can customize the design, content and settings of Portal to suit your site, whether you just want people to sign up to your newsletter — or you're running a full premium publication with user sign-ins and private content.\\"]]],[10,0],[1,\\"p\\",[[0,[],0,\\"Once people sign up to your site, they'll receive an email confirmation with a link to click. The link acts as an automatic sign-in, so subscribers will be automatically signed-in to your site when they click on it. There are a couple of interesting angles to this:\\"]]],[1,\\"p\\",[[0,[],0,\\"Because subscribers are automatically able to sign in and out of your site as registered members: You can (optionally) restrict access to posts and pages depending on whether people are signed-in or not. So if you want to publish some posts for free, but keep some really great stuff for members-only, this can be a great draw to encourage people to sign up!\\"]]],[1,\\"p\\",[[0,[],0,\\"Ghost members sign in using email authentication links, so there are no passwords for people to set or forget. You can turn any list of email subscribers into a database of registered members who can sign in to your site. Like magic.\\"]]],[1,\\"p\\",[[0,[],0,\\"Portal makes all of this possible, and it appears by default as a floating button in the bottom-right corner of your site. When people are logged out, clicking it will open a sign-up/sign-in window. When members are logged in, clicking the Portal button will open the account menu where they can edit their name, email, and subscription settings.\\"]]],[1,\\"p\\",[[0,[],0,\\"The floating Portal button is completely optional. If you prefer, you can add manual links to your content, navigation, or theme to trigger it instead.\\"]]],[1,\\"p\\",[[0,[],0,\\"Like this! \\"],[0,[1],1,\\"Sign up here\\"]]],[10,1],[1,\\"p\\",[[0,[],0,\\"As you start to grow your registered audience, you'll be able to get a sense of who you're publishing \\"],[0,[0],1,\\"for\\"],[0,[],0,\\" and where those people are coming \\"],[0,[0],1,\\"from\\"],[0,[],0,\\". Best of all: You'll have a straightforward, reliable way to connect with people who enjoy your work.\\"]]],[1,\\"p\\",[[0,[],0,\\"Social networks go in and out of fashion all the time. Email addresses are timeless.\\"]]],[1,\\"p\\",[[0,[],0,\\"Growing your audience is valuable no matter what type of site you run, but if your content \\"],[0,[0],1,\\"is\\"],[0,[],0,\\" your business, then you might also be interested in \\"],[0,[2],1,\\"setting up premium subscriptions\\"],[0,[],0,\\".\\"]]]],\\"ghostVersion\\":\\"4.0\\"}",
@ -533,7 +538,7 @@ exports[`Posts API Can browse filtering by collection using paging parameters 2:
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "8802",
"content-length": "8817",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
@ -1015,10 +1020,10 @@ Object {
"featured": false,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"newsletter": null,
"og_description": null,
"og_image": null,
@ -1084,116 +1089,7 @@ exports[`Posts API Copy Can copy a post 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "3814",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"location": StringMatching /https\\?:\\\\/\\\\/\\.\\*\\?\\\\/posts\\\\/\\[a-f0-9\\]\\{24\\}\\\\//,
"vary": "Accept-Version, Origin, Accept-Encoding",
"x-powered-by": "Express",
}
`;
exports[`Posts API Create Can create a post with html (labs.lexicalEditor) 1: [body] 1`] = `
Object {
"posts": Array [
Object {
"authors": Any<Array>,
"canonical_url": null,
"codeinjection_foot": null,
"codeinjection_head": null,
"comment_id": Any<String>,
"count": Object {
"clicks": 0,
"negative_feedback": 0,
"positive_feedback": 0,
},
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"custom_excerpt": null,
"custom_template": null,
"email": null,
"email_only": false,
"email_segment": "all",
"email_subject": null,
"excerpt": "Testing post creation with html",
"feature_image": null,
"feature_image_alt": null,
"feature_image_caption": null,
"featured": false,
"frontmatter": null,
"html": "<p>Testing post creation with html</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[{\\"detail\\":0,\\"format\\":0,\\"mode\\":\\"normal\\",\\"style\\":\\"\\",\\"text\\":\\"Testing post creation with html\\",\\"type\\":\\"extended-text\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": null,
"newsletter": null,
"og_description": null,
"og_image": null,
"og_title": null,
"primary_author": Any<Object>,
"primary_tag": Any<Object>,
"published_at": null,
"reading_time": 0,
"slug": "html-test-2",
"status": "draft",
"tags": Any<Array>,
"tiers": Array [
Object {
"active": true,
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"currency": null,
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"monthly_price": null,
"monthly_price_id": null,
"name": "Free",
"slug": "free",
"trial_days": 0,
"type": "free",
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"visibility": "public",
"welcome_page_url": null,
"yearly_price": null,
"yearly_price_id": null,
},
Object {
"active": true,
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"currency": "usd",
"description": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"monthly_price": 500,
"monthly_price_id": null,
"name": "Default Product",
"slug": "default-product",
"trial_days": 0,
"type": "paid",
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"visibility": "public",
"welcome_page_url": null,
"yearly_price": 5000,
"yearly_price_id": null,
},
],
"title": "HTML test",
"twitter_description": null,
"twitter_image": null,
"twitter_title": null,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"url": Any<String>,
"uuid": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"visibility": "public",
},
],
}
`;
exports[`Posts API Create Can create a post with html (labs.lexicalEditor) 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "4126",
"content-length": "3894",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
@ -1232,10 +1128,10 @@ Object {
"frontmatter": null,
"html": "<p>Testing post creation with html</p>",
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[{\\"detail\\":0,\\"format\\":0,\\"mode\\":\\"normal\\",\\"style\\":\\"\\",\\"text\\":\\"Testing post creation with html\\",\\"type\\":\\"extended-text\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"atoms\\":[],\\"cards\\":[],\\"markups\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"Testing post creation with html\\"]]]]}",
"mobiledoc": null,
"newsletter": null,
"og_description": null,
"og_image": null,
@ -1302,7 +1198,7 @@ exports[`Posts API Create Can create a post with html 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "3902",
"content-length": "4124",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
@ -1641,6 +1537,7 @@ Definition listConsectetur adipisicing elit, sed do eiusmod tempor incididunt ut
"featured": true,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[[\\"markdown\\",{\\"markdown\\":\\"<p><nav><ul><li><a href=\\\\\\"#nowhere\\\\\\" title=\\\\\\"Anchor URL\\\\\\">Lorem</a></li><li><a href=\\\\\\"http://127.0.0.1:2369/about#nowhere\\\\\\" title=\\\\\\"Relative URL\\\\\\">Aliquam</a></li><li><a href=\\\\\\"//somewhere.com/link#nowhere\\\\\\" title=\\\\\\"Protocol Relative URL\\\\\\">Tortor</a></li><li><a href=\\\\\\"http://somewhere.com/link#nowhere\\\\\\" title=\\\\\\"Absolute URL\\\\\\">Morbi</a></li><li><a href=\\\\\\"#nowhere\\\\\\" title=\\\\\\"Praesent dapibus, neque id cursus faucibus\\\\\\">Praesent</a></li><li><a href=\\\\\\"#nowhere\\\\\\" title=\\\\\\"Pellentesque fermentum dolor\\\\\\">Pellentesque</a></li></ul></nav><p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p><table><thead><tr><th>1</th><th>2</th><th>3</th><th>4</th></tr></thead><tbody><tr><td>a</td><td>b</td><td>c</td><td>d</td></tr><tr><td>e</td><td>f</td><td>g</td><td>h</td></tr><tr><td>i</td><td>j</td><td>k</td><td>l</td></tr></tbody></table><dl><dt>Definition list</dt><dd>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</dd><dt>Lorem ipsum dolor sit amet</dt><dd>Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</dd></dl><ul><li>Morbi in sem quis dui placerat ornare. Pellentesque odio nisi, euismod in, pharetra a, ultricies in, diam. Sed arcu. Cras consequat.</li><li>Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus.</li><li>Phasellus ultrices nulla quis nibh. Quisque a lectus. Donec consectetuer ligula vulputate sem tristique cursus. Nam nulla quam, gravida non, commodo a, sodales sit amet, nisi.</li><li>Pellentesque fermentum dolor. Aliquam quam lectus, facilisis auctor, ultrices ut, elementum vulputate, nunc.</li></ul></p>\\"}]],\\"sections\\":[[10,0]]}",
@ -1736,6 +1633,7 @@ mctesters
"featured": true,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": null,
"meta_description": "meta description for short and sweet",
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[[\\"markdown\\",{\\"markdown\\":\\"## testing\\\\n\\\\nmctesters\\\\n\\\\n- test\\\\n- line\\\\n- items\\"}]],\\"sections\\":[[10,0]]}",
@ -1805,7 +1703,7 @@ exports[`Posts API Delete Can delete posts belonging to a collection and returns
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "11701",
"content-length": "11731",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
@ -2019,9 +1917,10 @@ Object {
"featured": false,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"newsletter": null,
"og_description": null,
"og_image": null,
@ -2087,7 +1986,7 @@ exports[`Posts API Update Can add and remove collections 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "3813",
"content-length": "3908",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
@ -2214,10 +2113,6 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"sort_order": 20,
},
Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"sort_order": 21,
},
],
"slug": "latest",
"title": "Latest",
@ -2245,9 +2140,10 @@ Object {
"featured": false,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"newsletter": null,
"og_description": null,
"og_image": null,
@ -2313,7 +2209,7 @@ exports[`Posts API Update Can add and remove collections 4: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "5459",
"content-length": "5504",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
@ -2440,10 +2336,6 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"sort_order": 20,
},
Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"sort_order": 21,
},
],
"slug": "latest",
"title": "Latest",
@ -2471,9 +2363,10 @@ Object {
"featured": false,
"frontmatter": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"lexical": "{\\"root\\":{\\"children\\":[{\\"children\\":[],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"paragraph\\",\\"version\\":1}],\\"direction\\":null,\\"format\\":\\"\\",\\"indent\\":0,\\"type\\":\\"root\\",\\"version\\":1}}",
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"newsletter": null,
"og_description": null,
"og_image": null,
@ -2539,7 +2432,7 @@ exports[`Posts API Update Can add and remove collections 6: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "5453",
"content-length": "5498",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,

View File

@ -758,7 +758,7 @@ exports[`Settings API Edit Can edit a setting 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "4278",
"content-length": "4255",
"content-type": "application/json; charset=utf-8",
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,

View File

@ -38,7 +38,7 @@ describe('Pages API', function () {
jsonResponse.pages[1].url.should.eql(`${config.get('url')}/contribute/`);
});
it('Can retrieve pages with lexical format', async function () {
it('Can retrieve pages with just lexical format', async function () {
const res = await request.get(localUtils.API.getApiQuery('pages/?formats=lexical'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
@ -121,7 +121,7 @@ describe('Pages API', function () {
res.body.pages.length.should.eql(1);
const [returnedPage] = res.body.pages;
const additionalProperties = ['lexical', 'reading_time'];
const additionalProperties = ['reading_time'];
localUtils.API.checkResponse(returnedPage, 'page', additionalProperties);
should.equal(returnedPage.mobiledoc, page.mobiledoc);
@ -172,7 +172,7 @@ describe('Pages API', function () {
res.body.pages.length.should.eql(1);
const [returnedPage] = res.body.pages;
const additionalProperties = ['lexical', 'html', 'reading_time'];
const additionalProperties = ['html', 'reading_time'];
localUtils.API.checkResponse(returnedPage, 'page', additionalProperties);
should.equal(returnedPage.mobiledoc, null);

View File

@ -80,30 +80,6 @@ describe('Pages API', function () {
describe('Create', function () {
it('Can create a page with html', async function () {
mockManager.mockLabsDisabled('lexicalEditor');
const page = {
title: 'HTML test',
html: '<p>Testing page creation with html</p>'
};
await agent
.post('/pages/?source=html&formats=mobiledoc,lexical,html')
.body({pages: [page]})
.expectStatus(201)
.matchBodySnapshot({
pages: [Object.assign({}, matchPageShallowIncludes, {published_at: null})]
})
.matchHeaderSnapshot({
'content-version': anyContentVersion,
etag: anyEtag,
location: anyLocationFor('pages')
});
});
it('Can create a page with html (labs.lexicalEditor)', async function () {
mockManager.mockLabsEnabled('lexicalEditor');
const page = {
title: 'HTML test',
html: '<p>Testing page creation with html</p>'

View File

@ -85,7 +85,7 @@ describe('Posts API', function () {
});
it('Can retrieve multiple post formats', async function () {
const res = await request.get(localUtils.API.getApiQuery('posts/?formats=plaintext,mobiledoc&limit=3&order=title%20ASC'))
const res = await request.get(localUtils.API.getApiQuery('posts/?formats=plaintext,mobiledoc,lexical&limit=3&order=title%20ASC'))
.set('Origin', config.get('url'))
.expect('Content-Type', /json/)
.expect('Cache-Control', testUtils.cacheRules.private)

View File

@ -324,30 +324,6 @@ describe('Posts API', function () {
});
it('Can create a post with html', async function () {
mockManager.mockLabsDisabled('lexicalEditor');
const post = {
title: 'HTML test',
html: '<p>Testing post creation with html</p>'
};
await agent
.post('/posts/?source=html&formats=mobiledoc,lexical,html')
.body({posts: [post]})
.expectStatus(201)
.matchBodySnapshot({
posts: [Object.assign({}, matchPostShallowIncludes, {published_at: null})]
})
.matchHeaderSnapshot({
'content-version': anyContentVersion,
etag: anyEtag,
location: anyLocationFor('posts')
});
});
it('Can create a post with html (labs.lexicalEditor)', async function () {
mockManager.mockLabsEnabled('lexicalEditor');
const post = {
title: 'HTML test',
html: '<p>Testing post creation with html</p>'
@ -637,7 +613,7 @@ describe('Posts API', function () {
// collectionToRemove
collectionMatcher,
// automatic "latest" collection which cannot be removed
buildCollectionMatcher(22)
buildCollectionMatcher(21)
]})]
})
.matchHeaderSnapshot({
@ -655,7 +631,7 @@ describe('Posts API', function () {
// collectionToAdd
collectionMatcher,
// automatic "latest" collection which cannot be removed
buildCollectionMatcher(22)
buildCollectionMatcher(21)
]})]
})
.matchHeaderSnapshot({

View File

@ -50,6 +50,7 @@ const expectedProperties = {
'title',
'slug',
'mobiledoc',
'lexical',
'comment_id',
'feature_image',
'feature_image_alt',
@ -96,6 +97,7 @@ const expectedProperties = {
'title',
'slug',
'mobiledoc',
'lexical',
'comment_id',
'feature_image',
'feature_image_alt',

View File

@ -63,10 +63,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -222,7 +223,7 @@ Object {
"featured": false,
"html": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"published_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"show_title_and_feature_image": true,
"slug": "testing-page-deleted-webhook",
@ -314,11 +315,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -536,11 +537,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -758,11 +759,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -979,11 +980,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -1200,11 +1201,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -1422,11 +1423,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -1688,11 +1689,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -1894,11 +1895,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -2115,11 +2116,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",

View File

@ -66,10 +66,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -224,7 +225,7 @@ Object {
"featured": false,
"html": null,
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"published_at": null,
"slug": "testing-post-deleted-webhook",
"status": "draft",
@ -317,11 +318,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -564,7 +565,7 @@ Header Level 3
* Aliquam tincidunt mauris eu risus.
#header h1 a{display: block;width: 300px;height: 80px;}",
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -784,11 +785,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -1006,11 +1007,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -1228,11 +1229,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -1476,7 +1477,7 @@ Header Level 3
* Aliquam tincidunt mauris eu risus.
#header h1 a{display: block;width: 300px;height: 80px;}",
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -1765,7 +1766,7 @@ Header Level 3
* Aliquam tincidunt mauris eu risus.
#header h1 a{display: block;width: 300px;height: 80px;}",
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -1994,7 +1995,7 @@ Header Level 3
* Aliquam tincidunt mauris eu risus.
#header h1 a{display: block;width: 300px;height: 80px;}",
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",
@ -2213,11 +2214,11 @@ Object {
"id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"meta_description": null,
"meta_title": null,
"mobiledoc": "{\\"version\\":\\"0.3.1\\",\\"ghostVersion\\":\\"4.0\\",\\"markups\\":[],\\"atoms\\":[],\\"cards\\":[],\\"sections\\":[[1,\\"p\\",[[0,[],0,\\"\\"]]]]}",
"mobiledoc": null,
"og_description": null,
"og_image": null,
"og_title": null,
"post_revisions": Array [],
"post_revisions": Any<Array>,
"primary_author": Object {
"accessibility": null,
"bio": "bio",

View File

@ -6,6 +6,7 @@ const {
matchers
} = require('../utils/e2e-framework');
const {
anyArray,
anyGhostAgent,
anyUuid,
anyLocalURL,
@ -57,7 +58,8 @@ const buildPageSnapshotWithTiers = ({
primary_author: buildAuthorSnapshot(roles),
authors: new Array(1).fill(buildAuthorSnapshot(roles)),
primary_tag: tags ? tagSnapshot : null,
tags: tags ? new Array(1).fill(tagSnapshot) : []
tags: tags ? new Array(1).fill(tagSnapshot) : [],
post_revisions: anyArray
};
};

View File

@ -1,6 +1,6 @@
const moment = require('moment-timezone');
const {agentProvider, mockManager, fixtureManager, matchers} = require('../utils/e2e-framework');
const {anyGhostAgent, anyObjectId, anyISODateTime, anyUuid, anyContentVersion, anyNumber, anyLocalURL, anyString} = matchers;
const {anyGhostAgent, anyArray, anyObjectId, anyISODateTime, anyUuid, anyContentVersion, anyNumber, anyLocalURL, anyString} = matchers;
const tierSnapshot = {
id: anyObjectId,
@ -48,7 +48,8 @@ const buildPostSnapshotWithTiers = ({published, tiersCount, roles = true}) => {
url: anyLocalURL,
tiers: new Array(tiersCount).fill(tierSnapshot),
primary_author: buildAuthorSnapshot(roles),
authors: new Array(1).fill(buildAuthorSnapshot(roles))
authors: new Array(1).fill(buildAuthorSnapshot(roles)),
post_revisions: anyArray
};
};
@ -65,7 +66,8 @@ const buildPostSnapshotWithTiersAndTags = ({published, tiersCount, tags, roles =
primary_author: buildAuthorSnapshot(roles),
authors: new Array(1).fill(buildAuthorSnapshot(roles)),
primary_tag: tags ? tagSnapshot : null,
tags: tags ? new Array(1).fill(tagSnapshot) : []
tags: tags ? new Array(1).fill(tagSnapshot) : [],
post_revisions: anyArray
};
};

View File

@ -102,7 +102,7 @@ describe('Importer 1.0', function () {
});
});
it('mobiledoc and html is null', function () {
it('mobiledoc, lexical, and html is null', function () {
const exportData = exportedBodyV1().db[0];
exportData.data.posts[0] = testUtils.DataGenerator.forKnex.createPost({
@ -110,9 +110,10 @@ describe('Importer 1.0', function () {
});
exportData.data.posts[0].mobiledoc = null;
exportData.data.posts[0].lexical = null;
exportData.data.posts[0].html = null;
const options = Object.assign({formats: 'mobiledoc,html'}, testUtils.context.internal);
const options = Object.assign({formats: 'mobiledoc,lexical,html'}, testUtils.context.internal);
return dataImporter.doImport(exportData, importOptions)
.then(function () {
@ -124,7 +125,8 @@ describe('Importer 1.0', function () {
posts.length.should.eql(1);
should(posts[0].html).eql(null);
posts[0].mobiledoc.should.eql('{"version":"0.3.1","ghostVersion":"4.0","markups":[],"atoms":[],"cards":[],"sections":[[1,"p",[[0,[],0,""]]]]}');
should(posts[0].mobiledoc).eql(null);
posts[0].lexical.should.eql('{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}');
});
});

View File

@ -136,7 +136,7 @@ describe('Batch sending tests', function () {
// Prepare a post and email model
const {emailModel} = await sendEmail(agent);
assert.equal(emailModel.get('source_type'), 'mobiledoc');
assert.equal(emailModel.get('source_type'), 'lexical');
assert(emailModel.get('subject'));
assert(emailModel.get('from'));
assert.equal(emailModel.get('email_count'), 4);

View File

@ -30,6 +30,7 @@ const expectedProperties = {
'title',
'slug',
'mobiledoc',
'lexical',
'comment_id',
'feature_image',
'feature_image_alt',

View File

@ -44,18 +44,19 @@ describe('Unit: endpoints/utils/serializers/input/pages', function () {
frame.options.filter.should.eql('(tag:eins)+type:page');
});
it('remove mobiledoc option from formats', function () {
it('remove mobiledoc and lexical option from formats', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
formats: ['html', 'mobiledoc', 'plaintext'],
formats: ['html', 'mobiledoc', 'lexical', 'plaintext'],
context: {}
}
};
serializers.input.pages.browse(apiConfig, frame);
frame.options.formats.should.not.containEql('mobiledoc');
frame.options.formats.should.not.containEql('lexical');
frame.options.formats.should.containEql('html');
frame.options.formats.should.containEql('plaintext');
});
@ -142,7 +143,7 @@ describe('Unit: endpoints/utils/serializers/input/pages', function () {
const frame = {
apiType: 'content',
options: {
formats: ['html', 'mobiledoc', 'plaintext'],
formats: ['html', 'mobiledoc', 'lexical', 'plaintext'],
context: {}
},
data: {
@ -153,6 +154,7 @@ describe('Unit: endpoints/utils/serializers/input/pages', function () {
serializers.input.pages.read(apiConfig, frame);
frame.options.formats.should.not.containEql('mobiledoc');
frame.options.formats.should.not.containEql('lexical');
frame.options.formats.should.containEql('html');
frame.options.formats.should.containEql('plaintext');
});
@ -233,7 +235,7 @@ describe('Unit: endpoints/utils/serializers/input/pages', function () {
serializers.input.pages.copy({}, frame);
frame.options.formats.should.eql('mobiledoc');
frame.options.formats.should.eql('mobiledoc,lexical');
});
it('adds default relations if no relations are specified', function () {

View File

@ -77,18 +77,19 @@ describe('Unit: endpoints/utils/serializers/input/posts', function () {
frame.options.filter.should.eql('(tag:eins)+type:post');
});
it('remove mobiledoc option from formats', function () {
it('remove mobiledoc and lexical options from formats', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
formats: ['html', 'mobiledoc', 'plaintext'],
formats: ['html', 'mobiledoc', 'lexical', 'plaintext'],
context: {}
}
};
serializers.input.posts.browse(apiConfig, frame);
frame.options.formats.should.not.containEql('mobiledoc');
frame.options.formats.should.not.containEql('lexical');
frame.options.formats.should.containEql('html');
frame.options.formats.should.containEql('plaintext');
});
@ -160,12 +161,12 @@ describe('Unit: endpoints/utils/serializers/input/posts', function () {
frame.options.filter.should.eql('(status:draft)+type:post');
});
it('remove mobiledoc option from formats', function () {
it('remove mobiledoc and lexical options from formats', function () {
const apiConfig = {};
const frame = {
apiType: 'content',
options: {
formats: ['html', 'mobiledoc', 'plaintext'],
formats: ['html', 'mobiledoc', 'lexical', 'plaintext'],
context: {}
},
data: {}
@ -173,16 +174,17 @@ describe('Unit: endpoints/utils/serializers/input/posts', function () {
serializers.input.posts.read(apiConfig, frame);
frame.options.formats.should.not.containEql('mobiledoc');
frame.options.formats.should.not.containEql('lexical');
frame.options.formats.should.containEql('html');
frame.options.formats.should.containEql('plaintext');
});
});
describe('edit', function () {
describe('Ensure html to mobiledoc conversion', function () {
describe('Ensure html to lexical conversion', function () {
it('no transformation when no html source option provided', function () {
const apiConfig = {};
const mobiledoc = '{"version":"0.3.1","atoms":[],"cards":[],"sections":[]}';
const lexical = '{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}';
const frame = {
options: {},
data: {
@ -190,7 +192,8 @@ describe('Unit: endpoints/utils/serializers/input/posts', function () {
{
id: 'id1',
html: '<p>convert me</p>',
mobiledoc: mobiledoc
mobiledoc: null,
lexical: lexical
}
]
}
@ -199,12 +202,13 @@ describe('Unit: endpoints/utils/serializers/input/posts', function () {
serializers.input.posts.edit(apiConfig, frame);
let postData = frame.data.posts[0];
postData.mobiledoc.should.equal(mobiledoc);
postData.lexical.should.equal(lexical);
should.equal(null, postData.mobiledoc);
});
it('no transformation when html data is empty', function () {
const apiConfig = {};
const mobiledoc = '{"version":"0.3.1","atoms":[],"cards":[],"sections":[]}';
const lexical = '{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}';
const frame = {
options: {
source: 'html'
@ -214,7 +218,8 @@ describe('Unit: endpoints/utils/serializers/input/posts', function () {
{
id: 'id1',
html: '',
mobiledoc: mobiledoc
mobiledoc: null,
lexical: lexical
}
]
}
@ -223,12 +228,13 @@ describe('Unit: endpoints/utils/serializers/input/posts', function () {
serializers.input.posts.edit(apiConfig, frame);
let postData = frame.data.posts[0];
postData.mobiledoc.should.equal(mobiledoc);
postData.lexical.should.equal(lexical);
should.equal(null, postData.mobiledoc);
});
it('transforms html when html is present in data and source options', function () {
const apiConfig = {};
const mobiledoc = '{"version":"0.3.1","atoms":[],"cards":[],"sections":[]}';
const lexical = '{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}';
const frame = {
options: {
source: 'html'
@ -238,7 +244,7 @@ describe('Unit: endpoints/utils/serializers/input/posts', function () {
{
id: 'id1',
html: '<p>this is great feature</p>',
mobiledoc: mobiledoc
lexical: lexical
}
]
}
@ -247,7 +253,11 @@ describe('Unit: endpoints/utils/serializers/input/posts', function () {
serializers.input.posts.edit(apiConfig, frame);
let postData = frame.data.posts[0];
postData.mobiledoc.should.not.equal(mobiledoc);
postData.lexical.should.not.equal(lexical);
postData.lexical.should.equal('{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"this is great feature","type":"extended-text","version":1}],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}');
// we convert to both mobiledoc and lexical to avoid changing formats
// for existing content when updating with `?source=html,
// the unused data is cleared in the Post model when saving
postData.mobiledoc.should.equal('{"version":"0.3.1","atoms":[],"cards":[],"markups":[],"sections":[[1,"p",[[0,[],0,"this is great feature"]]]]}');
});
@ -270,7 +280,7 @@ describe('Unit: endpoints/utils/serializers/input/posts', function () {
serializers.input.posts.edit(apiConfig, frame);
let postData = frame.data.posts[0];
postData.mobiledoc.should.equal('{"version":"0.3.1","atoms":[],"cards":[["html",{"html":"<div class=\\"custom\\">My Custom HTML</div>"}]],"markups":[],"sections":[[1,"p",[[0,[],0,"this is great feature"]]],[10,0],[1,"p",[[0,[],0,"custom html preserved!"]]]]}');
postData.lexical.should.equal('{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"this is great feature","type":"extended-text","version":1}],"direction":null,"format":"","indent":0,"type":"paragraph","version":1},{"type":"html","version":1,"html":"<div class=\\"custom\\">My Custom HTML</div>"},{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":"custom html preserved!","type":"extended-text","version":1}],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}');
});
});
@ -348,7 +358,7 @@ describe('Unit: endpoints/utils/serializers/input/posts', function () {
serializers.input.posts.copy({}, frame);
frame.options.formats.should.eql('mobiledoc');
frame.options.formats.should.eql('mobiledoc,lexical');
});
it('adds default relations if no relations are specified', function () {

View File

@ -39,7 +39,7 @@ function checkResponseValue(jsonResponse, expectedProperties) {
jsonResponse.should.not.have.property(prop);
});
providedProperties.length.should.eql(expectedProperties.length);
providedProperties.length.should.eql(expectedProperties.length, 'provided properties length does not match expected properties length');
}
// @TODO: support options pattern only, it's annoying to call checkResponse(null, null, null, something)

View File

@ -73,7 +73,7 @@ async function sendEmail(agent, settings, email_recipient_filter) {
assert.ok(emailModel.get('subject'));
assert.ok(emailModel.get('from'));
assert.equal(emailModel.get('source_type'), settings && settings.lexical ? 'lexical' : 'mobiledoc');
assert.equal(emailModel.get('source_type'), settings && settings.mobiledoc ? 'mobiledoc' : 'lexical');
// Await sending job
await completedPromise;
@ -98,7 +98,7 @@ async function sendFailedEmail(agent, settings, email_recipient_filter) {
assert.ok(emailModel.get('subject'));
assert.ok(emailModel.get('from'));
assert.equal(emailModel.get('source_type'), settings && settings.lexical ? 'lexical' : 'mobiledoc');
assert.equal(emailModel.get('source_type'), settings && settings.mobiledoc ? 'mobiledoc' : 'lexical');
// Await sending job
await completedPromise;