Skip to content

Commit 1cd5019

Browse files
committed
fix: stylesheets not included in feed
1 parent 93a21b5 commit 1cd5019

File tree

3 files changed

+155
-1
lines changed

3 files changed

+155
-1
lines changed

app.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ def self.development? = ENV['RACK_ENV'] == 'development'
100100
config[:strategy] ||= Html2rss::RequestService.default_strategy_name
101101
end
102102

103+
# Merge global stylesheets into the config
104+
config = LocalConfig.merge_global_stylesheets(config)
105+
103106
feed = Html2rss.feed(config)
104107

105108
HttpCache.expires(response, feed.channel.ttl.to_i * 60, cache_control: 'public')

app/local_config.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,22 @@ class NotFound < RuntimeError; end
1919
# @param name [String, Symbol, #to_sym]
2020
# @return [Hash<Symbol, Any>]
2121
def find(name)
22-
feeds.fetch(name.to_sym) { raise NotFound, "Did not find local feed config at '#{name}'" }
22+
feed_config = feeds.fetch(name.to_sym) { raise NotFound, "Did not find local feed config at '#{name}'" }
23+
merge_global_stylesheets(feed_config)
24+
end
25+
26+
##
27+
# Merges global stylesheets into a feed configuration if the feed doesn't already have stylesheets.
28+
#
29+
# @param config [Hash] The feed configuration to merge stylesheets into
30+
# @return [Hash] The configuration with merged stylesheets (duplicated if needed)
31+
def merge_global_stylesheets(config)
32+
global_config = global
33+
return config unless global_config[:stylesheets] && !config.key?(:stylesheets)
34+
35+
config = config.dup
36+
config[:stylesheets] = global_config[:stylesheets]
37+
config
2338
end
2439

2540
##

spec/html2rss/web/app/local_config_spec.rb

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,140 @@
3131
describe '.global' do
3232
it { expect(described_class.global).to be_a Hash }
3333
end
34+
35+
describe '.merge_global_stylesheets' do
36+
let(:config_with_stylesheets) do
37+
{
38+
stylesheets: [{ href: '/custom.xsl', type: 'text/xsl' }],
39+
feeds: {
40+
example: {
41+
channel: { url: 'https://example.com' },
42+
selectors: { items: { selector: 'div' } }
43+
}
44+
}
45+
}
46+
end
47+
48+
let(:config_without_stylesheets) do
49+
{
50+
stylesheets: [{ href: '/rss.xsl', type: 'text/xsl' }],
51+
feeds: {
52+
example: {
53+
channel: { url: 'https://example.com' },
54+
selectors: { items: { selector: 'div' } }
55+
}
56+
}
57+
}
58+
end
59+
60+
let(:config_no_global_stylesheets) do
61+
{
62+
feeds: {
63+
example: {
64+
channel: { url: 'https://example.com' },
65+
selectors: { items: { selector: 'div' } }
66+
}
67+
}
68+
}
69+
end
70+
71+
context 'when config has no stylesheets and global has stylesheets' do
72+
before do
73+
allow(described_class).to receive(:global).and_return(config_without_stylesheets)
74+
end
75+
76+
it 'merges global stylesheets into the config' do
77+
config = { channel: { url: 'https://test.com' } }
78+
result = described_class.merge_global_stylesheets(config)
79+
80+
expect(result[:stylesheets]).to eq([{ href: '/rss.xsl', type: 'text/xsl' }])
81+
end
82+
83+
it 'preserves original config data' do
84+
config = { channel: { url: 'https://test.com' } }
85+
result = described_class.merge_global_stylesheets(config)
86+
87+
expect(result[:channel]).to eq({ url: 'https://test.com' })
88+
end
89+
90+
it 'duplicates the config to avoid mutation' do
91+
config = { channel: { url: 'https://test.com' } }
92+
result = described_class.merge_global_stylesheets(config)
93+
94+
expect(result).not_to be(config)
95+
end
96+
97+
it 'creates a new object instance' do
98+
config = { channel: { url: 'https://test.com' } }
99+
result = described_class.merge_global_stylesheets(config)
100+
101+
expect(result.object_id).not_to eq(config.object_id)
102+
end
103+
end
104+
105+
context 'when config already has stylesheets' do
106+
before do
107+
allow(described_class).to receive(:global).and_return(config_without_stylesheets)
108+
end
109+
110+
it 'does not override existing stylesheets' do
111+
config = { stylesheets: [{ href: '/custom.xsl', type: 'text/xsl' }] }
112+
result = described_class.merge_global_stylesheets(config)
113+
114+
expect(result[:stylesheets]).to eq([{ href: '/custom.xsl', type: 'text/xsl' }])
115+
end
116+
117+
it 'returns the original config without duplication' do
118+
config = { stylesheets: [{ href: '/custom.xsl', type: 'text/xsl' }] }
119+
result = described_class.merge_global_stylesheets(config)
120+
121+
expect(result).to be(config)
122+
end
123+
end
124+
125+
context 'when global config has no stylesheets' do
126+
before do
127+
allow(described_class).to receive(:global).and_return(config_no_global_stylesheets)
128+
end
129+
130+
it 'returns the original config unchanged' do
131+
config = { channel: { url: 'https://test.com' } }
132+
result = described_class.merge_global_stylesheets(config)
133+
134+
expect(result).to be(config)
135+
end
136+
137+
it 'does not add stylesheets when none exist globally' do
138+
config = { channel: { url: 'https://test.com' } }
139+
result = described_class.merge_global_stylesheets(config)
140+
141+
expect(result[:stylesheets]).to be_nil
142+
end
143+
end
144+
end
145+
146+
describe '.find with stylesheet merging' do
147+
before do
148+
allow(described_class).to receive_messages(feeds: {
149+
example: {
150+
channel: { url: 'https://example.com' },
151+
selectors: { items: { selector: 'div' } }
152+
}
153+
}, global: {
154+
stylesheets: [{ href: '/rss.xsl', type: 'text/xsl' }]
155+
})
156+
end
157+
158+
it 'merges global stylesheets when finding a feed' do
159+
result = described_class.find('example')
160+
161+
expect(result[:stylesheets]).to eq([{ href: '/rss.xsl', type: 'text/xsl' }])
162+
end
163+
164+
it 'preserves feed configuration when finding a feed' do
165+
result = described_class.find('example')
166+
167+
expect(result[:channel]).to eq({ url: 'https://example.com' })
168+
end
169+
end
34170
end

0 commit comments

Comments
 (0)