Skip to content

Commit 218e001

Browse files
committed
Add rendered page content support
1 parent 1d3f473 commit 218e001

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed

app/controllers/api_public/v1/pages_controller.rb

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module ApiPublic
22
module V1
33
class PagesController < BaseController
44
include ApiPublic::Cacheable
5+
include UrlLocalizationHelper
56

67
def show
78
unless website_provisioned?
@@ -69,12 +70,39 @@ def available_page_slugs
6970
def page_json(page)
7071
json = page.as_json
7172

72-
# Include page parts if requested
73+
# Include page parts if requested (legacy - metadata only)
7374
json["page_parts"] = build_page_parts(page) if params[:include_parts] == "true"
7475

76+
# Include rendered page contents with pre-rendered HTML
77+
# This is the preferred approach for frontend clients that need to display content
78+
json["page_contents"] = build_rendered_page_contents(page) if params[:include_rendered] == "true"
79+
7580
json
7681
end
7782

83+
# Build rendered page contents with pre-rendered HTML
84+
# This matches how Pwb::PagesController#show_page works
85+
# The HTML is already rendered via Liquid and stored in Content.raw
86+
def build_rendered_page_contents(page)
87+
return [] unless page.respond_to?(:ordered_visible_page_contents)
88+
89+
page.ordered_visible_page_contents.map do |page_content|
90+
raw_html = page_content.is_rails_part ? nil : page_content.content&.raw
91+
# Localize URLs in HTML content based on current locale
92+
localized_html = raw_html.present? ? localize_html_urls(raw_html) : nil
93+
94+
{
95+
page_part_key: page_content.page_part_key,
96+
sort_order: page_content.sort_order,
97+
visible: page_content.visible_on_page,
98+
is_rails_part: page_content.is_rails_part || false,
99+
rendered_html: localized_html,
100+
# Include label for debugging/admin purposes
101+
label: page_content.label
102+
}
103+
end
104+
end
105+
78106
def build_page_parts(page)
79107
return [] unless page.respond_to?(:page_parts)
80108

spec/requests/api_public/v1/pages_spec.rb

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,87 @@
6363
end
6464
end
6565

66+
describe "include_rendered parameter" do
67+
let!(:page_with_content) do
68+
ActsAsTenant.with_tenant(website) do
69+
page = FactoryBot.create(:pwb_page, slug: "home", website: website)
70+
# Create page content with rendered HTML
71+
content = Pwb::Content.create!(
72+
website: website,
73+
page_part_key: "heroes/hero_centered",
74+
raw: "<section class='hero'><h1>Welcome</h1></section>"
75+
)
76+
Pwb::PageContent.create!(
77+
page: page,
78+
website: website,
79+
content: content,
80+
page_part_key: "heroes/hero_centered",
81+
sort_order: 1,
82+
visible_on_page: true,
83+
is_rails_part: false
84+
)
85+
# Create a Rails part (no pre-rendered HTML)
86+
Pwb::PageContent.create!(
87+
page: page,
88+
website: website,
89+
page_part_key: "properties/featured",
90+
sort_order: 2,
91+
visible_on_page: true,
92+
is_rails_part: true
93+
)
94+
page
95+
end
96+
end
97+
98+
it "returns rendered HTML for page contents when include_rendered=true" do
99+
get "/api_public/v1/pages/by_slug/home", params: { include_rendered: "true" }
100+
expect(response).to have_http_status(200)
101+
json = response.parsed_body
102+
103+
expect(json["page_contents"]).to be_an(Array)
104+
expect(json["page_contents"].length).to eq(2)
105+
106+
# First content: Liquid-rendered HTML
107+
hero_content = json["page_contents"].find { |c| c["page_part_key"] == "heroes/hero_centered" }
108+
expect(hero_content["is_rails_part"]).to be false
109+
expect(hero_content["rendered_html"]).to include("<section class='hero'>")
110+
expect(hero_content["rendered_html"]).to include("<h1>Welcome</h1>")
111+
112+
# Second content: Rails part (no HTML)
113+
rails_content = json["page_contents"].find { |c| c["page_part_key"] == "properties/featured" }
114+
expect(rails_content["is_rails_part"]).to be true
115+
expect(rails_content["rendered_html"]).to be_nil
116+
end
117+
118+
it "does not include page_contents when include_rendered is not specified" do
119+
get "/api_public/v1/pages/by_slug/home"
120+
expect(response).to have_http_status(200)
121+
json = response.parsed_body
122+
123+
expect(json["page_contents"]).to be_nil
124+
end
125+
126+
context "with non-default locale" do
127+
it "localizes URLs in rendered HTML" do
128+
# Create content with a link that should be localized
129+
ActsAsTenant.with_tenant(website) do
130+
content = page_with_content.page_contents.first.content
131+
content.update!(raw: '<a href="/search/buy">Search</a>')
132+
end
133+
134+
I18n.with_locale(:es) do
135+
get "/api_public/v1/pages/by_slug/home", params: { include_rendered: "true", locale: "es" }
136+
expect(response).to have_http_status(200)
137+
json = response.parsed_body
138+
139+
hero_content = json["page_contents"].find { |c| c["page_part_key"] == "heroes/hero_centered" }
140+
# URL should be localized to /es/search/buy
141+
expect(hero_content["rendered_html"]).to include('href="/es/search/buy"')
142+
end
143+
end
144+
end
145+
end
146+
66147
describe "website not provisioned errors" do
67148
context "when website has no pages" do
68149
before do

0 commit comments

Comments
 (0)