From c05928e89f303a34ce22897119532551226a2815 Mon Sep 17 00:00:00 2001 From: spamguy Date: Fri, 27 Jun 2025 12:01:51 -0700 Subject: [PATCH] Add Tailwind CSS v4 and revise v3 --- lib/docs/filters/tailwindcss/clean_html.rb | 73 +++++++++++++++------- lib/docs/filters/tailwindcss/entries.rb | 25 ++++++-- lib/docs/scrapers/tailwindcss.rb | 67 +++++++++++++------- 3 files changed, 114 insertions(+), 51 deletions(-) diff --git a/lib/docs/filters/tailwindcss/clean_html.rb b/lib/docs/filters/tailwindcss/clean_html.rb index 9815cf090a..bdab80b912 100644 --- a/lib/docs/filters/tailwindcss/clean_html.rb +++ b/lib/docs/filters/tailwindcss/clean_html.rb @@ -2,26 +2,38 @@ module Docs class Tailwindcss class CleanHtmlFilter < Filter def call + # Move h1 out of wrapper. + css('h1').each do |node| + doc.prepend_child(node) + end + # Remove main page headers (top level sticky) - css('#__next > .sticky').remove + css('#__next > .sticky', 'div.fixed.inset-x-0.top-0').remove # And anything absolutely positioned (fancy floating navigation elements we don't care about) - css('#__next .absolute').remove + css('#__next .absolute', '.fixed').remove # Remove the left-navigation we scraped css('nav').remove css('svg').remove if root_page? - # Remove the duplicate category name at the top of the page - redundant - at_css('header#header > div:first-child > p:first-child').remove - # Remove the right navigation sidebar - at_css('header#header').parent.css('> div:has(h5:contains("On this page"))').remove + css('header#header', 'p[data-section]').each do |node| + node.parent.css('> div:has(h5:contains("On this page"))').remove # v3 + + node.parent.parent.css('div.max-xl\\:hidden').remove # v4 + end + + # Remove the duplicate category name at the top of the page - redundant + css( + 'header#header > div:first-child > p:first-child', # v3 + 'p[data-section]' # v4 + ).remove # Remove footer + prev/next navigation - at_css('footer').remove + css('footer', '.row-start-5').remove # Handle long lists of class reference that otherwise span several scrolled pages - if class_reference = at_css('#class-reference') + if class_reference = at_css('#class-reference', '#quick-reference') reference_container = class_reference.parent classes_container = reference_container.children.reject{ |child| child == class_reference }.first @@ -33,7 +45,7 @@ def call end # Remove border color preview column as it isn't displayed anyway - if result[:path] == "border-color" and class_reference = at_css('#class-reference') + if result[:path] == "border-color" and class_reference = at_css('#class-reference', '#quick-reference') class_reference.parent.css("thead th:nth-child(3)").remove class_reference.parent.css("tbody td:nth-child(3)").remove end @@ -59,29 +71,48 @@ def call end # Remove buttons to expand lists - those are already expanded and the button is useless - css('div > button:contains("Show all classes")').each do |node| + css( + 'div > button:contains("Show all classes")', + 'div > button:contains("Show more")' + ).each do |node| node.parent.remove end # Remove class examples - not part of devdocs styleguide? (similar to bootstrap) # Refer to https://github.com/freeCodeCamp/devdocs/pull/1534#pullrequestreview-649818936 - css('.not-prose').each do |node| - if node.parent.children.length == 1 - node.parent.remove - else - node.remove - end - end + css('.mt-4.-mb-3', 'figure', 'svg', '.flex.space-x-2').remove - # Properly format code examples + # Properly format code examples. css('pre > code:first-child').each do |node| - node.parent['data-language'] = node['class'][/language-(\w+)/, 1] if node['class'] and node['class'][/language-(\w+)/] - node.parent.content = node.parent.content + # v4 doesn't provide language context, so it must be inferred imperfectly. + node.parent['data-language'] = + if node.content.include?('function') + 'jsx' + elsif node.content.include?(" (https://github.com/damms005/devdocs/commit/8c9fbd859b71a2525b94a35ea994393ce2b6fedb#commitcomment-50091018) + # Remove weird
(https://github.com/damms005/devdocs/commit/8c9fbd859b71a2525b94a35ea994393ce2b6fedb#commitcomment-50091018) css('hr').remove doc diff --git a/lib/docs/filters/tailwindcss/entries.rb b/lib/docs/filters/tailwindcss/entries.rb index ad0bf7b441..5e95d5a3fb 100644 --- a/lib/docs/filters/tailwindcss/entries.rb +++ b/lib/docs/filters/tailwindcss/entries.rb @@ -3,22 +3,35 @@ class Tailwindcss class EntriesFilter < Docs::EntriesFilter def get_type # We are only interested in children list items - selector = "nav li li a[href='#{result[:path]}']" + - anchor = at_css(selector) - category_list = anchor.ancestors('li')[1] - title = category_list.css('h5') + anchor = at_css(get_selector) + title = + if version == '3' + anchor.ancestors('li')[1].css('h5') + else + anchor.ancestors('ul').last.previous_element + end return title.inner_text end def get_name # We are only interested in children list items - selector = "nav li li a[href='#{result[:path]}']" - item = at_css(selector) + item = at_css(get_selector) return item.inner_text end + + private + + def get_selector + if version == '3' + "nav li li a[href='#{result[:path]}']" + else + "nav li a[href*='#{result[:path]}']" + end + end end end end diff --git a/lib/docs/scrapers/tailwindcss.rb b/lib/docs/scrapers/tailwindcss.rb index 71b84d5f3b..fdf045994c 100644 --- a/lib/docs/scrapers/tailwindcss.rb +++ b/lib/docs/scrapers/tailwindcss.rb @@ -3,9 +3,7 @@ class Tailwindcss < UrlScraper self.name = 'Tailwind CSS' self.type = 'tailwindcss' self.slug = 'tailwindcss' - self.base_url = 'https://tailwindcss.com/docs' self.root_path = '/' - self.release = '3.3.2' self.links = { home: 'https://tailwindcss.com/', code: 'https://github.com/tailwindlabs/tailwindcss' @@ -16,27 +14,6 @@ class Tailwindcss < UrlScraper # Disable the clean text filter which removes empty nodes - we'll do it ourselves more selectively text_filters.replace("clean_text", "tailwindcss/noop") - # Fix redirects from older tailwind 2 docs - options[:fix_urls] = lambda do |url| - if url.include? "installation/" - break "/docs/installation" - end - - if url.end_with? "/breakpoints" - break "/docs/screens#{/#.*$/.match(url)}" - end - if url.end_with? "/adding-base-styles" - break "/docs/adding-custom-styles#adding-base-styles" - end - if url.end_with? "/ring-opacity" - break "/docs/ring-color#changing-the-opacity" - end - - if url.match(/\/colors#?/) - break "/docs/customizing-colors#{/#.*$/.match(url)}" - end - end - options[:skip_patterns] = [ # Skip setup instructions /\/browser-support$/, @@ -49,9 +26,51 @@ class Tailwindcss < UrlScraper #Obtainable from https://github.com/tailwindlabs/tailwindcss/blob/master/LICENSE options[:attribution] = <<-HTML - © 2022 Tailwind Labs Inc. + © Tailwind Labs Inc. HTML + version do + self.release = '4.1.11' + self.base_url = 'https://tailwindcss.com/docs' + + # Fix redirects + options[:fix_urls] = lambda do |url| + if url.include? "installation/" + break "/docs/installation" + end + + if url.end_with? "text-color" + break "/docs/color" + end + end + end + + version '3' do + self.release = '3.4.17' + self.base_url = 'https://v3.tailwindcss.com/docs' + + # Fix redirects from older tailwind 2 docs + options[:fix_urls] = lambda do |url| + if url.include? "installation/" + break "/docs/installation" + end + + if url.end_with? "/breakpoints" + break "/docs/screens#{/#.*$/.match(url)}" + end + if url.end_with? "/adding-base-styles" + break "/docs/adding-custom-styles#adding-base-styles" + end + if url.end_with? "/ring-opacity" + break "/docs/ring-color#changing-the-opacity" + end + + if url.match(/\/colors#?/) + break "/docs/customizing-colors#{/#.*$/.match(url)}" + end + end + end + def get_latest_version(opts) get_latest_github_release('tailwindlabs', 'tailwindcss', opts) end