Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/helpers/pageflow/themes_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ def themes_options_json_seed(config = Pageflow.config)
config.themes.to_h { |theme| [theme.name, theme.options] }.to_json.html_safe
end

def theme_json_seeds(config)
def theme_json_seeds(config, theme_asset_resolver: SprocketsThemeAssetResolver.new)
render_json_partial('pageflow/themes/theme',
collection: config.themes.to_a,
as: :theme)
as: :theme,
theme_asset_resolver:)
end
end
end
5 changes: 4 additions & 1 deletion app/views/pageflow/editor/entries/seed.json.erb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
"site": <%= render_json_seed(@entry.site) %>,
"widget_types": <%= widget_types_json_seeds(@entry_config) %>,
"page_types": <%= page_type_json_seeds(@entry_config) %>,
"themes": <%= theme_json_seeds(@entry_config) %>,
"themes": <%= theme_json_seeds(
@entry_config,
theme_asset_resolver: @entry.entry_type.theme_asset_resolver
) %>,

"common": <%= render_json { |json| common_entry_seed(json, @entry) }.html_safe %>,

Expand Down
1 change: 0 additions & 1 deletion app/views/pageflow/editor/entries/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<% content_for(:head) do %>
<%= editor_entry_type_fragment(@entry, :head) %>

<%= entry_theme_stylesheet_link_tag(@entry) %>
<%= entry_stylesheet_link_tag(@entry) %>
<% end %>

Expand Down
4 changes: 3 additions & 1 deletion app/views/pageflow/structured_data/_entry.json.jbuilder
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ if meta_data[:publisher].present?
json.name meta_data[:publisher].split(',').map(&:squish)
json.logo do
json.set! '@type', 'ImageObject'
json.url structured_data_normalize_protocol(asset_url(entry.theme.print_logo_path))
json.url structured_data_normalize_protocol(
entry.entry_type.theme_asset_resolver.publisher_logo_url(entry, view_context: self)
)
end
end
end
Expand Down
5 changes: 2 additions & 3 deletions app/views/pageflow/themes/_theme.json.jbuilder
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
json.(theme, :name, :options)

json.preview_image_url(image_url(theme.preview_image_path))
json.preview_thumbnail_url(image_url(theme.preview_thumbnail_path))
json.stylesheet_path(stylesheet_path(theme.stylesheet_path))
json.preview_image_url(theme_asset_resolver.preview_image_url(theme, view_context: self))
json.preview_thumbnail_url(theme_asset_resolver.preview_thumbnail_url(theme, view_context: self))

json.home_button theme.has_home_button?
json.overview_button theme.has_overview_button?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<%= stylesheet_link_tag 'pageflow/application_with_simulated_media_queries', media: 'all' %>
<%= stylesheet_link_tag 'pageflow_paged/editor', media: 'all' %>
<%= entry_theme_stylesheet_link_tag(entry) %>

<%= render 'layouts/pageflow_paged/loading_spinner_inline_script' %>

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
# Pageflow Paged does not use editor JSON seed
theme_stylesheet_paths = Pageflow.config_for(entry).themes.to_h do |theme|
[theme.name, stylesheet_path(theme.stylesheet_path)]
end

json.theme_stylesheet_paths(theme_stylesheet_paths)
3 changes: 2 additions & 1 deletion entry_types/paged/lib/pageflow_paged.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ def entry_type
frontend_app: PageflowPaged::EntriesController.action(:show),
configuration: PageflowPaged::Configuration,
editor_app: PageflowPaged::Engine,
editor_fragment_renderer:)
editor_fragment_renderer:,
theme_asset_resolver: Pageflow::SprocketsThemeAssetResolver.new)
end

private
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ editor.addInitializer(function(options) {
});

state.entry.metadata.on('change:theme_name', function() {
var theme = state.entry.getTheme();
stylesheet.update('theme', theme.get('stylesheet_path'));
stylesheet.update('theme', state.entry.getThemeStylesheetPath());
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {PreviewEntryData} from './PreviewEntryData';

export const PagedEntry = Entry.extend({
setupFromEntryTypeSeed(seed, state){
this.themeStylesheetPaths = seed.theme_stylesheet_paths;

state.entryData = new PreviewEntryData({
entry: this,
storylines: state.storylines,
Expand All @@ -12,6 +14,10 @@ export const PagedEntry = Entry.extend({
});
},

getThemeStylesheetPath: function() {
return this.themeStylesheetPaths[this.metadata.get('theme_name')];
},

supportsPhoneEmulation: function() {
return features.isEnabled('editor_emulation_mode')
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,28 @@ def main_app
Rails.application.class.routes.url_helpers
end

describe 'editor fragments' do
it 'renders the theme stylesheet in the head fragment' do
entry = Pageflow::DraftEntry.find(create(:entry).id)

result = PageflowPaged.entry_type.editor_fragment_renderer.head_fragment(entry)

expect(result).to have_selector('link[data-name="theme"]', visible: false)
end

it 'includes theme stylesheet paths in the seed fragment' do
entry = Pageflow::DraftEntry.find(create(:entry).id)

result = JSON.parse(
PageflowPaged.entry_type.editor_fragment_renderer.seed_fragment(entry)
)

expect(result.dig('theme_stylesheet_paths', 'default')).to(
match(%r{/assets/pageflow/themes/default-[a-f0-9]+\.css})
)
end
end

describe '#partials' do
it 'reponds with success' do
entry = create(:entry)
Expand Down
9 changes: 9 additions & 0 deletions entry_types/scrolled/doc/creating_themes.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ only a subset of icons [required for modern
browsers](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs)
has been included. Webmanifests are generated dynamically.

The following images are used by the editor and for structured data:

* `preview.png`
* `preview_thumbnail.png`
* `logo_print.png`

If one of these files is missing, Pageflow falls back to resolving it
from the legacy Sprockets theme directory.

Register the theme in the theme plugin created by the
`pageflow_scrolled:install` generator:

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions entry_types/scrolled/lib/pageflow_scrolled.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def entry_type
configuration: PageflowScrolled::Configuration,
editor_fragment_renderer:,
editor_app: PageflowScrolled::Engine,
theme_asset_resolver: PageflowScrolled::ThemeAssetResolver.new,
web_app_manifest: PageflowScrolled::WebAppManifest,
theme_files: {
logo_mobile: LOGO_OPTIONS,
Expand Down
33 changes: 33 additions & 0 deletions entry_types/scrolled/lib/pageflow_scrolled/theme_asset_resolver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module PageflowScrolled
# Resolves theme assets from Webpack with a Sprockets fallback for
# backwards compatibility with existing themes.
class ThemeAssetResolver
def initialize(fallback = Pageflow::SprocketsThemeAssetResolver.new)
@fallback = fallback
end

def preview_image_url(theme, view_context:)
webpack_asset_url(theme, 'preview.png', view_context:) ||
@fallback.preview_image_url(theme, view_context:)
end

def preview_thumbnail_url(theme, view_context:)
webpack_asset_url(theme, 'preview_thumbnail.png', view_context:) ||
@fallback.preview_thumbnail_url(theme, view_context:)
end

def publisher_logo_url(entry, view_context:)
webpack_asset_url(entry.theme, 'logo_print.png', view_context:) ||
@fallback.publisher_logo_url(entry, view_context:)
end

private

def webpack_asset_url(theme, path, view_context:)
logical_path = "static/pageflow-scrolled/themes/#{theme.directory_name}/#{path}"
asset_path = view_context.current_shakapacker_instance.manifest.lookup(logical_path)

view_context.url_to_asset(asset_path) if asset_path
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
require 'spec_helper'

module PageflowScrolled
RSpec.describe ThemeAssetResolver do
let(:fallback) { double }
let(:manifest) { double }
let(:shakapacker) { double(manifest:) }
let(:view_context) { double(current_shakapacker_instance: shakapacker) }
let(:theme) { Pageflow::Theme.new(:custom) }

describe '#preview_image_url' do
it 'resolves conventional Webpack asset from manifest' do
expect(manifest).to receive(:lookup)
.with('static/pageflow-scrolled/themes/custom/preview.png')
.and_return('/packs/preview-123.png')
expect(view_context).to receive(:url_to_asset)
.with('/packs/preview-123.png')
.and_return('https://example.com/packs/preview-123.png')
expect(fallback).not_to receive(:preview_image_url)

result = described_class.new(fallback).preview_image_url(theme, view_context:)

expect(result).to eq('https://example.com/packs/preview-123.png')
end

it 'falls back to Sprockets when asset is missing from manifest' do
allow(manifest).to receive(:lookup).and_return(nil)
expect(fallback).to receive(:preview_image_url)
.with(theme, view_context:)
.and_return('https://example.com/assets/preview.png')

result = described_class.new(fallback).preview_image_url(theme, view_context:)

expect(result).to eq('https://example.com/assets/preview.png')
end
end

describe '#preview_thumbnail_url' do
it 'resolves conventional Webpack asset from manifest' do
expect(manifest).to receive(:lookup)
.with('static/pageflow-scrolled/themes/custom/preview_thumbnail.png')
.and_return('/packs/preview_thumbnail-123.png')
expect(view_context).to receive(:url_to_asset)
.with('/packs/preview_thumbnail-123.png')
.and_return('https://example.com/packs/preview_thumbnail-123.png')

result = described_class.new(fallback).preview_thumbnail_url(theme, view_context:)

expect(result).to eq('https://example.com/packs/preview_thumbnail-123.png')
end
end

describe '#publisher_logo_url' do
it 'resolves conventional Webpack asset from manifest' do
entry = double(theme:)
expect(manifest).to receive(:lookup)
.with('static/pageflow-scrolled/themes/custom/logo_print.png')
.and_return('/packs/logo_print-123.png')
expect(view_context).to receive(:url_to_asset)
.with('/packs/logo_print-123.png')
.and_return('https://example.com/packs/logo_print-123.png')

result = described_class.new(fallback).publisher_logo_url(entry, view_context:)

expect(result).to eq('https://example.com/packs/logo_print-123.png')
end
end
end
end
7 changes: 6 additions & 1 deletion lib/pageflow/entry_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module Pageflow
class EntryType
# @api private
attr_reader :name, :frontend_app, :editor_fragment_renderer, :configuration, :editor_app,
:theme_files, :web_app_manifest
:theme_asset_resolver, :theme_files, :web_app_manifest

# @param name [String] A unique name.
#
Expand All @@ -22,6 +22,9 @@ class EntryType
# interface used by editor Backbone collections. Mounted at
# `/editor/entries/:id/<entry_type_name>/`
#
# @param theme_asset_resolver [#preview_image_url, #preview_thumbnail_url,
# #publisher_logo_url] Resolves URLs of theme assets used by core.
#
# @param theme_files [Hash] A hash of the following form defining
# what files can be uploaded when customizing themes of the
# entry type and which Paperclip styles shall be processed:
Expand All @@ -31,12 +34,14 @@ class EntryType
# @param web_app_manifest [#call] Receives published entry and
# returns JSON for webmanifest file.
def initialize(name:, frontend_app:, editor_fragment_renderer:, configuration:, editor_app: nil,
theme_asset_resolver: SprocketsThemeAssetResolver.new,
theme_files: {}, web_app_manifest: nil)
@name = name
@frontend_app = frontend_app
@editor_fragment_renderer = editor_fragment_renderer
@configuration = configuration
@editor_app = editor_app
@theme_asset_resolver = theme_asset_resolver
@theme_files = theme_files
@web_app_manifest = web_app_manifest
end
Expand Down
19 changes: 19 additions & 0 deletions lib/pageflow/sprockets_theme_asset_resolver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Pageflow
# Resolves conventional theme assets from the Sprockets asset pipeline.
#
# Used as the default for backwards compatibility with entry types and
# themes created before entry types could provide their own resolver.
class SprocketsThemeAssetResolver
def preview_image_url(theme, view_context:)
view_context.image_url(theme.preview_image_path)
end

def preview_thumbnail_url(theme, view_context:)
view_context.image_url(theme.preview_thumbnail_path)
end

def publisher_logo_url(entry, view_context:)
view_context.asset_url(entry.theme.print_logo_path)
end
end
end
21 changes: 21 additions & 0 deletions spec/helpers/pageflow/structured_data_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,27 @@ module Pageflow
'thumbnailUrl' => image_file.thumbnail_url(:thumbnail_large))
end

it 'uses entry type theme asset resolver for publisher logo' do
entry = create(:published_entry,
revision_attributes: {publisher: 'Some publisher'})
resolver = double
allow(entry.entry_type).to receive(:theme_asset_resolver).and_return(resolver)
allow(resolver).to receive(:publisher_logo_url)
.with(entry, view_context: anything)
.and_return('https://example.com/publisher.png')

html = helper.structured_data_for_entry(entry)

expect(html).to have_json_ld(
'publisher' => a_hash_including(
'logo' => {
'@type' => 'ImageObject',
'url' => 'https://example.com/publisher.png'
}
)
)
end

it 'skips metadata if not present' do
pageflow_configure do |config|
config.default_keywords_meta_tag = ''
Expand Down
17 changes: 17 additions & 0 deletions spec/helpers/pageflow/themes_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ module Pageflow

expect(result.dig('options', 'some')).to eq('value')
end

it 'uses supplied theme asset resolver' do
Pageflow.config.themes.register(:test_theme)
resolver = double(
preview_image_url: 'https://example.com/preview.png',
preview_thumbnail_url: 'https://example.com/preview_thumbnail.png'
)

result = JSON.parse(
helper.theme_json_seeds(Pageflow.config, theme_asset_resolver: resolver)
).last

expect(result).to include(
'preview_image_url' => 'https://example.com/preview.png',
'preview_thumbnail_url' => 'https://example.com/preview_thumbnail.png'
)
end
end
end
end
Loading
Loading