Skip to content
Merged
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
3 changes: 3 additions & 0 deletions app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ def self.development? = ENV['RACK_ENV'] == 'development'
config[:strategy] ||= Html2rss::RequestService.default_strategy_name
end

# Merge global stylesheets into the config
config = LocalConfig.merge_global_stylesheets(config)

feed = Html2rss.feed(config)

HttpCache.expires(response, feed.channel.ttl.to_i * 60, cache_control: 'public')
Expand Down
17 changes: 16 additions & 1 deletion app/local_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,22 @@ class NotFound < RuntimeError; end
# @param name [String, Symbol, #to_sym]
# @return [Hash<Symbol, Any>]
def find(name)
feeds.fetch(name.to_sym) { raise NotFound, "Did not find local feed config at '#{name}'" }
feed_config = feeds.fetch(name.to_sym) { raise NotFound, "Did not find local feed config at '#{name}'" }
merge_global_stylesheets(feed_config)
end

##
# Merges global stylesheets into a feed configuration if the feed doesn't already have stylesheets.
#
# @param config [Hash] The feed configuration to merge stylesheets into
# @return [Hash] The configuration with merged stylesheets (duplicated if needed)
def merge_global_stylesheets(config)
global_config = global
return config unless global_config[:stylesheets] && !config.key?(:stylesheets)

config = config.dup
config[:stylesheets] = global_config[:stylesheets]
config
end

##
Expand Down
136 changes: 136 additions & 0 deletions spec/html2rss/web/app/local_config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,140 @@
describe '.global' do
it { expect(described_class.global).to be_a Hash }
end

describe '.merge_global_stylesheets' do
let(:config_with_stylesheets) do
{
stylesheets: [{ href: '/custom.xsl', type: 'text/xsl' }],
feeds: {
example: {
channel: { url: 'https://example.com' },
selectors: { items: { selector: 'div' } }
}
}
}
end

let(:config_without_stylesheets) do
{
stylesheets: [{ href: '/rss.xsl', type: 'text/xsl' }],
feeds: {
example: {
channel: { url: 'https://example.com' },
selectors: { items: { selector: 'div' } }
}
}
}
end

let(:config_no_global_stylesheets) do
{
feeds: {
example: {
channel: { url: 'https://example.com' },
selectors: { items: { selector: 'div' } }
}
}
}
end

context 'when config has no stylesheets and global has stylesheets' do
before do
allow(described_class).to receive(:global).and_return(config_without_stylesheets)
end

it 'merges global stylesheets into the config' do
config = { channel: { url: 'https://test.com' } }
result = described_class.merge_global_stylesheets(config)

expect(result[:stylesheets]).to eq([{ href: '/rss.xsl', type: 'text/xsl' }])
end

it 'preserves original config data' do
config = { channel: { url: 'https://test.com' } }
result = described_class.merge_global_stylesheets(config)

expect(result[:channel]).to eq({ url: 'https://test.com' })
end

it 'duplicates the config to avoid mutation' do
config = { channel: { url: 'https://test.com' } }
result = described_class.merge_global_stylesheets(config)

expect(result).not_to be(config)
end

it 'creates a new object instance' do
config = { channel: { url: 'https://test.com' } }
result = described_class.merge_global_stylesheets(config)

expect(result.object_id).not_to eq(config.object_id)
end
end

context 'when config already has stylesheets' do
before do
allow(described_class).to receive(:global).and_return(config_without_stylesheets)
end

it 'does not override existing stylesheets' do
config = { stylesheets: [{ href: '/custom.xsl', type: 'text/xsl' }] }
result = described_class.merge_global_stylesheets(config)

expect(result[:stylesheets]).to eq([{ href: '/custom.xsl', type: 'text/xsl' }])
end

it 'returns the original config without duplication' do
config = { stylesheets: [{ href: '/custom.xsl', type: 'text/xsl' }] }
result = described_class.merge_global_stylesheets(config)

expect(result).to be(config)
end
end

context 'when global config has no stylesheets' do
before do
allow(described_class).to receive(:global).and_return(config_no_global_stylesheets)
end

it 'returns the original config unchanged' do
config = { channel: { url: 'https://test.com' } }
result = described_class.merge_global_stylesheets(config)

expect(result).to be(config)
end

it 'does not add stylesheets when none exist globally' do
config = { channel: { url: 'https://test.com' } }
result = described_class.merge_global_stylesheets(config)

expect(result[:stylesheets]).to be_nil
end
end
end

describe '.find with stylesheet merging' do
before do
allow(described_class).to receive_messages(feeds: {
example: {
channel: { url: 'https://example.com' },
selectors: { items: { selector: 'div' } }
}
}, global: {
stylesheets: [{ href: '/rss.xsl', type: 'text/xsl' }]
})
end

it 'merges global stylesheets when finding a feed' do
result = described_class.find('example')

expect(result[:stylesheets]).to eq([{ href: '/rss.xsl', type: 'text/xsl' }])
end

it 'preserves feed configuration when finding a feed' do
result = described_class.find('example')

expect(result[:channel]).to eq({ url: 'https://example.com' })
end
end
end