diff --git a/assets/javascripts/news.json b/assets/javascripts/news.json index 6679b04f5c..1d049a723d 100644 --- a/assets/javascripts/news.json +++ b/assets/javascripts/news.json @@ -1,4 +1,8 @@ [ + [ + "2025-06-27", + "New documentation: Zsh" + ], [ "2025-06-04", "New documentation: es-toolkit" diff --git a/lib/docs/filters/zsh/clean_html.rb b/lib/docs/filters/zsh/clean_html.rb new file mode 100644 index 0000000000..43d65e045c --- /dev/null +++ b/lib/docs/filters/zsh/clean_html.rb @@ -0,0 +1,20 @@ +module Docs + class Zsh + class CleanHtmlFilter < Filter + def call + css('table.header', 'table.menu', 'hr').remove + + # Remove indices from headers. + css('h1', 'h2', 'h3').each do |node| + node.content = node.content.match(/^[\d\.]* (.*)$/)&.captures&.first + end + + css('h2.section ~ a').each do |node| + node.next_element['id'] = node['name'] + end + + doc + end + end + end +end diff --git a/lib/docs/filters/zsh/entries.rb b/lib/docs/filters/zsh/entries.rb new file mode 100644 index 0000000000..02e7dc9602 --- /dev/null +++ b/lib/docs/filters/zsh/entries.rb @@ -0,0 +1,74 @@ +module Docs + class Zsh + class EntriesFilter < Docs::EntriesFilter + def get_name + extract_header_text(at_css('h1.chapter').content) + end + + def additional_entries + entries = [] + used_fns = [] + + css('h2.section').each do |node| + type = get_type + # Linkable anchor sits above

. + a = node.xpath('preceding-sibling::a').last + header_text = extract_header_text(node.content) + + case type + when 'Zsh Modules' + module_name = header_text.match(/The (zsh\/.* Module)/)&.captures&.first + header_text = module_name if module_name.present? + when 'Calendar Function System' + header_text << ' (Calendar)' + end + + entries << [header_text, a['name'], type] unless header_text.start_with?('Description') + end + + # Functions are documented within
elements. + # Names are wrapped in
, details within
. + #
can also contain anchors for the next function. + doc.css('> dl').each do |node| + type = get_type + fn_names = node.css('> dt') + node.css('dd a[name]').each_with_index do |anchor, i| + if fn_names[i].present? && anchor['name'].present? + fn_names[i]['id'] = anchor['name'] + + # Groups of functions are sometimes comma-delimited. + # Strip arguments, flags, etc. from function name. + # Skip flag-only headers. + fn_names[i].inner_html.split(', ').each do |fn| + fn.gsub!(/<(?:tt|var)>(.+?)<\/(?:tt|var)>/, '\1') + fn = fn.split(' ').first + fn.gsub!(/(?:[\[\(]).*(?:[\]\)]).*$/, '') + + # Add context for operators. + fn << " (#{type})" if fn.length == 1 + + if fn.present? && !fn.match?(/^[\-\[]/) && !used_fns.include?(fn) + used_fns << fn + entries << [fn, anchor['name'], type] + end + end + end + end + end + + entries + end + + def get_type + extract_header_text(at_css('h1.chapter').content) + end + + private + + # Extracts text from a string, dropping indices preceding it. + def extract_header_text(str) + str.match(/^[\d\.]* (.*)$/)&.captures&.first + end + end + end +end diff --git a/lib/docs/scrapers/zsh.rb b/lib/docs/scrapers/zsh.rb new file mode 100644 index 0000000000..b4705960b3 --- /dev/null +++ b/lib/docs/scrapers/zsh.rb @@ -0,0 +1,33 @@ +module Docs + class Zsh < UrlScraper + self.type = 'zsh' + self.release = '5.9.0' + self.base_url = 'https://zsh.sourceforge.io/Doc/Release/' + self.root_path = 'index.html' + self.links = { + home: 'https://zsh.sourceforge.io/', + code: 'https://sourceforge.net/p/zsh/web/ci/master/tree/', + } + + options[:skip] = %w( + zsh_toc.html + zsh_abt.html + The-Z-Shell-Manual.html + Introduction.html + ) + options[:skip_patterns] = [/-Index.html/] + + html_filters.push 'zsh/entries', 'zsh/clean_html' + + options[:attribution] = <<-HTML + The Z Shell is copyright © 1992–2017 Paul Falstad, Richard Coleman, + Zoltán Hidvégi, Andrew Main, Peter Stephenson, Sven Wischnowsky, and others.
+ Licensed under the MIT License. + HTML + + def get_latest_version(opts) + body = fetch('https://zsh.sourceforge.io/Doc/Release', opts) + body.scan(/Zsh version ([0-9.]+)/)[0][0] + end + end +end diff --git a/public/icons/docs/zsh/16.png b/public/icons/docs/zsh/16.png new file mode 100644 index 0000000000..05dc56e07e Binary files /dev/null and b/public/icons/docs/zsh/16.png differ diff --git a/public/icons/docs/zsh/16@2x.png b/public/icons/docs/zsh/16@2x.png new file mode 100644 index 0000000000..014d7ab78a Binary files /dev/null and b/public/icons/docs/zsh/16@2x.png differ diff --git a/public/icons/docs/zsh/SOURCE b/public/icons/docs/zsh/SOURCE new file mode 100644 index 0000000000..70cc4aeed8 --- /dev/null +++ b/public/icons/docs/zsh/SOURCE @@ -0,0 +1,2 @@ +https://sourceforge.net/p/zsh/web/ci/master/tree/favicon.png +