Browse Source

Merge pull request #2606 from denilsonsa/lit

New docs: Lit (JavaScript library for web components, 20k stars)
Simon Legner 1 month ago
parent
commit
6baddddb4b

+ 1 - 0
assets/stylesheets/application.css.scss

@@ -82,6 +82,7 @@
         'pages/kubernetes',
         'pages/laravel',
         'pages/liquid',
+        'pages/lit',
         'pages/love',
         'pages/lua',
         'pages/gnu_make',

+ 57 - 0
assets/stylesheets/pages/_lit.scss

@@ -0,0 +1,57 @@
+._lit {
+  @extend %simple;
+
+  h4 {
+    @extend %block-label, %label-blue;
+  }
+
+  .view-source {
+    float: right;
+  }
+  .propertyDetails {
+    padding-left: 1.5em;
+  }
+  .heading.property {
+    margin-top: 2em;
+  }
+  .heading.property > h4 {
+    font-weight: 400;
+  }
+  .newKeyword,
+  .readonlyKeyword,
+  .staticKeyword {
+    font-style: italic;
+  }
+  .functionName,
+  .propertyName {
+    font-weight: 700;
+  }
+  aside.litdev-aside {
+    display: flex;
+    border-style: solid;
+    border-width: 1px;
+    padding: 1em 1em 1em 0em;
+    margin: 1em 0;
+    svg {
+      width: 1.5em;
+      margin-inline: 1em;
+    }
+  }
+  litdev-switchable-sample {
+    pre[data-language] {
+      position: relative;
+    }
+    pre[data-language]::before {
+      position: absolute;
+      top: 0;
+      right: 16px;
+      opacity: 0.5;
+    }
+    pre[data-language="js"]::before {
+      content: "JavaScript";
+    }
+    pre[data-language="ts"]::before {
+      content: "TypeScript";
+    }
+  }
+}

+ 84 - 0
lib/docs/filters/lit/clean_html.rb

@@ -0,0 +1,84 @@
+module Docs
+  class Lit
+    class CleanHtmlFilter < Filter
+      def call
+
+        css('.offscreen, #inlineToc, a.anchor, [aria-hidden="true"], #prevAndNextLinks').remove
+
+        css('[tabindex]').remove_attribute('tabindex')
+
+        # Removing the side navigation.
+        css('#docsNavWrapper, #rhsTocWrapper').remove
+
+        # Removing this extra div.
+        div = at_css('#articleWrapper')
+        article = div.at_css('article')
+        article.remove_attribute('id')
+        div.replace(article)
+
+        # Expanding and replacing the <template>, statically.
+        # This code is a hacky incomplete implementation of
+        # https://github.com/lit/lit.dev/blob/main/packages/lit-dev-content/src/components/litdev-aside.ts
+        css('litdev-aside').each do |node|
+          frag = Nokogiri::HTML::DocumentFragment.new(node.document)
+          template = node.at_css('template')
+          aside = template.children.first
+          aside['class'] = 'litdev-aside'
+          frag.add_child(aside)
+          template.remove
+          div = Nokogiri::XML::Node.new('div', @doc)
+          div.add_child(node.children)
+          aside.add_child(div)
+          node.replace(aside)
+        end
+
+        # Removing the live playground examples.
+        # https://github.com/lit/lit.dev/blob/main/packages/lit-dev-content/src/components/litdev-example.ts
+        # Someday we can try enabling the live examples by adding appropriate code to assets/javascripts/views/pages/.
+        css('litdev-example').each do |node|
+          node.remove
+        end
+
+        # Cleaning up the preformatted example code.
+        css('pre:has(code[class])').each do |node|
+          lang = node.at_css('code')['class']
+          lang.sub! /^language-/, ''
+          node.content = node.css('.cm-line').map(&:content).join("\n")
+          node['data-language'] = lang
+        end
+
+        # Cleaning up example import.
+        css('div.import').each do |node|
+          pre = Nokogiri::XML::Node.new('pre', @doc)
+          pre.content = node.css('.cm-line').map(&:content).join("\n")
+          pre['data-language'] = 'javascript'
+          node.replace(pre)
+        end
+
+        # Moving the "kind" to inside the header.
+        # Because it looks better this way.
+        css('.kindTag').each do |kindtag|
+          heading = kindtag.parent
+          next unless heading['class'].include? 'heading'
+          h = heading.at_css('h2, h3, h4')
+          h.prepend_child(kindtag)
+        end
+
+        # View source
+        css('h2 ~ a.viewSourceLink, h3 ~ a.viewSourceLink, h4 ~ a.viewSourceLink').each do |node|
+          node['class'] = 'view-source'
+          node.content = 'Source'
+          node.previous_element << node
+        end
+
+        css('.mdnIcon').each do |node|
+          parent = node.parent
+          node.remove
+          parent.content = parent.content.strip
+        end
+
+        doc
+      end
+    end
+  end
+end

+ 72 - 0
lib/docs/filters/lit/entries.rb

@@ -0,0 +1,72 @@
+module Docs
+  class Lit
+    class EntriesFilter < Docs::EntriesFilter
+
+      def get_name
+        name = at_css('h1').content.strip
+      end
+
+      def get_type
+        # The type/category is section name from the sidebar.
+        active = at_css('#docsNav details li.active')
+        return nil unless active
+        summary = active.ancestors('details').first.at_css('summary')
+        return nil unless summary
+        summary.css('[aria-hidden="true"]').remove
+        summary.content.strip
+      end
+
+      def additional_entries
+        entries = []
+
+        # Code for the API reference pages (and other similar pages).
+        scope_name = ''
+        css('.heading > h2[id], .heading > h3[id], .heading > h4[id]').each do |node|
+          name = node.content.strip
+          id = node['id']
+          # The kindTag has these values:
+          # class, decorator, directive, function, namespace, type, value
+          kind = node.parent.at_css('.kindTag')&.content&.strip
+
+          if kind
+            # Saving the current "scope", i.e. the current class name.
+            # This is useful to prefix the method/property names, which are defined after this element.
+            scope_name = name
+            name = kind + " " + name
+          else
+            # If this is a method/property, it has a different markup.
+            # Let's extract them and add a prefix for disambiguation.
+            function = node.at_css('.functionName')
+            property = node.at_css('.propertyName')
+            if function
+              # Note how "functions" are actually "methods" of some class.
+              # Bare (top-level) functions are extracted when `.kindTag` is "function".
+              name = scope_name + '.' + function.content.strip
+              kind = 'method'
+            elsif property
+              name = scope_name + '.' + property.content.strip
+              kind = 'property'
+            end
+          end
+
+          # If we couldn't figure out the kind, this is a header tag that we can ignore.
+          entries << [name, id, kind] if kind
+        end
+
+        # Code for the Built-in Directives page.
+        # This page has a TOC of the built-in directives, with a clear documentation of each one.
+        # Note that the directives are also indexed in the API reference pages.
+        # Yes, each directive is indexed twice, because each one is documented twice.
+        css('.directory a[href^="#"]').each do |node|
+          name = node.content.strip
+          id = node['href'].sub /^#/, ''
+          # type will be "Built-in directives"
+          type = node.ancestors('article').at_css('h1').content.strip
+          entries << [name, id, type]
+        end
+
+        entries
+      end
+    end
+  end
+end

+ 55 - 0
lib/docs/scrapers/lit.rb

@@ -0,0 +1,55 @@
+module Docs
+  class Lit < UrlScraper
+    self.name = 'Lit'
+    self.slug = 'lit'
+    self.type = 'lit'
+
+    self.links = {
+      home: 'https://lit.dev/',
+      code: 'https://github.com/lit/lit/'
+    }
+
+    options[:container] = 'main'
+
+    options[:max_image_size] = 250_000
+
+    # Note: the copyright will change soon due to https://lit.dev/blog/2025-10-14-openjs/
+    options[:attribution] = <<-HTML
+      &copy; Google LLC<br>
+      Licensed under the Creative Commons Attribution 3.0 Unported License.
+    HTML
+
+    options[:fix_urls] = ->(url) do
+      # A name without any extension is assumed to be a directory.
+      # example.com/foobar -> example.com/foobar/
+      url.sub! /(\/[-a-z0-9]+)([#?]|$)/i, '\1/\2'
+
+      url
+    end
+
+    # The order of the filters is important.
+    # The entries filter is applied to the raw (mostly) unmodified HTML.
+    # The clean_html filter reformats the HTML to the a more appropriate markup for devdocs.
+    html_filters.push 'lit/entries', 'lit/clean_html'
+
+    version '3' do
+      self.release = '3.3.1'
+      self.base_url = 'https://lit.dev/docs/'
+      options[:skip_patterns] = [/v\d+\//]
+    end
+
+    version '2' do
+      self.release = '2.8.0'
+      self.base_url = 'https://lit.dev/docs/v2/'
+    end
+
+    version '1' do
+      self.release = '1.0.1'
+      self.base_url = 'https://lit.dev/docs/v1/'
+    end
+
+    def get_latest_version(opts)
+      get_npm_version('lit', opts)
+    end
+  end
+end

BIN
public/icons/docs/lit/16.png


BIN
public/icons/docs/lit/16@2x.png


+ 3 - 0
public/icons/docs/lit/SOURCE

@@ -0,0 +1,3 @@
+https://github.com/lit/lit.dev/blob/main/packages/lit-dev-content/site/images/flame.svg
+https://github.com/lit/lit.dev/blob/main/packages/lit-dev-content/site/images/icon.svg
+https://github.com/lit/lit/blob/main/packages/lit/logo.svg