const _ = require('lodash'); const uuid = require('uuid'); const ObjectId = require('bson-objectid'); const moment = require('moment'); const constants = require('@tryghost/constants'); const DataGenerator = {}; DataGenerator.markdownToMobiledoc = function markdownToMobiledoc(content) { const mobiledoc = { version: '0.3.1', markups: [], atoms: [], cards: [ ['markdown', { markdown: content || '' }] ], sections: [[10, 0]] }; return JSON.stringify(mobiledoc); }; DataGenerator.Content = { posts: [ { id: '618ba1ffbe2896088840a6df', title: 'HTML Ipsum', slug: 'html-ipsum', mobiledoc: DataGenerator.markdownToMobiledoc('

HTML Ipsum Presents

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. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.

Header Level 2

  1. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
  2. Aliquam tincidunt mauris eu risus.

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.

Header Level 3

#header h1 a{display: block;width: 300px;height: 80px;}
'), published_at: new Date('2015-01-01'), custom_excerpt: 'This is my custom excerpt!', feature_image: 'https://example.com/super_photo.jpg' }, { id: '618ba1ffbe2896088840a6e1', title: 'Ghostly Kitchen Sink', slug: 'ghostly-kitchen-sink', mobiledoc: DataGenerator.markdownToMobiledoc('

HTML Ipsum Presents

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. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.

Header Level 2

  1. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
  2. Aliquam tincidunt mauris eu risus.

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.

Header Level 3

#header h1 a{display: block;width: 300px;height: 80px;}
'), published_at: new Date('2015-01-02'), feature_image: '__GHOST_URL__/content/images/2018/hey.jpg' }, { id: '618ba1ffbe2896088840a6e3', title: 'Short and Sweet', slug: 'short-and-sweet', mobiledoc: DataGenerator.markdownToMobiledoc('## testing\n\nmctesters\n\n- test\n- line\n- items'), html: '

testing

\n

mctesters

\n\n', plaintext: 'testing\nmctesters\n\n * test\n * line\n * items', feature_image: 'http://placekitten.com/500/200', published_at: new Date('2015-01-03'), featured: true, uuid: '2ac6b4f6-e1f3-406c-9247-c94a0496d39d' }, { id: '618ba1ffbe2896088840a6e5', title: 'Not finished yet', slug: 'unfinished', mobiledoc: DataGenerator.markdownToMobiledoc('

HTML Ipsum Presents

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. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.

Header Level 2

  1. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
  2. Aliquam tincidunt mauris eu risus.

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.

Header Level 3

#header h1 a{display: block;width: 300px;height: 80px;}
'), status: 'draft', uuid: 'd52c42ae-2755-455c-80ec-70b2ec55c903' }, { id: '618ba1ffbe2896088840a6e7', title: 'Not so short, bit complex', slug: 'not-so-short-bit-complex', mobiledoc: DataGenerator.markdownToMobiledoc('

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.

1234
abcd
efgh
ijkl
Definition list
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.
Lorem ipsum dolor sit amet
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.

'), featured: true }, { id: '618ba1ffbe2896088840a6e9', title: 'This is a static page', slug: 'static-page-test', mobiledoc: DataGenerator.markdownToMobiledoc('

Static page test is what this is for.

Hopefully you don\'t find it a bore.

'), type: 'page' }, { id: '618ba1ffbe2896088840a6eb', title: 'This is a draft static page', slug: 'static-page-draft', mobiledoc: DataGenerator.markdownToMobiledoc('

Static page test is what this is for.

Hopefully you don\'t find it a bore.

'), type: 'page', status: 'draft', uuid: 'd52c42ae-2755-455c-80ec-70b2ec55c904' }, { id: '618ba1ffbe2896088840a6ed', title: 'This is a scheduled post!!', slug: 'scheduled-post', mobiledoc: DataGenerator.markdownToMobiledoc('

Welcome to my invisible post!

'), status: 'scheduled', published_at: moment().add(2, 'days').toDate() } ], tags: [ { id: '618ba1febe2896088840a6db', name: 'kitchen sink', slug: 'kitchen-sink', feature_image: 'https://example.com/super_photo.jpg' }, { id: '9451f5fca366002ebd5dbea6', name: 'bacon', slug: 'bacon' }, { id: '618ba1fdbe2896088840a675', name: 'chorizo', slug: 'chorizo' }, { id: '6193c6d5e792de832cd08148', name: 'pollo', slug: 'pollo' }, { id: '6193c6dfe792de832cd08149', name: 'injection', slug: 'injection' } ], // Password = Sl1m3rson99 users: [ { // owner (owner is still id 1 because of permissions) id: '1', name: 'Joe Bloggs', slug: 'joe-bloggs', email: 'jbloggs@example.com', password: 'Sl1m3rson99', profile_image: 'https://example.com/super_photo.jpg' }, { // admin id: '6193c65ee792de832cd08130', name: 'Smith Wellingsworth', slug: 'smith-wellingsworth', email: 'swellingsworth@example.com', password: 'Sl1m3rson99' }, { // editor id: '6193c672e792de832cd0813c', name: 'Jimothy Bogendath', slug: 'jimothy-bogendath', email: 'jbOgendAth@example.com', password: 'Sl1m3rson99' }, { // author id: '6193c685e792de832cd08141', name: 'Slimer McEctoplasm', slug: 'slimer-mcectoplasm', email: 'smcectoplasm@example.com', password: 'Sl1m3rson99' }, { // editor 2 id: '6193c693e792de832cd08142', name: 'Ivan Email', slug: 'ivan-email', email: 'info1@ghost.org', password: 'Sl1m3rson99' }, { // author 2 id: '6193c6a1e792de832cd08143', name: 'Author2', slug: 'a-2', email: 'info2@ghost.org', password: 'Sl1m3rson99' }, { // admin 2 id: '6193c6abe792de832cd08144', name: 'admin2', slug: 'ad-2', email: 'info3@ghost.org', password: 'Sl1m3rson99' }, { // contributor id: '6193c6bae792de832cd08146', name: 'Contributor', slug: 'contributor', email: 'contributor@ghost.org', password: 'Sl1m3rson99' }, { // contributor id: '6193c6c5e792de832cd08147', name: 'contributor2', slug: 'contrib-2', email: 'contributor2@ghost.org', password: 'Sl1m3rson99' } ], permissions: [ { id: ObjectId().toHexString(), name: 'Browse posts', action_type: 'browse', object_type: 'post' }, { id: ObjectId().toHexString(), name: 'test', action_type: 'edit', object_type: 'post' }, { id: ObjectId().toHexString(), name: 'test', action_type: 'edit', object_type: 'tag' }, { id: ObjectId().toHexString(), name: 'test', action_type: 'edit', object_type: 'user' }, { id: ObjectId().toHexString(), name: 'test', action_type: 'edit', object_type: 'page' }, { id: ObjectId().toHexString(), name: 'test', action_type: 'add', object_type: 'post' }, { id: ObjectId().toHexString(), name: 'test', action_type: 'add', object_type: 'user' }, { id: ObjectId().toHexString(), name: 'test', action_type: 'add', object_type: 'page' }, { id: ObjectId().toHexString(), name: 'test', action_type: 'destroy', object_type: 'post' }, { id: ObjectId().toHexString(), name: 'test', action_type: 'destroy', object_type: 'user' } ], roles: [ { id: ObjectId().toHexString(), name: 'Administrator', description: 'Administrators' }, { id: ObjectId().toHexString(), name: 'Editor', description: 'Editors' }, { id: ObjectId().toHexString(), name: 'Author', description: 'Authors' }, { id: ObjectId().toHexString(), name: 'Owner', description: 'Blog Owner' }, { id: ObjectId().toHexString(), name: 'Contributor', description: 'Contributors' }, { id: ObjectId().toHexString(), name: 'Admin Integration', description: 'External Apps' } ], members: [ { id: ObjectId().toHexString(), email: 'member1@test.com', name: 'Mr Egg', uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b340', status: 'free' }, { id: ObjectId().toHexString(), email: 'member2@test.com', email_open_rate: 50, uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b341', status: 'free' }, { id: ObjectId().toHexString(), email: 'paid@test.com', name: 'Egon Spengler', email_open_rate: 80, uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b342', status: 'paid' }, { id: ObjectId().toHexString(), email: 'trialing@test.com', name: 'Ray Stantz', uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b343', status: 'paid' }, { id: ObjectId().toHexString(), email: 'comped@test.com', name: 'Vinz Clortho', uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b344', status: 'paid' }, { id: ObjectId().toHexString(), email: 'vip@test.com', name: 'Winston Zeddemore', uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b345', status: 'free' }, { id: ObjectId().toHexString(), email: 'vip-paid@test.com', name: 'Peter Venkman', uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b346', status: 'paid', subscribed: false }, { id: ObjectId().toHexString(), email: 'with-product@test.com', name: 'Dana Barrett', uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b347', status: 'paid', subscribed: false } ], newsletters: [ { id: ObjectId().toHexString(), name: 'Daily newsletter', slug: 'daily-newsletter', description: '', sender_name: 'Jamie', sender_email: 'jamie@example.com', sender_reply_to: 'newsletter', status: 'active', subscribe_on_signup: false, title_font_category: 'serif', body_font_category: 'serif', show_header_icon: true, show_header_title: true, show_badge: true, sort_order: 1, header_image: '__GHOST_URL__/content/images/2022/05/test.jpg' }, { id: ObjectId().toHexString(), name: 'Weekly newsletter', slug: 'weekly-newsletter', description: '', sender_name: 'Jamie', sender_email: 'jamie@example.com', sender_reply_to: 'newsletter', status: 'active', subscribe_on_signup: true, title_font_category: 'serif', body_font_category: 'serif', show_header_icon: true, show_header_title: true, show_badge: true, sort_order: 2, header_image: '__GHOST_URL__/content/images/2022/05/test.jpg' }, { id: ObjectId().toHexString(), name: 'Old newsletter', slug: 'old-newsletter', description: '', sender_name: 'Jamie', sender_email: 'jamie@example.com', sender_reply_to: 'newsletter', status: 'archived', subscribe_on_signup: true, title_font_category: 'serif', body_font_category: 'serif', show_header_icon: true, show_header_title: true, show_badge: true, sort_order: 2, header_image: '__GHOST_URL__/content/images/2022/05/test.jpg' } ], products: [ { // No ID because these are in the core fixtures.json slug: 'free', // slug is to match the product, the below are updated for the product welcome_page_url: '/welcome-free' }, { // No ID because these are in the core fixtures.json slug: 'default-product', // slug is to match the product, the below are updated for the product welcome_page_url: '/welcome-paid' } ], labels: [ { id: ObjectId().toHexString(), name: 'Label 1', slug: 'label-1' }, { id: ObjectId().toHexString(), name: 'Label 2', slug: 'label-2' }, { id: ObjectId().toHexString(), name: 'VIP', slug: 'vip' } ], members_stripe_customers: [ { id: ObjectId().toHexString(), member_id: null, // relation added later customer_id: 'cus_HR3tBmNhx4QsZY', name: 'Egon Spengler', email: 'paid@test.com' }, { id: ObjectId().toHexString(), member_id: null, // relation added later customer_id: 'cus_HR3tBmNhx4QsZZ', name: 'Ray Stantz', email: 'trialing@test.com' }, { id: ObjectId().toHexString(), member_id: null, // relation added later customer_id: 'cus_HR3tBmNhx4QsZ0', name: 'Vinz Clortho', email: 'comped@test.com' }, { id: ObjectId().toHexString(), member_id: null, // relation added later customer_id: 'cus_HR3tBmNhx4QsZ1', name: 'Peter Venkman', email: 'vip-paid@test.com' }, { id: ObjectId().toHexString(), member_id: null, // relation added later customer_id: 'cus_HR3tBmNhx4QsZ2', name: 'Dana Barrett', email: 'with-product@test.com' } ], members_paid_subscription_events: [ { id: ObjectId().toHexString(), type: 'created', mrr_delta: 1000, currency: 'usd', source: 'stripe', created_at: null, subscription_id: null, member_id: null, from_plan: null, to_plan: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730bb8' }, { id: ObjectId().toHexString(), type: 'created', mrr_delta: 0, currency: 'usd', source: 'stripe', created_at: null, subscription_id: null, member_id: null, from_plan: null, to_plan: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730bb9' }, { id: ObjectId().toHexString(), type: 'created', mrr_delta: 0, currency: 'usd', source: 'stripe', created_at: null, subscription_id: null, member_id: null, from_plan: null, to_plan: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730ba0' } ], members_stripe_customers_subscriptions: [ { id: ObjectId().toHexString(), customer_id: 'cus_HR3tBmNhx4QsZY', subscription_id: 'sub_HR3tLNgGAHsa7b', plan_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730bb8', stripe_price_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730bb8', status: 'active', cancel_at_period_end: false, current_period_end: '2020-07-09 19:01:20', start_date: '2020-06-09 19:01:20', default_payment_card_last4: '4242', plan_nickname: 'Monthly', plan_interval: 'month', plan_amount: '1000', plan_currency: 'usd', mrr: 1000 }, { id: ObjectId().toHexString(), customer_id: 'cus_HR3tBmNhx4QsZZ', subscription_id: 'sub_HR3tLNgGAHsa7c', plan_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730bb9', stripe_price_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730bb9', status: 'trialing', cancel_at_period_end: true, current_period_end: '2025-07-09 19:01:20', start_date: '2020-06-09 19:01:20', default_payment_card_last4: '4242', plan_nickname: 'Monthly', plan_interval: 'month', plan_amount: '1000', plan_currency: 'usd', mrr: 0 }, { id: ObjectId().toHexString(), customer_id: 'cus_HR3tBmNhx4QsZ0', subscription_id: 'sub_HR3tLNgGAHsa7d', plan_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730ba0', stripe_price_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730ba0', status: 'active', cancel_at_period_end: true, current_period_end: '2025-07-09 19:01:20', start_date: '2020-06-09 19:01:20', default_payment_card_last4: '4242', plan_nickname: 'Complimentary', plan_interval: 'year', plan_amount: '0', plan_currency: 'usd', mrr: 0 } ], stripe_prices: [ { id: ObjectId().toHexString(), stripe_price_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730b12', stripe_product_id: '109c85c734fb9992e7bc30a26af66c22f5c94d8dc62e0a33cb797be902c06b2d', active: true, nickname: 'Monthly', currency: 'USD', amount: 5000, type: 'recurring', interval: 'month' }, { id: ObjectId().toHexString(), stripe_price_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730bb8', stripe_product_id: '109c85c734fb9992e7bc30a26af66c22f5c94d8dc62e0a33cb797be902c06b2d', active: true, nickname: 'Monthly', currency: 'GBP', amount: 1200, type: 'recurring', interval: 'month' }, { id: ObjectId().toHexString(), stripe_price_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730ba0', stripe_product_id: '109c85c734fb9992e7bc30a26af66c22f5c94d8dc62e0a33cb797be902c06b2d', active: true, nickname: 'Yearly', currency: 'GBP', amount: 12000, type: 'recurring', interval: 'year' }, { id: ObjectId().toHexString(), stripe_price_id: '173e16a1fffa7d232b398e4a9b08d266a456ae8f3d23e5f11cc608ced6730bb9', stripe_product_id: '109c85c734fb9992e7bc30a26af66c22f5c94d8dc62e0a33cb797be902c06b2d', active: true, nickname: 'Yearly', currency: 'GBP', amount: 15000, type: 'recurring', interval: 'year' } ], stripe_products: [ { id: ObjectId().toHexString(), product_id: '', stripe_product_id: '109c85c734fb9992e7bc30a26af66c22f5c94d8dc62e0a33cb797be902c06b2d' } ], webhooks: [ { id: ObjectId().toHexString(), event: 'member.added', target_url: 'https://example.com/webhooks/subscriber-added' }, { id: ObjectId().toHexString(), event: 'member.removed', target_url: 'https://example.com/webhooks/subscriber-removed' } ], integrations: [ { id: ObjectId().toHexString(), name: 'Test Integration', slug: 'test-integration' }, { id: ObjectId().toHexString(), name: 'Test Internal Integration', slug: 'test-internal-integration', type: 'internal' } ], api_keys: [ { id: ObjectId().toHexString(), type: 'admin', secret: _.repeat('a', 64) // integration_id: DataGenerator.Content.integrations[0].id }, { id: ObjectId().toHexString(), type: 'content', secret: _.repeat('c', 26) // integration_id: DataGenerator.Content.integrations[0].id }, { id: ObjectId().toHexString(), type: 'admin', integration_id: undefined // "internal" } ], emails: [ { id: ObjectId().toHexString(), uuid: '6b6afda6-4b5e-4893-bff6-f16859e8349a', status: 'submitted', email_count: 2, recipient_filter: 'all', subject: 'You got mailed!', html: '

Look! I\'m an email

', plaintext: 'Waba-daba-dab-da', track_opens: false, submitted_at: moment().toDate() }, { id: ObjectId().toHexString(), uuid: '365daa11-4bf0-4614-ad43-6346387ffa00', status: 'failed', error: 'Everything went south', email_count: 3, subject: 'You got mailed! Again!', html: '

What\'s that? Another email!

', plaintext: 'yes this is an email', track_opens: false, submitted_at: moment().toDate() } ], email_batches: [ { id: ObjectId().toHexString(), email_id: null, // emails[0] relation added later provider_id: 'email1@testing.mailgun.net', status: 'submitted' } ], email_recipients: [ { id: ObjectId().toHexString(), email_id: null, // emails[0] relation added later member_id: null, // members[0] relation added later batch_id: null, // email_batches[0] relation added later processed_at: moment().toDate(), failed_at: null, member_uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b340', member_email: 'member1@test.com', member_name: 'Mr Egg' }, { id: ObjectId().toHexString(), email_id: null, // emails[0] relation added later member_id: null, // members[1] relation added later batch_id: null, // email_batches[0] relation added later processed_at: moment().toDate(), failed_at: null, member_uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b341', member_email: 'member2@test.com', member_name: null }, { id: ObjectId().toHexString(), email_id: null, // emails[0] relation added later member_id: null, // members[2] relation added later batch_id: null, // email_batches[0] relation added later processed_at: moment().toDate(), failed_at: null, member_uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b342', member_email: 'member1@test.com', member_name: 'Mr Egg' }, { id: ObjectId().toHexString(), email_id: null, // emails[0] relation added later member_id: null, // members[3] relation added later batch_id: null, // email_batches[0] relation added later processed_at: moment().toDate(), failed_at: null, member_uuid: 'f6f91461-d7d8-4a3f-aa5d-8e582c40b343', member_email: 'member1@test.com', member_name: 'Mr Egg' } ], snippets: [ { id: ObjectId().toHexString(), name: 'Test snippet 1', mobiledoc: '{}' } ], custom_theme_settings: [ { id: ObjectId().toHexString(), theme: 'casper', key: 'header_typography', type: 'select', value: 'Serif' }, { id: ObjectId().toHexString(), theme: 'casper', key: 'footer_type', type: 'select', value: 'Full' } ] }; // set up belongs_to relationships DataGenerator.Content.api_keys[0].integration_id = DataGenerator.Content.integrations[0].id; DataGenerator.Content.api_keys[1].integration_id = DataGenerator.Content.integrations[0].id; DataGenerator.Content.webhooks[0].integration_id = DataGenerator.Content.integrations[0].id; DataGenerator.Content.webhooks[1].integration_id = DataGenerator.Content.integrations[0].id; DataGenerator.Content.emails[0].post_id = DataGenerator.Content.posts[0].id; DataGenerator.Content.emails[1].post_id = DataGenerator.Content.posts[1].id; DataGenerator.Content.email_batches[0].email_id = DataGenerator.Content.emails[0].id; DataGenerator.Content.email_recipients[0].batch_id = DataGenerator.Content.email_batches[0].id; DataGenerator.Content.email_recipients[0].email_id = DataGenerator.Content.email_batches[0].email_id; DataGenerator.Content.email_recipients[0].member_id = DataGenerator.Content.members[0].id; DataGenerator.Content.email_recipients[1].batch_id = DataGenerator.Content.email_batches[0].id; DataGenerator.Content.email_recipients[1].email_id = DataGenerator.Content.email_batches[0].email_id; DataGenerator.Content.email_recipients[1].member_id = DataGenerator.Content.members[1].id; DataGenerator.Content.email_recipients[2].batch_id = DataGenerator.Content.email_batches[0].id; DataGenerator.Content.email_recipients[2].email_id = DataGenerator.Content.email_batches[0].email_id; DataGenerator.Content.email_recipients[2].member_id = DataGenerator.Content.members[2].id; DataGenerator.Content.email_recipients[3].batch_id = DataGenerator.Content.email_batches[0].id; DataGenerator.Content.email_recipients[3].email_id = DataGenerator.Content.email_batches[0].email_id; DataGenerator.Content.email_recipients[3].member_id = DataGenerator.Content.members[3].id; DataGenerator.Content.members_stripe_customers[0].member_id = DataGenerator.Content.members[2].id; DataGenerator.Content.members_stripe_customers[1].member_id = DataGenerator.Content.members[3].id; DataGenerator.Content.members_stripe_customers[2].member_id = DataGenerator.Content.members[4].id; DataGenerator.Content.members_stripe_customers[3].member_id = DataGenerator.Content.members[6].id; DataGenerator.Content.members_stripe_customers[4].member_id = DataGenerator.Content.members[7].id; DataGenerator.Content.members_paid_subscription_events[0].member_id = DataGenerator.Content.members[2].id; DataGenerator.Content.members_paid_subscription_events[1].member_id = DataGenerator.Content.members[3].id; DataGenerator.Content.members_paid_subscription_events[2].member_id = DataGenerator.Content.members[4].id; DataGenerator.forKnex = (function () { function createBasic(overrides) { const newObj = _.cloneDeep(overrides); return _.defaults(newObj, { id: ObjectId().toHexString(), created_by: DataGenerator.Content.users[0].id, created_at: new Date(), updated_by: DataGenerator.Content.users[0].id, updated_at: new Date() }); } function createTag(overrides) { const newObj = _.cloneDeep(overrides); return _.defaults(newObj, { id: ObjectId().toHexString(), name: 'tag', slug: 'slug', feature_image: null, meta_title: null, meta_description: null, description: 'description', visibility: 'public', created_by: DataGenerator.Content.users[0].id, created_at: new Date(), updated_by: DataGenerator.Content.users[0].id, updated_at: new Date() }); } function createPost(overrides) { overrides = overrides || {}; const newObj = _.cloneDeep(overrides); let mobiledocObj; if (!newObj.mobiledoc) { newObj.mobiledoc = DataGenerator.markdownToMobiledoc('## markdown'); } if (!newObj.html) { mobiledocObj = JSON.parse(newObj.mobiledoc); newObj.html = mobiledocObj.cards && mobiledocObj.cards[0][1].markdown; } return _.defaults(newObj, { id: ObjectId().toHexString(), uuid: uuid.v4(), title: 'title', status: 'published', feature_image: null, featured: false, type: 'post', slug: 'slug', updated_at: new Date(), updated_by: DataGenerator.Content.users[0].id, created_at: new Date(), created_by: DataGenerator.Content.users[0].id, published_at: new Date(), published_by: DataGenerator.Content.users[0].id, visibility: 'public' }); } function createGenericPost(uniqueInteger, status, locale, authors) { status = status || 'draft'; locale = locale || null; return createPost({ id: ObjectId().toHexString(), title: 'Test Post ' + uniqueInteger, slug: 'ghost-from-fiction-to-function-' + uniqueInteger, mobiledoc: DataGenerator.markdownToMobiledoc('Three days ago I released a concept page<\/a> for a lite version of WordPress that I\'ve been thinking about for a long time, called Ghost. I think it\'s fair to say that I didn\'t quite anticipate how strong the reaction would be - and I\'ve hardly had time to catch my breath in the last 72 hours.\n\nThe response was overwhelming, and overwhelmingly positive. In the first 6 hours my site got 35,000 page views after hitting the number 1 slot on Hacker News<\/a>. As of right now, the traffic count is just over 91,000 page views<\/a> - and Ghost has been featured all over the place. Notable mentions so far include Christina Warren from Mashable, who wrote about it<\/a>. Michael Carney from PandoDaily interviewed me about it<\/a>. Someone even wrote about it in Chinese<\/a>. That\'s pretty cool.\n\n\nThe feedback has been amazing, and while it\'s impossible to reply to all of the messages individually, I\'m getting to as many of them as I can and I want to thank each and every one of you who took the time to send me a message or share the concept because you liked it. Now that the initial storm has died down a bit, I wanted to take some time to answer some of the more common questions and talk about what\'s next.\n

FAQ - Continued...<\/h2>\n\nThe most common question, bizarrely:\n

Oh my god, why is that whole page made of images? What\'s wrong with you? \/\/ I can\'t take you seriously \/\/ Don\'t you know anything about the web? \/\/ You are literally Satan re-incarnate.<\/strong><\/em><\/h5>\n\nThis was really the only negativity I got in response to the post, and it surprised me. I put together the concept page as... just that... a concept. It was a way for me to get the ideas out of my head and "down on paper" - or so to speak. I used photoshop as a tool<\/em> to write down my idea with text and images. If I used a sketchbook as a tool <\/em>to create images and handwritten notes, then uploaded scans of it, I doubt anyone would complain. The concept page was never supposed to be a finished product because I had no idea if there would be any interest in it. I had no motivation to waste hours coding a custom layout for something might only ever be read by a few people and then forgotten.\n\nHardware manufacturers make hundreds of foam cutout prototypes of products before they build one with working buttons and screens. I\'m aware of all the usability problems with a web page made of images, and equally, foam cutouts without buttons or screens aren\'t particularly user friendly either. They\'re not supposed to be.\n\nLet\'s move on.\n
What? Why no comments? I need comments.<\/strong><\/em><\/h5>\n\nBecause comments add a layer of complexity that is beyond the core focus of this platform, which is publishing. Again, that\'s not to say you couldn\'t have any comments. This could easily be added with a dedicated plugin where you own the data or (as mentioned) there are third party providers such as Disqus, IntenseDebate, Livefyre and Facebook who all have great platforms. The point of this isn\'t to say "you can\'t have comments" - it\'s to say "comments aren\'t on by default". It\'s about simplicity, more than anything else.\n
Yeah, but WordPress are already going to revise their dashboard, WordPress.com is experimenting with a potential simplified version... so why bother with this?<\/strong><\/em><\/h5>\n\n<\/a>\n\nSorry, but Tumblr already did this - it\'s not the future of blogging, it\'s the past.\n\nGhost isn\'t about sharing "Fuck Yeah [Dogs<\/a>\/Sharks<\/a>\/Girls with Tattoos<\/a>]" - it\'s about publishing - which means writing - rather than mashing a few buttons to make sure that everyone can see and appreciate your latest funny picture\/status, which is surely the most funny picture\/status you\'ve ever posted.\n\nTumblr, Pinterest and Facebook already have this locked down. It\'s not the future.\n
So... are you actually going to build this thing?<\/strong><\/em><\/h5>\n\nThe concept page was a way for me to test demand and interest. To see if anyone actually agreed with my frustrations and, more importantly, my solutions. I plucked a random figure of "10,000 pageviews" out of the air before I hit the publish button. If it got less than 10,000 pageviews, I would surrender to the fact that it would only ever be an idea. I\'ve now exceeded that goal 9 times over, so yes, I\'m looking at how Ghost can now be made into a reality.\n
How can I find out when it\'s done? \/\/ SHUT UP AND TAKE MY MONEY<\/strong><\/em><\/h5>\n\nOk, ok - there\'s a holding page up on http:\/\/TryGhost.org<\/a> - put your email address in.\n
\n

How are you going to do this?<\/h3>\n\nThere\'s three main ways of going about this, each has merits as well as drawbacks.\n\n1.) Build it from scratch<\/strong><\/em> - Many people (particularly the Hacker News crowd) expressed the sentiment that there was little point in forking WordPress. When you\'re going to strip out so much, you get to a point where you might as well start from scratch anyway. Take away the crutches of being stuck with older technologies and put together something which is as sophisticated in code as it is in UI\/UX.\n