From 2b90a21b365eb588823a30c8dd264634989b243d Mon Sep 17 00:00:00 2001 From: spamguy Date: Fri, 23 Jan 2026 10:20:59 -0800 Subject: [PATCH] Implementation of CouchDB docs. --- lib/docs/filters/couchdb/clean_html.rb | 30 ++++++++++++++ lib/docs/filters/couchdb/entries.rb | 53 +++++++++++++++++++++++++ lib/docs/scrapers/couchdb.rb | 39 ++++++++++++++++++ public/icons/docs/couchdb/16.png | Bin 0 -> 1476 bytes public/icons/docs/couchdb/16@2x.png | Bin 0 -> 2153 bytes public/icons/docs/couchdb/SOURCE | 1 + 6 files changed, 123 insertions(+) create mode 100644 lib/docs/filters/couchdb/clean_html.rb create mode 100644 lib/docs/filters/couchdb/entries.rb create mode 100644 lib/docs/scrapers/couchdb.rb create mode 100644 public/icons/docs/couchdb/16.png create mode 100644 public/icons/docs/couchdb/16@2x.png create mode 100644 public/icons/docs/couchdb/SOURCE diff --git a/lib/docs/filters/couchdb/clean_html.rb b/lib/docs/filters/couchdb/clean_html.rb new file mode 100644 index 0000000000..0616a2097f --- /dev/null +++ b/lib/docs/filters/couchdb/clean_html.rb @@ -0,0 +1,30 @@ +module Docs + class Couchdb + class CleanHtmlFilter < Filter + def call + css('h1').each do |node| + node.content = node.content.gsub(/\d*\. |\P{ASCII}/, '').split('.').last + end + + css('h2', 'h3').each do |node| + node.content = node.content.gsub(/\P{ASCII}/, '').split('.').last + end + + css('pre').each do |node| + node.content = node.content.strip + + classes = node.parent.parent.classes + if classes.include? 'highlight-bash' + node['data-language'] = 'bash' + else + node['data-language'] = 'javascript' + end + + node.parent.parent.replace(node) + end + + doc + end + end + end +end diff --git a/lib/docs/filters/couchdb/entries.rb b/lib/docs/filters/couchdb/entries.rb new file mode 100644 index 0000000000..3d03a9616e --- /dev/null +++ b/lib/docs/filters/couchdb/entries.rb @@ -0,0 +1,53 @@ +module Docs + class Couchdb + class EntriesFilter < Docs::EntriesFilter + SLUG_MAP = { + 'api' => 'API', + 'json' => 'JSON Structures', + 'cluster' => 'Cluster Management', + 'replication' => 'Replication', + 'maintenance' => 'Maintenance', + 'partitioned' => 'Partitioned Databases' + } + + def get_name + at_css('h1').content.gsub(/\P{ASCII}/, '').split('.').last + end + + def get_type + if slug.start_with?('ddocs/views') + 'Views' + elsif slug.start_with?('ddocs') + 'Design Documents' + else + SLUG_MAP[slug[/^(.+?)[-\/]/, 1]] || name + end + end + + def additional_entries + needs_breakup = [ + 'JSON Structure Reference', + 'Design Documents', + 'Partitioned Databases' + ] + + if needs_breakup.include?(name) + entries = [] + + css('section > section').each do |node| + h2 = node.at_css('h2') + + if h2.present? + name = node.at_css('h2').content.split('.').last + entries << [name, node['id']] + end + end + + entries + else + [] + end + end + end + end +end diff --git a/lib/docs/scrapers/couchdb.rb b/lib/docs/scrapers/couchdb.rb new file mode 100644 index 0000000000..a077e195a1 --- /dev/null +++ b/lib/docs/scrapers/couchdb.rb @@ -0,0 +1,39 @@ +module Docs + class Couchdb < UrlScraper + self.name = 'CouchDB' + self.type = 'couchdb' + self.root_path = 'index.html' + + self.links = { + home: 'https://couchdb.apache.org/', + code: 'https://github.com/apache/couchdb' + } + + html_filters.push 'couchdb/clean_html', 'couchdb/entries' + + options[:container] = 'div[itemprop=articleBody]' + options[:only_patterns] = [ + /api\//, + /cluster\//, + /ddocs\//, + /replication\//, + /maintenance\//, + /partitioned-dbs\//, + /json\-structure*/ + ] + options[:rate_limit] = 50 # Docs are subject to Cloudflare limiters. + options[:attribution] = <<-HTML + Copyright © 2025 The Apache Software Foundation — Licensed under the Apache License 2.0 + HTML + + version '3.5' do + self.release = '3.5.1' + self.base_url = "https://docs.couchdb.org/en/#{self.release}" + end + + def get_latest_version(opts) + doc = fetch_doc('https://couchdb.apache.org/', opts) + doc.at_css('.download-pane > h2').content.split(' ').last + end + end +end diff --git a/public/icons/docs/couchdb/16.png b/public/icons/docs/couchdb/16.png new file mode 100644 index 0000000000000000000000000000000000000000..7cae0c8b513e126c3c666f7a4b78668b857d62ce GIT binary patch literal 1476 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBC{d9b;hE;^%b*2hb1<+l z3NbJPS&Tr)z$nE4G7ZRLuw#^lv)$S=8Cam=en1)oJb)Oa4ni|8U__X*fC;WzU;#6N z4bpb|^nF(##aZAHSl5MQj7C*NCKLdf8il*VCt0c zba4!^5S$w9n=Rrfu=drvxsmo^;ztAxHH0`6E%~Z~!}e5u6gk+JJ;5HfXf?Hcg(n?$gybYC9%Qjo9#|tbA|P`nazKXPr7_zE-`< z_#)Jo9Dqs=u>m$Ftv0 zk9c(OSJmqzN&9rgC+td3#5sh5vNkU+T(f=hmHVgIn)fpBi7aB7o_@SEw^uf4{|WAy z6I2+M>`tv@tE{$(i8~jRwKwgNqEyv|q;uX^okM15GfjA)w=#sCVV~)Lg7GhIsB0)1UGj18YLcRstYEcj-R;jE>19h8I)oH}FJRo`J%e({u@cCu4iKP%gz z6)Wz1Tw@);wOG*LoQdgUp@SPA^Q}%h@K!1P9P^x;k6$tsGcw!NxhOi#{Ft!spmDzI zrPChkdLF#LAad&7!S$xQgO}A-D9C&5k$4*JWu@Owz?)h`y41(xS(Em03$JO7f)t*twxueaZhPP@#xPV$vV zccS!%<8k^u-A?8g!tBr2-g}u*Z!}Z8rexap-vTWMrk{2-ocmw%gxIn_Y=Nzopr0OIBV#Q*>R literal 0 HcmV?d00001 diff --git a/public/icons/docs/couchdb/16@2x.png b/public/icons/docs/couchdb/16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..81dc55b2021ada389a20e69ce6d1d4b9cc9af8c9 GIT binary patch literal 2153 zcmZ`)4LFqP8h$6kVMeXLbFvOKB*ZZ@jn2e0=8zeg82?1%XBZlcnKdIrva;DwQtbNM zWMqyuhEj1Me=B5U6Gi#$P?jxO8tZ3cI^W=w)78G;^?uLu-OqDB_w#=5`(0nEv*V$y z2rUEvU@O&*>{s zrJfhf8D+zcVxaJ7EE=mvLZDD6VpMPl!If;gL5H3!^^Ws+90CRt6BC1uF+;PXLNR+S zEG#fs90rFog)&UJv5~w$zG)5ejm3P9#^5vmgeHru)7I9tE=QCVBY3+qxa^2%SzDz2IO3YZ z|A8O-TPJvZj<6a0l;9M_WI(TEO=0hbz-DYyzN}AzGn3DV@FFu=j7YAmt9|A~%x43i z5^dNK>?k)*U=V`@>8w#UL7!%?$$0;n%%;Ewk%*D)+NNDxKO$==bVf)BBId(+BO$&h zYB7PnxCScO+TBa(jVJB6uZKqCfbMp0oTXS~vbdAt( z7mk~+Vw%8SUiGOO6zhS1)UOl}p?*|U6?swAxv7+C_+}*cSC7Hdy zzS|~^JF#ajPs3-{t(+2M$(cD?t&pWK>wm1}^aK8nu~x5%%Y)=|jUH1}FqWsg|7_Pa zZ3!;TZnRCQ)nJ5nep+l&S3NUAE$-qusMic3y0@QORCx^VEnwkRx4n68qayEq3k=nq zYHwD!`h;!CB&Kgx$)1xzg&Y_G6`2>ZQi^zr4AOFAN)3i*L-j)Y&W*mp>Te zx(fFvwqIwG+(D$mE0jdFHsE-4@!#;5kt@4u6vf67ejA2`)g)ft-h zrH;olx%6RI&#&6){`xyab7xgiUEewuUbq<_Qth1IJN>SR%>S#E&M;>hCG<9#eAo1~ zito8(SK~bfbNa#K%~yx4Uu1K~wl<~gBE_5E4mP_XK(y;pJ+`Nu0_P5Y z8NGlriPR4ziOCCi&wwmb?Sztad;BVPaL(RUOT@{=>*}nk89uU_c+`7D=Y7hPuv>;h zhn!K-_mEzhom3N12Q_gdy=3Tmb;WM*Yl21Pe5sRGvnM&6QJboTJ@ajkR#I=iS$;95 ze;{7pClTKd@0QXNe@PjxsGYi6^5niFrF*xk;-z}qqY-9He#MI6b5a3nuD5Ld*hJp< zRYgVDOzJ|1z5DS=lql5c<@>6o$dnG}&d1%WO{;f^{ziC<{2*;e-A$7kAu!qSUP%BI=jMpykr44;J~pd6(NgjuWo51u`J z%@J{K#r0gE6j3>y)=HFz$U|uv0y&cWNQLp+8}G6B6BAOiNk=dbG<}!MW3I#tY(X#m z;lC>u>s`dF%*S<;lqHj}61U~I^J07fyvJ|l$iGxtpTCzV!P>f$4yy&{