Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server Side Rendering of Tailwind #301

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
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
28 changes: 28 additions & 0 deletions app/controllers/staff/pages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def index

def show
@body = params[:preview] || @page.unpublished_body || ""
@include_tailwind = true
render template: 'pages/show', layout: "themes/#{current_website.theme}"
end

Expand Down Expand Up @@ -39,6 +40,8 @@ def update
def preview; end

def publish
save_tailwind_page_content

@page.update(published_body: @page.unpublished_body,
body_published_at: Time.current)
flash[:success] = "#{@page.name} Page was successfully published."
Expand Down Expand Up @@ -67,6 +70,31 @@ def set_page
end
end

def save_tailwind_page_content
@body = @page.unpublished_body
content = render_to_string(template: 'pages/show', layout: "themes/#{current_website.theme}")
command = ["yarn run tailwindcss --minify"]
page_file = Tempfile.new(['page_content', '.html'], 'tmp')
page_file.write(content)
page_file.close
command.push("--content", page_file.path)
if tailwind_config = current_website.tailwind_config
config_file = Tempfile.new(['config_file', '.js'], 'tmp')
config_file.write(tailwind_config)
config_file.close
command.push("--config", config_file.path)
end
output = `#{command.join(' ')}`
css = output.match(/(\/\*! tailwindcss .*)/m)
html = "<style>#{css}</style>"

content = @page.contents.find_or_initialize_by(name: Page::TAILWIND)
content.update!(placement: Website::Content::HEAD, html: html)
ensure
page_file&.unlink
config_file&.unlink
end

def build_page
if template = params[:page] && page_params[:template].presence
Page.from_template(
Expand Down
6 changes: 6 additions & 0 deletions app/helpers/page_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,10 @@ def background_style
def logo_image(args)
resize_image_tag(current_website.logo, **args)
end

def tailwind_content
return false if @include_tailwind

@page&.tailwind_css&.html_safe
end
end
1 change: 1 addition & 0 deletions app/javascript/packs/default_theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "controllers"
71 changes: 35 additions & 36 deletions app/javascript/packs/tailwind.js

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions app/models/page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ class Page < ApplicationRecord
'home' => { },
}

TAILWIND = 'tailwind'.freeze

belongs_to :website
after_save_commit :purge_website_cache

has_many :contents, class_name: 'Website::Content', as: :contentable, dependent: :destroy

scope :published, -> { where.not(published_body: nil).where(hide_page: false) }
scope :in_footer, -> { published.where.not(footer_category: [nil, ""]) }

Expand Down Expand Up @@ -39,6 +43,10 @@ def unpublished_changes?
published_body != unpublished_body
end

def tailwind_css
contents.where(name: TAILWIND).pluck(:html).first
end

private

def purge_website_cache
Expand Down
12 changes: 11 additions & 1 deletion app/models/website.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Website < ApplicationRecord
belongs_to :event
has_many :pages, dependent: :destroy
has_many :fonts, class_name: 'Website::Font', dependent: :destroy
has_many :contents, class_name: 'Website::Content', dependent: :destroy
has_many :contents, class_name: 'Website::Content', as: :contentable, dependent: :destroy
has_one :meta_data, class_name: 'Website::MetaData', dependent: :destroy

has_many :session_formats, through: :event
Expand All @@ -29,6 +29,16 @@ def self.domain_match(domain)
where(arel_table[:domains].matches("%#{domain}%"))
end

def tailwind_config
config = contents
.where(Content.arel_table[:html]
.matches("%tailwind.config%"))
.first
if config
config.html.gsub(%r{<script>|</script>}, "").gsub("tailwind.config", "module.exports")
end
end

def manual_purge
purge_cache { save }
end
Expand Down
3 changes: 2 additions & 1 deletion app/models/website/content.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ class Website::Content < ApplicationRecord
FOOTER = "footer",
].freeze

belongs_to :website
belongs_to :contentable, polymorphic: true

scope :for, -> (placement) { where(placement: placement) }
scope :for_page, -> (slug) { where(name: slug) }
end

# == Schema Information
Expand Down
6 changes: 3 additions & 3 deletions app/views/layouts/themes/default.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
%meta{property: "twitter:image", content: current_website.meta_image_url}

= stylesheet_link_tag current_website.theme, media: 'all'
= javascript_pack_tag "application"
= javascript_pack_tag "default_theme"
:css
#{current_website.font_faces_css}
#{current_website.font_root_css}
= javascript_pack_tag "tailwind"
= tailwind_content || javascript_pack_tag("tailwind")
= current_website.head_content

%body
Expand Down Expand Up @@ -58,4 +58,4 @@
})
= current_website.footer_content

= yield :javascript
= yield :javascript
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class ConvertWebsiteContentsToPolymorphic < ActiveRecord::Migration[6.1]
def change
change_table :website_contents, bulk: true do |t|
t.rename :website_id, :contentable_id
t.string :contentable_type, default: 'Website', null: false
t.index [:contentable_id, :contentable_type]
t.remove_index :contentable_id
end
end
end
7 changes: 4 additions & 3 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2022_05_23_185412) do
ActiveRecord::Schema.define(version: 2022_06_09_140626) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -344,10 +344,11 @@
t.text "html"
t.string "placement", default: "head", null: false
t.string "name"
t.bigint "website_id"
t.bigint "contentable_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["website_id"], name: "index_website_contents_on_website_id"
t.string "contentable_type", default: "Website", null: false
t.index ["contentable_id", "contentable_type"], name: "index_website_contents_on_contentable_id_and_contentable_type"
end

create_table "website_fonts", force: :cascade do |t|
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"react-dom": "^16.8.6",
"react_ujs": "^2.5.0",
"regenerator-runtime": "^0.13.7",
"stimulus": "^3.0.1"
"stimulus": "^3.0.1",
"tailwindcss": "3.1.4"
},
"devDependencies": {
"webpack-dev-server": "^3.3.1"
Expand Down
6 changes: 2 additions & 4 deletions spec/features/website/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
website = create(:website, event: event)
home_page = create(:page, website: website)

login_as(organizer)
signin_as(organizer)
visit edit_event_staff_website_path(event)
click_on("Add Content")
fill_in_codemirror(<<~HTML
Expand Down Expand Up @@ -111,7 +111,7 @@
visit page_path(event, home_page)
expect(response_headers["Cache-Control"]).to eq("max-age=0, private, s-maxage=0")

login_as(organizer)
signin_as(organizer)
visit edit_event_staff_website_path(event)

select("automatic", from: "Caching")
Expand All @@ -126,7 +126,6 @@
expect(response_headers["Last-Modified"]).to eq(last_modified)

RSpec::Mocks.space.proxy_for(fastly_service).reset
sleep 1
visit event_staff_pages_path(event)
click_on("Publish")
expect(fastly_service).to have_received(:purge_by_key).with(event.slug)
Expand All @@ -145,7 +144,6 @@
last_modified = response_headers["Last-Modified"]

RSpec::Mocks.space.proxy_for(fastly_service).reset
sleep 1
visit event_staff_pages_path(event)
click_on("Publish")
expect(fastly_service).not_to have_received(:purge_by_key).with(event.slug)
Expand Down
4 changes: 2 additions & 2 deletions spec/features/website/page_management_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@

scenario "Organizer publishes a website page", :js do
home_page = create(:page, unpublished_body: 'Home Content', published_body: nil)
login_as(organizer)
signin_as(organizer)

visit page_path(slug: event.slug, page: home_page.slug)
expect(page).to have_content("Page Not Found")
Expand Down Expand Up @@ -91,7 +91,7 @@
end

scenario "Organizer creates and publishes a splash page from a template", :js do
login_as(organizer)
signin_as(organizer)
visit new_event_staff_page_path(event)
select("splash", from: "template")

Expand Down
1 change: 1 addition & 0 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,4 @@ def save_timestamped_screenshot(page)

page.save_screenshot(screenshot_path)
end
Capybara.default_max_wait_time = 3.seconds
3 changes: 3 additions & 0 deletions spec/support/helpers/session_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ def forgot_password(email)
click_button 'Send me reset password instructions'
end

def signin_as(user)
signin(user.email, user.password)
end
end
end
Loading