From ea20f6208a39d8af93465cafac1238ee3e6fe6f6 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 11:41:32 -0400 Subject: [PATCH 001/244] Update Padrino documentation (0.14.1) --- lib/docs/scrapers/padrino.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/padrino.rb b/lib/docs/scrapers/padrino.rb index def8160e..218f1731 100644 --- a/lib/docs/scrapers/padrino.rb +++ b/lib/docs/scrapers/padrino.rb @@ -2,7 +2,7 @@ module Docs class Padrino < UrlScraper self.slug = 'padrino' self.type = 'rubydoc' - self.release = '0.13.2' + self.release = '0.14.1' self.base_url = 'http://www.rubydoc.info/github/padrino/padrino-framework/' self.root_path = 'file/README.rdoc' self.initial_paths = %w(index2) From 485b9b903b4a929c97de37ec4b80f3f61f61f0df Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 11:43:24 -0400 Subject: [PATCH 002/244] Update Angular documentation (4.4.6) --- lib/docs/scrapers/angular.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/angular.rb b/lib/docs/scrapers/angular.rb index 988616b5..8ff7c728 100644 --- a/lib/docs/scrapers/angular.rb +++ b/lib/docs/scrapers/angular.rb @@ -16,7 +16,7 @@ module Docs HTML version do - self.release = '4.4.4' + self.release = '4.4.6' self.base_url = 'https://angular.io/' self.root_path = 'docs' From c6f90f61df575128282c5d546b581596519d65c3 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 11:44:44 -0400 Subject: [PATCH 003/244] Update Angular.js documentation (1.6.6) --- lib/docs/scrapers/angularjs.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/angularjs.rb b/lib/docs/scrapers/angularjs.rb index f103005a..b8ff08b9 100644 --- a/lib/docs/scrapers/angularjs.rb +++ b/lib/docs/scrapers/angularjs.rb @@ -46,7 +46,7 @@ module Docs end version '1.6' do - self.release = '1.6.5' + self.release = '1.6.6' self.base_url = "https://code.angularjs.org/#{release}/docs/partials/" end From 96349083dc85c8f60e3c439817c2a981ddbb6864 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 11:46:31 -0400 Subject: [PATCH 004/244] Update Apache HTTP Server documentation (2.4.29) --- lib/docs/scrapers/apache.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/apache.rb b/lib/docs/scrapers/apache.rb index b3e69b4f..23ac7a5a 100644 --- a/lib/docs/scrapers/apache.rb +++ b/lib/docs/scrapers/apache.rb @@ -3,7 +3,7 @@ module Docs self.name = 'Apache HTTP Server' self.slug = 'apache_http_server' self.type = 'apache' - self.release = '2.4.27' + self.release = '2.4.29' self.base_url = 'https://httpd.apache.org/docs/2.4/en/' self.links = { home: 'https://httpd.apache.org/' From 2f752f9ff4b27a35e16a92c60135bc4103a89bfe Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 11:48:07 -0400 Subject: [PATCH 005/244] Update Bootstrap documentation (4.0.0-beta.2) --- lib/docs/scrapers/bootstrap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/bootstrap.rb b/lib/docs/scrapers/bootstrap.rb index f462e220..7858e40e 100644 --- a/lib/docs/scrapers/bootstrap.rb +++ b/lib/docs/scrapers/bootstrap.rb @@ -16,7 +16,7 @@ module Docs HTML version '4' do - self.release = '4.0.0-beta' + self.release = '4.0.0-beta.2' self.base_url = 'https://getbootstrap.com/docs/4.0/' self.root_path = 'getting-started/introduction/' From e66219a853e97b19e8897e9b4c9274dae091042b Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 13:58:09 -0400 Subject: [PATCH 006/244] Update CoffeeScript documentation (2.0.2) --- lib/docs/scrapers/coffeescript.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/coffeescript.rb b/lib/docs/scrapers/coffeescript.rb index ff87a534..0b75ae34 100644 --- a/lib/docs/scrapers/coffeescript.rb +++ b/lib/docs/scrapers/coffeescript.rb @@ -16,7 +16,7 @@ module Docs HTML version '2' do - self.release = '2.0.1' + self.release = '2.0.2' self.base_url = 'http://coffeescript.org/' html_filters.push 'coffeescript/entries', 'coffeescript/clean_html', 'title' From a158d0d1a03300e3f17a33bccca4d70d674ade3d Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:00:00 -0400 Subject: [PATCH 007/244] Update Cordova documentation (7.1.0) --- lib/docs/scrapers/cordova.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/cordova.rb b/lib/docs/scrapers/cordova.rb index 4852bec1..a8ff86e9 100644 --- a/lib/docs/scrapers/cordova.rb +++ b/lib/docs/scrapers/cordova.rb @@ -29,7 +29,7 @@ module Docs HTML version '7' do - self.release = '7.0.1' + self.release = '7.1.0' self.base_url = 'https://cordova.apache.org/docs/en/7.x/' end From 3ac5406da284e4e2626a38a5f3c3d6e4ed84481d Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:03:06 -0400 Subject: [PATCH 008/244] Update Electron documentation (1.7.9) --- lib/docs/scrapers/electron.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/electron.rb b/lib/docs/scrapers/electron.rb index 7e16ef58..96f0b9b2 100644 --- a/lib/docs/scrapers/electron.rb +++ b/lib/docs/scrapers/electron.rb @@ -2,7 +2,7 @@ module Docs class Electron < UrlScraper self.type = 'electron' self.base_url = 'https://electron.atom.io/docs/' - self.release = '1.7.5' + self.release = '1.7.9' self.links = { home: 'https://electron.atom.io/', code: 'https://github.com/electron/electron' From 4ecd36a3e54085f51839bb76c6dd5db5b5939af1 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:07:04 -0400 Subject: [PATCH 009/244] Update Flow documentation (0.57.3) --- lib/docs/scrapers/flow.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/flow.rb b/lib/docs/scrapers/flow.rb index 05d0fb6f..53ee0406 100644 --- a/lib/docs/scrapers/flow.rb +++ b/lib/docs/scrapers/flow.rb @@ -1,7 +1,7 @@ module Docs class Flow < UrlScraper self.type = 'flow' - self.release = '0.56.0' + self.release = '0.57.3' self.base_url = 'https://flow.org/en/docs/' self.links = { home: 'https://flow.org/', From 56115de7daabf1d8d9969960bc7eba252426d4fc Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:08:48 -0400 Subject: [PATCH 010/244] Update Go documentation (1.9.2) --- lib/docs/scrapers/go.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/go.rb b/lib/docs/scrapers/go.rb index 5414e943..b7eca540 100644 --- a/lib/docs/scrapers/go.rb +++ b/lib/docs/scrapers/go.rb @@ -1,7 +1,7 @@ module Docs class Go < UrlScraper self.type = 'go' - self.release = '1.9.0' + self.release = '1.9.2' self.base_url = 'https://golang.org/pkg/' self.links = { home: 'https://golang.org/', From 2547efffd9d9f36d28261cc0c7976e159f725598 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:10:28 -0400 Subject: [PATCH 011/244] Update Git documentation (2.14.3) --- lib/docs/scrapers/git.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/git.rb b/lib/docs/scrapers/git.rb index 63889608..223b48c2 100644 --- a/lib/docs/scrapers/git.rb +++ b/lib/docs/scrapers/git.rb @@ -1,7 +1,7 @@ module Docs class Git < UrlScraper self.type = 'git' - self.release = '2.14.1' + self.release = '2.14.3' self.base_url = 'https://git-scm.com/docs' self.initial_paths = %w(/git.html) self.links = { From a92e01c731483313a2cb2076e93974970a78555e Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:11:09 -0400 Subject: [PATCH 012/244] Update Jasmine documentation (2.8.0) --- lib/docs/scrapers/jasmine.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/jasmine.rb b/lib/docs/scrapers/jasmine.rb index 9b55eb93..bcffb684 100644 --- a/lib/docs/scrapers/jasmine.rb +++ b/lib/docs/scrapers/jasmine.rb @@ -2,7 +2,7 @@ module Docs class Jasmine < UrlScraper self.type = 'jasmine' self.release = '2.8.0' - self.base_url = 'https://jasmine.github.io/api/2.7/' + self.base_url = 'https://jasmine.github.io/api/2.8/' self.root_path = 'index.html' self.links = { home: 'https://jasmine.github.io/', From 60e4cbf99cab59694c003ecc8cbe11048cb6d4fa Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:18:40 -0400 Subject: [PATCH 013/244] Update Matplotlib documentation (2.1.0) --- lib/docs/scrapers/matplotlib.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/docs/scrapers/matplotlib.rb b/lib/docs/scrapers/matplotlib.rb index 20adbe86..0e50a7f7 100644 --- a/lib/docs/scrapers/matplotlib.rb +++ b/lib/docs/scrapers/matplotlib.rb @@ -20,6 +20,15 @@ module Docs Licensed under the Matplotlib License Agreement. HTML + version '2.1' do + self.release = '2.1.0' + self.base_urls = [ + "http://matplotlib.org/#{release}/api/", + "http://matplotlib.org/#{release}/mpl_toolkits/mplot3d/", + "http://matplotlib.org/#{release}/mpl_toolkits/axes_grid/api/" + ] + end + version '2.0' do self.release = '2.0.2' self.base_urls = [ From 5e38b42c2cf22a069067698bfd7c9e88e075e1c7 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:19:24 -0400 Subject: [PATCH 014/244] Update Moment.js documentation (2.19.1) --- lib/docs/scrapers/moment.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/moment.rb b/lib/docs/scrapers/moment.rb index 713b1cfc..94d1e55c 100644 --- a/lib/docs/scrapers/moment.rb +++ b/lib/docs/scrapers/moment.rb @@ -3,7 +3,7 @@ module Docs self.name = 'Moment.js' self.slug = 'moment' self.type = 'moment' - self.release = '2.18.1' + self.release = '2.19.1' self.base_url = 'http://momentjs.com' self.root_path = '/docs/' self.initial_paths = %w(/guides/) From 1ff4e421e3c069e4000f2039bff234048d8ebdbb Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:22:47 -0400 Subject: [PATCH 015/244] Update nginx documentation (1.13.6) --- lib/docs/filters/nginx/clean_html.rb | 4 ++++ lib/docs/filters/nginx/entries.rb | 2 +- lib/docs/scrapers/nginx.rb | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/docs/filters/nginx/clean_html.rb b/lib/docs/filters/nginx/clean_html.rb index d90dc6f5..12b05afe 100644 --- a/lib/docs/filters/nginx/clean_html.rb +++ b/lib/docs/filters/nginx/clean_html.rb @@ -30,6 +30,10 @@ module Docs node['data-language'] = 'nginx' end + css('code code').each do |node| + node.before(node.children).remove + end + doc end end diff --git a/lib/docs/filters/nginx/entries.rb b/lib/docs/filters/nginx/entries.rb index 3d3a602d..4f418b2b 100644 --- a/lib/docs/filters/nginx/entries.rb +++ b/lib/docs/filters/nginx/entries.rb @@ -20,7 +20,7 @@ module Docs def additional_entries css('h1 + ul a').each_with_object [] do |node, entries| name = node.content.strip - next if name =~ /\A[A-Z]/ + next if name =~ /\A[A-Z]/ || name.start_with?('/') id = node['href'].remove('#') next if id.blank? diff --git a/lib/docs/scrapers/nginx.rb b/lib/docs/scrapers/nginx.rb index 30fc7a96..a4e8897c 100644 --- a/lib/docs/scrapers/nginx.rb +++ b/lib/docs/scrapers/nginx.rb @@ -2,7 +2,7 @@ module Docs class Nginx < UrlScraper self.name = 'nginx' self.type = 'nginx' - self.release = '1.13.4' + self.release = '1.13.6' self.base_url = 'https://nginx.org/en/docs/' self.links = { home: 'https://nginx.org/', From ab236f913bdba7cb6751924085e0d83f6d392046 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:23:59 -0400 Subject: [PATCH 016/244] Update Nim documentation (0.17.2) --- lib/docs/scrapers/nim.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/nim.rb b/lib/docs/scrapers/nim.rb index 11d7addc..26df46e7 100644 --- a/lib/docs/scrapers/nim.rb +++ b/lib/docs/scrapers/nim.rb @@ -1,7 +1,7 @@ module Docs class Nim < UrlScraper self.type = 'nim' - self.release = '0.17.0' + self.release = '0.17.2' self.base_url = 'https://nim-lang.org/docs/' self.root_path = 'overview.html' self.links = { From 0fe50f0f5e8cff144c52c71219131e71c352e0b6 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:25:24 -0400 Subject: [PATCH 017/244] Update Meteor documentation (1.5.2) --- lib/docs/scrapers/meteor.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/meteor.rb b/lib/docs/scrapers/meteor.rb index cd32c67d..b38d5dc2 100644 --- a/lib/docs/scrapers/meteor.rb +++ b/lib/docs/scrapers/meteor.rb @@ -31,7 +31,7 @@ module Docs HTML version '1.5' do - self.release = '1.5.1' + self.release = '1.5.2' self.base_urls = ['https://docs.meteor.com/', 'https://guide.meteor.com/', 'http://blazejs.org/'] end From 5aae73fca87615c4777680c55298567be7de9b18 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:25:50 -0400 Subject: [PATCH 018/244] Update Node.js documentation (8.8.1) --- lib/docs/scrapers/node.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/docs/scrapers/node.rb b/lib/docs/scrapers/node.rb index e4f7c716..c8cc3105 100644 --- a/lib/docs/scrapers/node.rb +++ b/lib/docs/scrapers/node.rb @@ -23,17 +23,17 @@ module Docs HTML version do - self.release = '8.6.0' + self.release = '8.8.1' self.base_url = 'https://nodejs.org/dist/latest-v8.x/docs/api/' end version '6 LTS' do - self.release = '6.11.4' + self.release = '6.11.5' self.base_url = 'https://nodejs.org/dist/latest-v6.x/docs/api/' end version '4 LTS' do - self.release = '4.8.4' + self.release = '4.8.5' self.base_url = 'https://nodejs.org/dist/latest-v4.x/docs/api/' end end From 9337dd651aba03d0372b7226b9ea197c2096c1ef Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:34:14 -0400 Subject: [PATCH 019/244] Update Mocha documentation (4.0.1) --- assets/images/docs-1.png | Bin 46034 -> 46181 bytes assets/images/docs-1@2x.png | Bin 121858 -> 122108 bytes .../templates/pages/about_tmpl.coffee | 2 +- lib/docs/scrapers/mocha.rb | 4 ++-- public/icons/docs/mocha/16.png | Bin 176 -> 282 bytes public/icons/docs/mocha/16@2x.png | Bin 270 -> 408 bytes 6 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/images/docs-1.png b/assets/images/docs-1.png index e1c9ce119773b9a00587a3379aa868bfb5631e1e..c5bfb6b8d9f836a21d73883da36876924f2f27e7 100644 GIT binary patch delta 17499 zcmV)FK)=7z=K|&E0+1sDv@EeDZE$~2@+8q%qY*`_ib}I078J0HsMvdrT|qD^_J$~; z2qIEd#Da<P zBj%RZ-sS+&GXWoCp%MUAH)&TwHB2ov0$3cr=Dh}>?F?7wo41zli8kHieIc? zqz&JH|9zH)g#{%(qcME=aG08!QubB(G4-tzMeTpcS{Um$?`^KX!`Y(I^92@-(8F9m zvXe0-1Zp;nz6i5V%ccXn8yi>15=1rt-`seXxFP!5a%FJp2>7J*!p3AaaR-0{#s?YumH)Y+tO$os20>Cbg-!tRUU$NPneqrIK zb=dwCJ>|i(`rr_9_)0KRsKB{9&yn%yB|c$iP#(*<1#Iia!7Cj=eXE{unBn|hgJ#V| zu@?m6IN0KS(&D+^e!3qj)!U0}6hGg^$EDnxB@kNU(I^*QR%n3R9+;NXDN)KsXM z*w0N)PDZa@z4-V{v4}6HU8(B`brtV#+gx{*SLY^pU}pyOXi92?d)>`3*+MVNk}^3y zrd#_qE4Ahaz^be5!D7<~ldh3aMqT4`)Zx4QI3hmu!bEtTCg@Jvz(2+AS?HM|`$En* zWcnocfaj?$*m%koJ1&1rz{Mx~_X4Oak#X?+lXR5L%$d!? z8U)|Bto`)wScgBpW*&R$u<%oQY|lwuw)eEIa(}X(@_tSpN;8X9N6^tN0TpI1?*Tzp z9J-X;9(X%YXB&XowwQJ(@?A7Z~r=Jm<|U~+0XkFW`&(c zar@orAR4+HLWP*30NB-E9XyR8SU?tbI0o^_XHdu54h?^LIKXpPI9|Mdi5}ypaZoh^ z*sQxf)$C@9wz1t{*m&*`qPDo#YTPV7rZfOI^y}A8i8%*I%q2)-LpGbT4s&a>j#DeK7Ne`N$?g){ zeCVBgNFnihY-f@-Gg}%5^JQ`62JrRULKGA!P$qvnAIM=V8-TT2cH{sG?^m^5SNves z0qw`nz}td6;RR_;SSoXrcT z&D$bmzs~;@fTBO(#H})Tzd|6W)8_%$f9_%d;4r88r2=R+cr2{fZ%5;fHn7A`LGG3iK5+kl^<-qc8M`Gmd}v^?ANMQE57Yk{M)faxc&O;uaTIT2-##W*tUOd zTRzvJtiWjk@Q*fzXLB7)@pgbIavV(XteXkmjxYrrN&Q=5xw!$fYy6zpqQ2I~w)J(K z?F|jT(FkDqA(T=m+ufYp8yim9z%9NL+#`A+<;b7g6yZ|=zg}RwCjt9rAU|{j?(80N z`O=}`yYC;Ibo%W9>c6}%-Q%DxTN-~RvD9l3?~_y|D`4^G_cD{|602e_vGpNym_nH^ z_mdPX>HIpj>3~!MK(8a$(BJ!HnE~8!=?RYCd4aq_4c_o}A_uMf0G>@t6A8$;FPf|)<19tV@C$1z89VHvVlyq2Q#ML4pY76+NPaem;qzvGi!Gi~*xY2)cFaC}C z@bmLSX*OukAaT;>a{+X0*C?xKpef!AFhNd#6TBb@U)!1BVGk1oHED+62?lt6sxdAE z8e;oGJ*@eo5rz&hcxG*>zpuZUq0#38c=Wp0>kTJtvF@lf7VWi!b5J`39UK{THDPW* z_JJuc^L9^!GS~sw*dANQ3#(*fIlX>~mJgV(U40Cf`SHaS)HMEI)wT z4n~SKA3?}HpMbBCja{kb7=lQw^BP%p7VVCUH=vte1az7-MgRCKT%v#7BREF%(HK6K z=7h=suH~6;DJI|>F=7PxwqS7^I&^4-065vgFfGr{6uG@k@Vu)jo?DyZ1$n{q&5d!q zcT*IlH3goNZjmk+VbOs`&VF!Nj6w{xD)1wwS)8aHdqwa z310i{vv%xt*dH4)EHHmPeDKbf0X=iz+YKye0NA#nV4wGTcS`JV%32kCN=7EG zfRcIdac5FziCw>Q{vCh>pHc;C&g;8uGiA(_gj5KCvg~$V#{HN1cyHmu|DFd-I`fyv zim5F;Ahk6DsI6~^4hubCyDQ^Xh=%jd`d_NSNE zlnB8Tc18H5Ff78cnu)O#wksqAcWJKgcV%>QV1yZRMjPYR6l1&?Y=S};V<3f~yKjWt zD@}3prV(7y8{?OghA>=W0Q;8u=-f2`dR;@}1x_9!I-j@xJz0vyW6Y$)PKuuG=o+RelkK1$8PnfN~ZrGU9)>R5rQ)=pnp!?*3#MhCG|7 z^|hV80KIl5qF3lq2<=D^_k^cx*Qt0GT$_@RXZ$#rY?N^D#6u(?rP=xO=keWl--#qd z6L4h((6qi@pVgBLf!oc1G$Y^wDVcPm32@g4>4{Agt$hs(YkL^rw?zi%*xx`osIh*b zgTDU65@3IoUs49`aBMj-9Nq_eP4s#8aSnOXLSZ;o{fGaQm1v_+dBkSNIv7R&Pu|wu|swAJIV7Z0>BsfcN?5Z_d0tqVsuFEruGcW^^xOiN$>U< zaK-CHZ@48|W7EmLICFH|p2F}6xoqbcFiJ>p+Eaf-O>a%$}sKj!(JBv(N z!8U~3vq@eOb6BOrMlSn-c^$0JJoeFAG2VZQg(cdtO$R0Bd$=~$1slExFf`>3hWRCH z1W>lJ0@yj|0$6zg)a}?EZhpbS;sRUnUQ>1?e zH%4z0ec0;g#}+59A`8*^k5VTVhK&Ul*9Tl{L%CENSzFpgo;cV$bziIV6<^JL$s za27TmjFJ*|z!A86TKocfM%7hv2;C!e*)mE<_?pmZD_ytgvY{UJ*tGROvu%kDSzvr) zwk5hM^Nsq71;rb%;3GOLAhv-LA6kEf0m${>RX*U~uIvC3SOPdIx5yG9Sl%U}tvOMQ zCNEhkfDLqX_!>`y+D^;7(XdeyF3}c6>5V)27)@JoMjR~igyP!^Xf2}-p4gtFVzmsP z$UZ9yKyH0Z4Eu5j+w1Bc8r#L-uSs1EV5y@AD+7Hvv@Qu?1#iWDg);%s@algAEUF7O zuR4^Aen;-wrm4@oTZO#YWErd6WCgZ!ELhAE;KJT`0HPeUG4^-mdV#rb{^MZ+Y`C;*^Wfo4WV6-ki>?{pg8S+6u@&2Ujw1N%N2q( z9z>w4{8{s1g!1c=^r6)xZJ>YkT^1!7ywoCgJ$RBr_nz{;fATPbT;uDcr#HESt{!?B z>)-6((qMUSGrfQOI28v9Y5P`V_c#W369FRTS0~i~2u65Y14(O@xSO&;hED((_dC2u zp3!xbB<2}im#qx1#ay>nV@r0_VE(jIvg@QShfpY#>x7PyAVgrCHpqX@d(r__+Ewb+zN+pdTtcwk?b(Nkmb(I@q>#{WmY7>CJvK6~)vXG>PEQ|wq;+;Zi z|99spUFEh!oez#^GWD!dQF^z-!sLz{PDJ2e7P0hdI|xoH((S^beYR z0yw>ee)BXF?Y?Qo4QHh{*PfPUtZkp!T(^nbFMWm`J$e-Me=itpBbFmabpPpTi`>8YwgD&p9(g`>s?Ln>1;XMP_Cuqo?NzJv}{r=!f}_c%utV zbhXlqv^>(A){n_B(|eWKrpfCoZH!)Jn(M!!dy$u$)LWZoT)(dLS>_6Lse$)9DfMYi zA-wiI#K;v_F<^gTrVzEoJ>JL1@Ua>|awp)Jyw9NeaW@cvHN}`T0Bzj>rZ<-7p-^^^pG>6s$M%I6l%3x_twR@(U>j&Q&*0&(b z+XJtTL?idy8RVs&#p}d)JlpDxJL8AsXS8k-c*&@Kw~u%Z6o*XQ(+r>tU(V6g7cz7j z#mDfm#UPXjyxlT*RjO1eAQe(uQL9!h1zij2VeJCd?hRMir#zqAxGoFVOt9`j@I5D; zdf%tnejtCfCUI~16RD02`Tq|9`Lizg@89=7em3J5B@XEKGJQ}pT%2u$%yspVGM93I zPubL|QwQ>IMpZX@gj3n9S+l2?fBTblE1`Ii1KDWX2!)Eg|9;NRMRt%cu2_E>`)4+*Q;W~l3|{FVmKK6lUQKwo zH*Xb4$#{ibN3)Q2D_1Bm>IwIP#UV^p_k1d_^69I|6f%fiO zvjRSVPh|#E<~wW8UK!rp*?nsxmvxystGA=+IH#VX(_Z|gDw&R+(cj!=(2wu`vi8!K z=|=T8UGLUTQTX64)J>tt$HhxQIQy3u?%aPlidV1iqaY^>w+HtsqENja^yhsFKHeuA zwS`Jq^9eim@CY)q&Oo+PR~VwtGhBbf1ei|Vw`2(Aa6C-4=3_kEe)G*Y0={;Z?U;>? z4deIeaRT<_$rCnn=1kV3XAl11ybLI#(A-F4_?_5QpL;+ahCdyGg>i5zlWLPDkp6#7 zvLJOL{X#NT!T94p37{H$|K4gldHaFsTd;YUCl*y3SL7zyvoNjUNH!acvo_t~+sSa6 zRNN?JRHf%wsJ*}oMq_49?$X8n7YV3D{}_KY3o;j82F=o&H;l{d*c8t$ zMuI^Jb$jyUJPt(;NBF+}bRCP6hn$en)f{Qfw4*K>>ou0cswNdPx>o|ggsj{La7`Eh z$C$3jEqsNbHlql_VdRG^#FbP)=Nb8R^#=*ZI9n4{*zH(Cbf1flDIG=um#zx72Bi5a*z8Gt zNm``tDsR}JtN@nm*9@Qx-vGiW#9@Bgo*99d*V0KbPa3H7)fvlT#w>?V>mkopNF8>~ zm#ml3@5+beEy~jB(faPZ{F;9(1?gU49xmtR;8D?AJbRkOU!S_5IJ8Y1Ms=^_><%4Q zuYAL0{)*pR))qCGw}CZU9>D6&T?egci{FQ<##>L_s=ntsep-95K!4ieC26J&M`Rc` z%*|-2hl@Lh zqm>sxbuS3ARmaC*)c)q!pXrUXmof0T-UVB44+S@`sP_;GASoOR0RLEb9o%@fTeWIc zel4VWC0`>mdas@Ee)KI2jDMzmZbtu2mXVRcXp9)k0i<=~33ZtGT93p&rcbN~zb187 zLDq=mp;{0AK^jFeCXIh2nXB|gMFA*(l}Hz=(*_S&cqM4U7EJ$oOyN>#C<67zBT{b+ zE;+a&ebxpz)oMSVk43Tnhp+s$Y>9@NrRToDmAsc&cJC6Ra-SmR;GwrPPDg!`;Y8QI zhVy*(Xsr%~-l`pFvSt^wmiR+=c?g=g?`93?e#1q6*~arXJDY#33|;%1@A2n9ZHT>6 zedW&0Mnh-lq#5hX$uQB)%`nx&jgUFGoX)@9Y9j4?Oe63daq;3DoIE)J2M;+Q;_yHm zTh|pCX1d5Q(RqE@L}$7TTG>KysoAf9k0iox#6wpOpwQF&>*V=9^n$b|l*6zL;0>w@ z@T-Evzq(kQNTGkXyfb>DPaF<7cI+6V=aoV0W&!4pKmI6(;Ty#O%pmRKVV8S49)`I@ zo9>BqA&t=tpn%|CD##kD!fr6B3TY8(h6>O*q&B4QDhR;$%dmhRGmiz0+Jrx(A%&}I zjzU25iSTbYP_a|X{`rCGy%j+^cK1gawr{NttuWf=YJGqG`gL&2F3QKf{9NpKdJ{g6 zt|0kU7V?+^xj8TRDV6CTY+Wn~zFH?KAG(JgD|8|s;rGZVs2}+h+H`Gj=rO-C?Wip1 z#lJwcV}rOzI zl$6BiD}hCuz7SJ@M{7hzCw~O2Ca$1c0up8lQK|A@jq=ZNkhNqYHoCYmdUVx}$NThcnL2To0#e?E+~? zGx3X2noXWEB`6~64x)1&;_&kaIFNl0K~HXA!JYH4&p3)n*OL+V<|$^(p1n_f-fz>~ z)_)Oj9#X)$LdoweY6qOeF9FH;YU>$P_9q39{7x&r@IF=e&DvP#jCLF=CWfVb!`F}L zCOUsZxd%*drj3g;>~Qnu7Gz{BM_QUIX(7_m7vlJ42kcwi0sBJj5I@Qc7mXTl0AHn> z>h!M&0RK2-ApqQQY4!UMd@t{UfRUSDyZ{jQp8YojFATUN1IU5kU;R;d`SNAZiyC>- z0a`~hN;m|7y?giO0P?ZoO7Io(E9rzfVBCNEaq%|KhGnT|#-d-IQ@Z_2<=yJ2fHNoA zk`h&L?ot)Xr;(gK7eH6(-7f-prN+U7mKH8*ITP+b4`u#M$H2dy{j0ro`{spPjLu!$ zq{q~czG`gvh!IgMZk)r4Tj#Omeg=H+Wnjh4RE$eYg6&_CFgOtgy))skpFTP6gAjk* zt-n#-`F;xREk|JJeYmiZ*FnXPzDZ2-J)x-NbG%6MJgSsDlkn}TLufGGb%`oxs3g1X zG!q>&f-o_SJYZsLZJY@miEB63(xSJXI(^_X(6>~17w=$ z#HAZ+H?IHy6a3E27XZph$hn-o-1~nC5and#=;ilG2!~I!$-=o~qL(v@#Dby&2Tx?Y z^jRby_wL{0ZQ=R22b7Z#)pb<~4_7k8ihfl#e2S0xIDo>ckQ_(`q`fLHXixf!q)&<` z1(K?ME`ahnZmaFou&wsXu%faY&ZqFd4)w1^Es-2>ie8Xbsk{rdVApF3vKlzzVZBj02`d5T#n z_aJRLg-UeP`^yc-P3~11A_CBE-xe6}@Dgprn3=MU>vsKl?Wdi8HG-zRXvrk#6YJ1yLB=jZ9`57(LQ=B_u|v5yZec8hyH z**HWOO?B#LnCgZRgrG2z49+)efWKPl;7msYq;xXC88dC1Yg!+djT?f-@C-O4qlI2Q z*_HoY@23V~>hU|1A&eD&L9KM61UI9Hmpa>2QModhMc*ilnPgyd5yg*J=r-<3t^D3k zHhC*fhERh9m^4P-iu+IT8Z52xc%hlYSFm;KRuef<85(|`h@2z2A?_%ZX_jtt@UKkKqVUWg9%E~>f&>Y z7o%m5CrgI$gCcbK%z|XCS_jUp$i3hd)vO%nSGDwh2b`-|=aD}9)RI=~<|fmOjEwel zXk+1~{oQ|>OaBAL!!Z{fN@&5eV_u?3GtqOoWTHFrl9{fF=>Oy~rt*QO;W$<}N?LeX zj$^5gT&<>mJ>e7o{`bFcQ2U0e;Jk`tr~%v$AXKgUn7a7A_hTy1J{Lgyf9cc~#ctW_ z%Bl!!;1u>)8nn^$Zv&P8#u^Gm1PXJFrGLm;?_c?YP2~E@mId;bZw6KDUOme_D+>{;z5{2Ry6c7-&X+*OlTksiw1kpXyG5J;i6C05`hV zmgZ!u=3G(_d0}Dy-GpzV)2{8RKU*DL;?ycy>$kRM@_jz0jQ>ClNZUyvqI~i{Wb&GR ztnt~eovdTqIN8Qqj5YT8TD?!*UcGu%#eH7rp21cN^BvmH#|N_Hnuh_!G`N#%zWbj$ z_VBrXk|t~9vU{ELp{tN4?0PE=_G()$@Lpx~^@k_6?cAI{~*mU4k)9%Bbn%WK@E|1}DevkL@F?_6;Lvw37 z2S8R0mw>LdT>N&{a`8tkm#wJfymd-V=fH7)az6pMyN2`DzM_xD5RB~IISUSzY%R5? zk8ZmuHmqeXo|yxW&2e~ptCv$ov~?%{_?s9a&nex0BDu+>8kO=$D@9*fjj9X3I7x_Vt-Ah8aHyR(P6l)i?sBNdCE72)& zB|1bdf%%}(XwhX9OuG?q-N$~%#oKg$PxR3kF_zEaa|tR1hpX=V&8R$euaz|PXs|T) zFr?8jkj6!iB`-Ik_FMrR0qVa)8WYn)8XXI1Y!oTF@W0-y^Y;V0w{hCBvE`$@n=ODh z#<=^JiSpqE6D9IY@bYR)1g>j&vs=eDlPD64(gg5&a-|AEr_~vv=uypJid(Ej^e0N?m7eHFa4RExLyE@w@zCrP2 z0C~Cm4`I^;+#I1k@8yJk7IX6@b+dLqJSz3x3--D|fhDoGID8-KkG)E1_~yx_tegH# z8ccwt9(x9CB;ZzDE<(^v1(KhC7QyG50xK>R!tW+<_BrsX2#FM$y8-xG0BHCfmjID} zmf@S12X$$LuzmEBjaG@P(Ba6kytdws3X_(D-nQ&L7G_(=kYY zxc~5PhlY&r-7j$JVEe7pI&c8{SX=b)T+-^yowFP~6Xf1DRYYzxV=G+DvFcAV#OyR< z1@}x8cx{R+$68?Zyw=D2TDR?}24HVeW;vg#>!T6Cxl+)ti=|LmRa~V#zs{AWd?I5O z_Rj0YJG`sW;!9V{1OYC8dBT-WwsHQ&yDj9;JirU3U}Sb6zUJ!XE(3E*8T3ssej& z=3{a6ZS>l74xYy!Vb85Xtj|zjC4rehkiJ#mEqO~T89;Rif9N`YR)$Wtk3!fsYH7{( zhZkpeh+D?NQnZ*nj+wL`1hekL6kNQ`@9{n{CTj6BK1U*>5WBpVv)^WEc;cqX`vw_2 zfHYwD6`jp74{G{G-TTe#cNd@L-%j1N`KQ_2eXGw7c8GmgQ$OKJRqycYT0RGEYEeep zy{fN!tNVD#!>vhw(TRhm%wv%mTxXcUXO$Vemh-kb)-N%~nP^ibvP_DQ(-K?U+MK7F z!_S}hV0%f^o-9@Vb)K|ahEEm&xbf4WH@=mlZS3*V#?0;((~!Ji`t&YQzwpnpccf7I zfp@!_b{E{TvtHufttWW=Ae(%R65ReenSov{X1`ZY^I4F8gpFAL>-@+}rN^7H~V(eqtTxtrPw;a|eEP3Pv@@ z;Qb!SZF+mAw8rwp&RCIT1^QEJgl}zei#(rl?-n!V!kK1R>uQRqP%}KgVv6i5CWr_z z$JzzvaHYP;5HkwNrpmp3t^T69^2>gTNR2e`QJ?gGwu}G@BiKHGuliysjKc6z4a0?} z6W*_D+(hzp!J=(@#F>EfdY6dAHlEfi;U@ynYHat2@6>lTcqr}DQb>3=8Nl_6cM@cd z0<@JbLE!fC#TyQtP!IE&LXxmi0dX9xGHbXmB)etH)c|yhe*&z!T!>gYEwcFFHT2z_ z3N4p^L{y!5TEax8Aqc`mZy0N>WzXzA zbLL>^nl#J}%Ewlk)=!i)!i&7%#TP9t1fU^*8*Z*=AS(u-EO4Sa_kc3ro+ZzAiLLF% zpIYCf;`P%N&EfmlUx3 z;s~>k>_VsfW6248U=xmiEIGcLSeiY_%Zy z)I$jSe64Vl;5+)6z3@dB-Fd{zJ)m~719`w*tW1H&a}R?&(3E_Jz&lI2z}oC5C;lXQ zKqhfI6=4$r+_o<4C2YQK!C-bZ?>6**lx#6Y$p&1CHW0Wi34hvc_^e_e%-90KWK+B> zfGN*_&DWZ-|57=Iu1>?ueV5@9bqfm)U4>h8A+-H-pyWj-g>ThkV?i@6$pF}y`S{q2 z(8-Fy+2N0`5V+`{+zZBeOqrD8jR{HXrDG+lTNQQYv?}V(X=P++V}i8BcF2<&BLz`IpciNV0ACcNTYWxqRl35cee;G7@p&Q zLCt0@V5@bUTYdkDZPMI70w)Z*o=jHj0sA$>R!`DYa2N1pFoloFoYP{cYr zB^=vN0M;tu_utwB$Ys`!jcI>>WeS$`6h4XVAq;||Cy{8H* zN%nHag8M50jOfXnwc|c>&_1=CAPeQeh)&8Rd+p@utZb?bF!A`ovoXeYf) zX7j0()CL;?SOV_t%4_iSQ5l{;E$6pf)YjBv`HYRwRkVI7oslaca9b9CDeV?~HYeHo zj{x+8Fn!a#&HxO`uYjB@_k0++Ap?HNcQMd46`#;=W$z4x7j_FkZdqqSIEb>MI`JTA zr=DlbSpykzEd)m9KD9qg=KJ0D8c~GRPZ+II0)u}_;P6=?1InY=$g%)-2^raI;bddm??+FJ z+wdJtvrQ8c*JFI_+7>2WraIQve(!o`jtX{MP(j4ap;#)JJyw{Pvb{I0`QEiWhWAz+ zHS|2IF+C{%XY9-!g~J8kg%5H6ZKSXu2{bjMmu(mrfG?+iV1K0+ZxqZgHonH?YeoSkxBT?=N=;z}OFjNl86~u#_G`u&B8Ag@X~4t}zgt zRZNAon`R3>8$=lrgxnKyPnY%)0hLc{KdnF3fl0}t=W{oX;C)>5lKW7fC!`nd#szO% zj7#Z3<(n*jW%F`6ZS!g(fLlC5xQ8QAyEPs^cn)UX&Orp86||W~SVG`t5phoh(1W0B zeB~Rz2ao(3j#7#`B%<5$Oh{o1? zei>tNy!cya?shU1W~GM@aNCVf?St{5%@M10XEf*SyEFp3D8;fZV|4i2mQh9wJf5s} z4&rOTr~{*lQ9ZKd*ggtEXqxq1t%S436%iY(gj3;4K%D|Yb|_=zf>B5cS0oRp*b=!% z3_`enr-O`|Ni*29y8xbeUsxl8Cn~Xr@cZ$e!cYUjWtj+`DCP+b1*d_3q*oFb5_|_= zM!VWca|o^$2c1)nVx5EDxt?rINcD-V%<8CpC8cE|_*AOMK;t3+?}C}1dk6!KOJBtX zPal_o+2%Eep*6yiw46)ew(#KZB7nD^)u6q9y{N9o-qTl5NAQWZd~ebTnKX=RRSOXR z1n{AJ-!4kSL>4z<$GJy1ocRcW1my1o=e8SCY$h+6UJleYqY;2c`$RN}!SyC}x(0H` z9|=pn2CGOLsABifeCUjhig5D7)U2K#LOC77Qz`^Ihe5rXVUALspl z$~$wFNA1p4J`!+2^~m-twFMtp2M_PLGU8BQ=l!9yCFf5`pwITPG)&bf;OWTb3`)an z^-zX~tul6OP=bd&tqBWQB3co-EDiHap&6Ab*zY$wpLR_?Zkuw^POaU5ua(3t=6zwo z>2@A4fu`fwUcyJy1P7y8!upM`0=Q;>leS>V{~olS^CXaLgf?SQ?`r)l9(=IhVsy;% zgFNsMr|roJ%2b!dr&9${R=Cjy;GM#UxNyDzIqBE%ILnFoAN zI~}!xbv)K46hgFu`_Ew&bQ+VrC0MvS5kJ@;#0|>p+n^i$_w9jk&u|u%Y0QW7uf7-I8cQ2ZX zDHUVX(;;FAdyRk+*P4Buf($=@cMeixk*l8iFM2z@)w1vAsers2PejKaR&3qqN;yCR z@%q`3tteHHvUOr%h6?=Gs-+ufj?hJv%XOyYS7dADHMl#IPj@)$ASM@i{_h2;6}yXYkR zAO<9SoK~_qdBNmArcx$LuFDs0anNK{Sze8-v@2LP)0;!5@sq_%2`|mmXQE*0C;j_O zKMZ#`2<26wJlN>HUO zC_b?Z(f@MQzP(~@@H2-)3*NPq%;`bxtWOW?@FTPrJeIYwJ_KrmOh&S|+0-!(VZW)B zR2A_Z5!|P(xM%r_QdEpY>Ge?v-l1A(sHwJ``t}e<{l%@g64Km%_9tmX2#>!j%p(xp z==l;(5ke!udD=9=$-+>uQ_g5%X;pB4jbP&KBD}#+UG}}S1-px?TdQtW1NUlCik221)W7KWKf2zwnrx!8m!#`J)38 z!c=Nessub%!imG9YL?Aaqu^pf|37yh2%_#EMyMva@)wSO{tt}SfeffKECMF47EREl zQaP8v^rNk~cUe$Ep7ILShf#7mg0(wMK5fX4GsOCQ11 z*F~7_8$+p3q$JC-{d9Y(my zj#d$D<$aug_D^72bL@AUjQctrG!TEYH6J|{Y5FZ~tGm(Fajbz~jvMXmtdinsr*iU> z4@WEiH;!Y;lO&{l|Cg6?${s9m&^@I@)A3YCodi{Pw&T%ej+2slIZRF&>7;YY*j_tP zgHkach-2B2DhATzk(LeZVCzcU^RY2(tnl7@?|}|~PqOd+a?#5({5L&cSI2*|u|hZO z;Ehq>U zppPFvSE4uI+@8>BAmI(h`p|2eZjYZo=ean{7(EZBV~R+?^j`pzv4AntIKYTxI38Tn zCII?>^n2=vCraIn6 zePkhgBY?S2i+{{}T6FU4{mbrgWtlwk($dlzK(8?JsZsWP9DR~?4gFuyP+wDl$|r^F z`ygDRu{PF+PkG%laQ!!ImePvFW(w97p1%fvNc=7R-|4Dfb5*G=8q2CnOG{B+UU?Jc zPp5T#PV%|I!$(hV5P(44lj`QOr*;J1O-vWzBXtFzu?8^Di0ZW&d?a;1PyM+dW7QJX z&yk=q6p~THq{md#q>(BH!hgDnFtKZMfBf-BgoTBHJPo@}jDL-Y#LHC2+o%ukD~=O? zUSpS^6ivAJwCKwDM+MTDJDCS8tgYqMC#u_Ms;kH8=<93B!bhLx3U6v`#N(V`+zvOx z&1eVQxpRk$yapaUdc?MLxLDtAK!|Dmyl}eTkiQJ!CcB+K8h*d%&J?+Mur=_^_nE)_ z%dYyWAH4M7G*7rI?i^J<|nzBpLXo zP@BzS8dnXt*#ncuGWe)o145fM9916Fd`xv~OO$F|vqYt#HA)q&(W;dV5*01sKiNc( z`t|Dvy3Ygw0Rj9)8hRgu-=9ZfWnM?Oqw+q~_q71BsW$IPk?Eypx9^>Qd<{o`@{;cT zYHhJyed44GTAEtYnGQ>mZ4-7Xi2a#YV_@C7bqhCQ*Wf|qER;mfMfr;|?g3v^6rsGb z1P>lO08PmpLN?}201obR2B(F;1|Wd9RxRA%um8hbX!bY5qOs0TeOCmI?yCPkTr+3C z<&go`xPrRq!paJR#1;$*ZH3~0349^;dEX_cui$zPL$+okIJdZR-?hfNueO)qtxcDY zw!ue|fp027sjCX;kS41ES}K5@1-Q980on{e4FXUTLYvh@EBBE`sh&if8l=ZmKoA1) zqglC0Dj8+g7^VCjNc9m)-wOYWR%s&VUu7)!qS{D4qQXcH6~^*4RYr1uwtp2sKGja1 zJQ@D}{(Nes+v%C7;ooVaGH<6g-iOLv0$6~8xAUGASzRhEesQWW2R^|&F>~&$T8#;l znx`1kX%|o17OQaIU3LkFJ`mS@Y-(jtalmd}M{$e|?u1Rp)eFho17=+EK=u_6+`W63 z_hEh67<%dZo7cf70x11|qWciWgvBdbo4Vba`qNx!eQSmpBP`1|+wAr^w2A(GJ2Q9u zy`NuBwcvaTp9Pdujf+F;l;h2qbQ&99{*8U}e82Y1hTxLi+QZm}jvTd4 zDpCElQKGVm;H<)N)u!f1l@90qs+I{h)ysvt%4NdJlBL2&6*2;;%#tO`yS6$Lc@qYo zs7g|`(ZDtJCUU!KjpY}-5y1Za`(ya<;b0$%p)15d*NcJfgvOpdd$_2~>Ui6#RjYVk z8q+C&S&wdvy!f<#uq-qo3iB-%K}$mu+PXTJ>97<__N|Axm)#?Sxii$o{w%lvS#jZI zRF&UFMMVX2GESr9*katt3d7T9_mO#J1#)xKc^es@j+wEs-2t#!c&A$crW{ClckiYU z?_afSt4u~M#FSy?n69uCEA-ct?e`8@+SRy0+w%Me_+~(VZfj11c5G9!0{YD=x9M`XE-qKU1_vR9DyjUj~LyrDN=PdVpKf|$oohb4FWK`{g{enLJe#L z5QvX!EQQd28Y|&QwWScoRI^+-(qJY0PUYROpl!oWtj2i27uCjc=m4RKoK@}gL4j4q z-wwgt0q<6r44g#XaxUn76+tux5(Na1NF;D`b3<@&FixB}!7kb1^(0=VI^IT~)#rVw zoX8%%bksjg18~W2G=o0*~l9fTHJHYX`JQfxvCx5wAAY z>C$uVbim%~PXIML2e2t})Cg&m+Vqx4mBj?y!$t~5XkB;#iDUS*Ov)qxGuywjOW^6Z ztPrkLE){g(F1!uA+RpkjFsm$uDMBY!syC#6XFC81KKY~M{SsDK0MNqB5^rxNsrwLvXP%9RTz%jC*HS zOvuqijw>+7X*n!*t;6b*`w(z05{HtHHAJSw`Q}&9E{Kd378X8W>%5#KN8HPpiQ+VW z6O^RS#LWyhBt>}QSadkfp3O&fbv2)kSzqzV#=a3ifdkkrFBsr)z}{{C#>aZY=CzoQ zw}SbE<*+h#frYLUmQPs)w*?zh{nrJ`b(*x>mY3CU<2ih@{YJBGYJJPf)0G$%)toVO z$HmNnp%0;#fb-&iIPhqfq(26@m<^`K8*9j*g(KdHLs1>4Sk>ROWSb**5FLB4R#< zjpf@p$9H{Y6T96wz)~1GF$K?}lwF&A?_xmQS9t%(PgPIlbeSz1PZOSW16P3Q6bt^!O=CT@}d z_2@m;yi)Mfo}#)5lByQP1NWen2xD;^hi@8bhBok=ooRCiCXZ%+@QJAw0&+Y7 zxE$Qv2tf6T)JL1E0}PSMUpF69xkw(cjsZwh@CBS4jn*h0n509Z^xCgJ5p>E7Hu8A( zbymU(`fW<(8I=|+G2XQ?$Vk!`#sho(F)hp8tTmQXVAE~Iba}ak>GFA1Ci3&^j0Y=K zPnY}Qr5EPk`<0hx7mxFQbPL^a$8K}yU#uk0$34Fx1_B*b*MD* z%9;CtX~$|eBp*g#Ml`l%9fSAT(8ude9&oe__V08dD^9_b$bGrKOSpLxXS1?!;zkaV zujSxU*cQ}RJnt|CQ&5ujIsm=apGArn2k?zva09&;zEwd)I9M7Fg&8A>Ytt$ zs(QI6V_ZaOoxv$$DOOr3dmxslS_}xlnL5CW=YZF0>hy~UA4!9LPXJa}v;pWU0!a0f zA+#BbZgG6{=%!McFr00g!joa>ayvYP1~~LSRa~l^JtolU>>o2>VV!=M)Fm)Ch{mZlzT*; zFs9x_{u=#GuQM5BNag2c)8xMv#2jGXzI~yiqXW7XABz`%FXm6W@smlmjz__C8x$WS z1|f4DmmQGgpHVqikkik~!)5&T&^?mGE9uR##o5@J8(rmrkk>z&Ah6Y z=sLhic|I0@>RMrw>o%-gxe0c&*T8m$J1q5GvC_b8ey7v0Z+5_-tvTqkF}rDMY;ASc z6EuXJÃ>tf|E(JfM)xK?Pzx4e=gZk1uQIZX+O4p+PD2HP2{a%{QcXMit(v3l$#0yk$J@`!@)yAPY?so zjOFApMdAG?vw!?RHV??ZM(OM83%bpTZ@b0E$8%Ac*HIhm(;*K?$!VUV5X)Nnx(0Ru z>n|UFy>z-hCO;KU2R37M;(^2kUQR#LuF5M%qF5?LHVs1_kwM5IbGR6d%~z6m`C&me z3jJo`Mq&v6SdN&6X%FDgXw|pqc-NPDYzz9gMwdZH+xJZ_*0P z8owBe^=)7`YYnWYyMd->kcVvcT(Q*w8wBM0u+v~gos$4F!D#iLV8z%td8hM`hlJ z`gWNI)EqOW@6@@b`{wO-KW`ViBmK~&M7Vjah3T^S58aavOzUi4RZK+FnvO##T4~vH zl)ZR?HY4~#adnS9ni?Cx#&ibXm+5cGio>{Gf9~&Z^nw8X=4rme&Sz<0vA5+;Y_#18 z`#EdytKLdjnL5GU!UvQMM9{X-hr#|4-w9pVknP#I!?xw3m*+Wr;+Wf^^LZnH;-Ld)XJ@|7TeD^j zh7B9WMP*(`ZQ_B1E&*gI77ZPpA7;5MGg*~-DBkB>nDk)W@8vYT$6Fut{0cJbpY~gE z;#M1ZJhsm3uoXw1kHbfI@P)P8io=Iif0himF7*@1a>YMzy8l~Udcn13+lOymdGJ*D z_Slw~Ly0&V6pgK(0odTO5nDXBBjQjbeh-rDN=ZrS@;_pK|0~nvw_E@PB^c&r?@#c_1RV67Oc1)*0cTDFw{8MinShTsU~Uc^2?G`^1k|+%f4+c^pq`&$>%p7 zM)-w3TC>32HpcyYNczqT(Fc<*(`^s>y7T65ckgmfRrW9f+N_(05%B#+L+0taEkmOr z*kIV%S`dHR@at~fLmQ*7Cmcybe@e_b#7hzpvNsIJ!lGM_9yxYA;!wmJPvi{QmSH0A zmr*<<;4(%8-GOS*gChOoFyf6J0ldlJ;}X|=S`z?`@$^&&4>%@~G&Oo2M6<5=7azH4T?fA~9>l)XQk zx_fy<>b0D{n#P(RTl#l>szi28$bt(N;flwxSeeyzvGoR~|IO!3q{^6nn3T*g(p?^MChD?(w-&3`Bh2Z>?{y^6k>@U`eY5N&5VL)Wymd{4CL9`7p#q4a;D)g*2B z{`>DU&CSgz@fm{=BSyg3*qE}f%1@}zO%%01leIL|ZPCY6cZZ{S;};9f8>6SGZbU~z zN(j_!IDHXjU$bU|dKem3$Pz?00N>nvp0FY6`U+)G%1C%8_r}H~YoX254!STBQP-9i zT+51Ir~YN%K__$(qyo@8Mw5SSifq9C3NvQiy^IOK8Un!1_TMwZF<-Gcn|@_sr?uGr zWF6(fv%26Aa`=idQlP;3yDyOb_!a)a&Y(P&eH+-;or700fVx(_U^mn8y#~*ohhEbh zVAyNm#{hgUy;kPv;uef1?K{J2Isiiow4zhHFjK_h)aJ@_wNNzSt8@$`6X&A{S&pBSF|ScI9QJ@+Hb^cwwSW6i)s>l z-!jV?-?8?8e$CwX)Ma6(bl9Gg+HCJ>ZRP$X9p!`UT$E(ytB;_AOFSyfUfl-*tvGZg z14v#@fabe93^(rI#pCChh)znzrR&$l=Q(TKP`8!UM*%b*I0}CzgU7!A+|7G0x@``V zKZ`yZQxbqRIea{6D9va$LxAYyQ0jaZsW(08yMK4Zd>*F>hP5dLU}TIzL1NP3A`=@U^nbY8g%h&;^g4l zF*9CXKjwHR>hyoqT^@0L6sw{-z%||q+s=>2wdZjwC9omJEYc=s(HpICW^NZ4BJK~$Loe53Yu47spL}h=kQ>ryYMhc7@^Pn^)*LVLAu3Q~;az zu%(*aEYUW!8G^1JJA|k$?zI{}n~y08zzzNT_b>HJi0IG*cJ12rz7#WX;6U&>6#<}` zfoAhH1Q~{#;%!%Bz)1_CAvT!iH62;Ys~~dZ2%Nrn5gx9qQF~o1>d$h|9;_+-SjxNI zoK->@CDwm@JnRy9!t-rO?u+EaNx`{$#sfP>Lm9aU4^O%0?uwceup+z@RvvB-*M!c9 zxxOa0IlpSXr>Q*=YN{!k;fY`4T5{UzoUD6yfNjamD7by$aKl~~I$)!7tRiETdg zx4cQgaXM^gq9!w077NqmvE>Hv&AS5R7b;LDyAXfCVJjPeb<8?&0EPFf)~*|>n6!uG zgqe7kpDVl|tqDs6P`jBSEat62|EMd%>-9UB0?YYpg{UpOVgHykSU9fYW7Prtoz{F= ze4DH!3k(bdJ=!UbRLRD7G^$jolEvqKDu7)~bX?PIS^z^#kk#7=7;B1?OSG|lNjChEjH-yld&j(M{`zYqBqTsK*$cL9+m?UN zwJR%dr2+V78~w96cE)%&&=}cvMtI)c2=7K31NNi=W>{gW2hEzlB(!Xxv9WCfEk|2@ z{clPIu>258$&~GGPU?dVr@F!=t|MH-dn5VCU)vO6(*WPzV7n&+`(`39WF+qH9(v{S zp%J?u9Gram-2v*qvM*4Q{R3*!2aToS7qZtybYAdnz!E>2HnJ4#? z6fE(A8{2e1Dh8nEk?R=Xb+XI=?zsFE$M3#GZb2#D@J<2;t^5Fx+_X@ZiDXq|K)SXy2}JX5k=Xyd7wS>;Xo2Nf5rVF~XysMhI-$96=NH@ZwYxTny01 z_C-2a`)6Ye8>siZi-qpK0Vetep9`*6}o;B3&_WqTyH?Z`y>nN<7@pYrc(zTzF5=RJu@ zRua2>Em_=CC<@>AKYw|Hd50GVaB+AlOqa!!89+ntvqI)u&%-0>0dk6hczjj)0o-;l zLag}+Lhktle2u%>lvs`-h{QUtu|+4*?yzJ7y8DJht7$U~h`Y)q+C6`RqD3E#;bUn| zhz#I5p81ww0=|(WM}lt)7PVo+hE)iFQ_S^Kb8U=~)5i!ex*6j|7h}96FLd4Or_s)SIm~A*lD(a1o6lJaoBe;uVhoMtb7TMq(93Iz zgC|g0;va6dE((4HHZ}|-pLTEJYX)f z_Z-F~Yl%gj@+wwKzHogPbK5J?JcitS1=dAppxL5Go>+*_vUKMk!uF&)(EaNW0#DwC z*1SVFc=4g=D^w^sbj8$d+ao>hrLfO8tFGd5B~^s^V&=8#&WX4 z$COltS#N7=E0PNmFS&@)O9>|WZES4R$}s;PK-pS0(7Ck7wK0&}jOZubBmmP%%I4U; zrZImsYG|$R*;w0Xke1H4VOqK!<#`nW;LE&w4bP-`p1l-4COBu4CBq6`WcygqyL|>; z^*qrBE(u+*>102gIXZq%LD<9`wsR~PB_ufQqeOm|zT2U?Y|Xv~Z2k@^u^jHfB9d3K z4PmxyvZuuCR%@|Q%d0TYgAJJbK3XfrS+Rf61RJ*Lpu~I**P*&#qxS%YB;Unw-=tCj zl&!1)b_%=*R$c(LJM@5yZ;4BH-M1VN zqPAQIPQi6Y) zppTI*thIDwiV|0mh3LG;DU%99#{o+k0M2!wT&9W4E$t#s9PE>_FUAJP;zr+nx^HwC z3!MN)NeMe(58OK~egHip>nS;euHo8jIVB`~P3W+duG_TPF!%aw`ubnkwuDA3Ag&49 z5><`)M1I8rIt-^l*5goG3<< zmn;#$hFV&DjVD5F$K_sV)VL{^Xp5rs#+`gjX@wY3k8>#TQfayLC#Xz9R8PZxHrivw7}TXA3EjDHk7I|6@;>w(R$ z0p;R9kh88?%5$$)!EZNN#3(mef$baz7QGa>xHk@fCd8FAf!*ZLU5@E z5$Gy^F8we<`Sn=(&}xx3(E5KaladTxY7x60JV~K@&v@VGJd7aM_&Vz7OlhyJgWiU^ zw+5K$t>|N-^VyG6aiEa8Zw+>jXK*zVAYwrcQcZwhgjW|Jah($Pk~hfk2>@gNfG5c# zs;-j6JfiBcRbjQ6^Y-d&>5iJrk9JCSoz&(K3Wac;&{7hF2#D1L*_nS&05JJu0G@gH z8i<;G%Kh4WYP=TJ$% zX7a2CbI;7wyeE~#CQqJho{^Ek=;^rv4-XG-`p5h%-soaeZH-g|4fnKW4WiRcbY5q) zY5L}B8-v#wrn;}`Uc{BA_1C2uHmE0kk~u?NYT*4rN_m!D0MC7oFlyyB3|y2UL~U`8 z_wg}&Y$+hQ5^#S^Uh7q=R7qUvIasJYl<)E}2v?12U1jyC4o<5_cQ~+WbcaV=yv^_N zKB;8;hSZQ><wTPS?uJ46B9fo9mSc;IHW6BzZGdWU2I6 z<~w%+cOJ%UsW}1J!(oA)OZV&I5pXud}*GHm| zbN&o+Q_kW|LL8oN^}^i=L-W#GHx0OK(4hNAJT;0!ChnCEpbTI3(Ug}mbft=q;bV(H zC=qzOW$>z2t(s3NpthoR?b-^u7SO}m`KsL;2q#d2tr^q4J;8Q|gi>^ekC93?4rgo9 zx1^s*b!C6Z|1SXK&$`e*y!?Crb44sm)VewwvAAr$o=oUSvt zK1RYnhI&t5(G zgYz<=j6!o`Iqb@wuZ+4=JRA$pSD93YG?DZJ$(+=Y^ef3&1>=vO6F@cie%NX~W&3}D z8C$SO<0qW_GV z`u?Y3v}nsxiA>+t`I}TDz2<2x8pVHRbZCa>mma-6$SHV@gv?F2@%DrO&+VWPfhZu9 zJ)u|=l7$g?JmCO6c9_qvetv$8zP64(JI!X!oXKcUn^6SeF!I9{;!4V=^NfG|x`rgF z)_f?JXpZ!O3AnUXur(wtP{C$P>PONb^-y`khGhk?cz@{t%J2;&jDqbJr0$s+fca() ziuuwYrH|G)7Cm+ayju@_zEWzxYk|~dIsL4BSl*&6tv;>qF37LRQjqQ!ua`w#AU+$;)-DzE6!}%Ln;}!m_{yaBmOkeUoTs7Hx z>UNDiH}LbigZaACmn=;+ZZtC8uu)FBnGP=P9D$p6e2|rujNIJ&$j{G0UfwfYyy%9* zk#>lP9E6xHJ(1c*7c}P$WyyoMM=LLY>Ru3JtB;Sx=>09QKf?>DucCk9exozC-WdjN zo{{e%6hKlq76AU~b_3jawp*=QHGVCidL>^YGkUL`@P70y42*xKeQrj-CreLHXEa8P zIdx=!D#Bbn>D2SjTZZ6 z87|oDXtXM1-S0lfU;Mlw=4y>qJ2x8)o2iv*s5Lj;NINIpSOh^5jGuJYAMO7@clB(zvrxDfulF! zPibhu>RO}W-(nK{8VyqH)UbVVphh1>pq9;p(fXFH)u9ze+gz=0+_(X5S%rDHpO=Fj z&u+o{@l_CkhK!8WLMKnn z#3Ay2k+DN@YGFt6ep(#Bw`nHY_8g|NtLy;oelQ1liZ|r-J`Q00`t|vlK>iJ^3JSga zU3UVy#KeC@Mqddm+Vq8(0z6tHGCKJqU?uPOIRN}pRmA^Q6@m>&?MUII8l+96g`~lx zl^oWJ0MJ=g|KNuz1l&Mn# z!!z$9D*F)*zj%lPS@#k6^d=VGy#U+vqnLan39)}~pJC>lIs4S-{XX4g{TKchAo-s! zkbKXgj{iyg>Ys$Kww^&{KaxMm_q5^*uTurztc!ux82fQzVrc3&eEpbaq&19tz_jL? zxHQuSw{C4gdin~araF@rAvJ9gj&HWZz9sFkFT@6MqfKzhpdknFb(*o(fQkU{&qL+{ zz#V^=*SrtG_j4}_7`gez2>@~b`F}(3BLBNGfV|+$zxt!#%9Sgi7d7&v1GJ82lyC?D z`}FC<0pw%FmEbGjS5ifXU~d0WdAGVM;7m!@qy!b5yHthp=_H3w1<+agJB*T7Y7#Vf zS;1nnS#bSj81rj37Jl_@U+=BgFE`A5OwNCjrah;9^i^XcMvjbJdGkD0-oAh>57Oat zKOHM?rC@w&BCO9vK<`8-bk2mqcE*(04?=MF0S5IJ_$oBF9D%;q;ey7V2Ngg1Br?h8 zgrbu7@j}Vts8aGs#J8&tq2UDQrK+5vlI*rqjkHV%!h}@vfC;TNaVBIGuHRgbo40>A zVX(q5Gpv?ZM*>5}3|0iVvTE+yU-T^N(iwZ#Z{{4K4 z&K)~>YJZ>o5pOe|KEv$f`;a!BLM1xt{pE&ZsJtcuRh@jV>yMZ*s95PnF2jEq>TD*D z#x4+8$1JpQd~pXP?HP=-vEy(qej<*JHbbOlEyQWpL2^?K5U@(p2404d*L7u9@g!t8 zWx;Y7=Gm}-@KwPRL_c*AFv=#^3Ds=4YO&8K3l^dE%dfr!|4hl6NI>XYS_Oa_8XDqC z-cMftDM|VjScWND4>VA%`OJSv$4FgOiAcKYUJSp+RX_+{ELCs4yZ>VN82*WUnqzUi z$vEt7Vpq7@z{XYHl@aiL%rt+k^ZP7Mw-;SvcA(<{KUjtPqustOFx=&d2El9bo&PfQ z@LUB04UJA8){{|*Ut9Ga&~Slwz`{*C_r!EuwBhbAGu9ujJHy3QXN-S+UvFCM7WI6x zafmJ%Yc)tW)(#~IK_wYnXx5Fl0dGp`Mp~=7rmD&@vq<+;^~*{X0ibIg>z!-rbbIJr zt^KA|wK@l`tZn7jNvhZ5gV&9f#X4D9P95Xx0fRtSXm~C{U5^F$Wvv7L<7$si0q*E+ zYZF+~){ZT0zkTqTuS1FtqA{ggs-d=Rs*(0?0<3_f0*y;RCo6wH-B>I1vawFz;@fZK z_kOa;TX8akrAUBDW8|&4pNiICX^qDV%^be`ty{N>tvD{qdU-ovm3VON{0v)hB|&JV zTK@%;Mv@+r2C6(`>x$TlTT;zZdu@%*Z-!RZ>0HVS7t3dDOj^zy_}84QPVP%#vTgy) z-50}l`TYET{ri7;i7lSbXqOE&8>Sg+`=lA`B=E#U7SECiytq_jEpP7mO5X!6KYT?G zBTzUN-j3FTGI+c#?opq7D(0tB4ivbMl(g29K?9X&)DI>oIcJ~YFv35XIjM_k9XPKd z_kveex3XVQ&BE(%;GD%ekMzl>mNZ(oFq&>)V6dls8*_gb&F_9{A^k5H564_|D4`|K zj(LeD)kw$bvXS<-P3!g(4gUIfl|_vex@o zRp}bBzOsKsyz{s9C5vw@MvVBjYu722i;m;>s85XHWBD9Dx2B_CYR$QRuWLH`Kd)&Y zU_#eb;xnn1qhH?|4gtNyXCZ$Vy4RNGWU1y{Ru6fhq5s{4Z>rUbC#I%2Lu#PhyXXyR4dY`(ze*L->;C zL#!6%*;y{Y2eROrkAX!rq@#15>t8$e@VQcH*4Syco8zHtkS6YWCk^pzTQ2ZkXKE>d z^*7!i`^H<~?pyX4%ECp+$t>|Wy-)q>;FA7@wU1otV|jRSX8X8hS6jQxxM^rS=$dhl z;m?1Jtw)TI$M814$NTsgK32@3xwRbqA*-g7f4ACBzB_9>`JuMcR@8RfI<=N#z<9Zz z0Nh>Eace)(M`H*^_V+mp4wYs^>@Klp zB|*qR>fd%AY}*u-6Z*+&&E+U$Bde7o);I<4k&4+c?|O4~oqd@0mv&M;DEh$Th;NYi0;=GrQHjLz~GIiA8Aw z_`nl>MVds)B%u`XzA687;Ix{fq*e7VX0!MMy}iGlzIUi@U%%-?hXhR- zX19G@wI7|g{91L^wxQJ>f`-+y57ZsuH{#o2!4vxQ512N@cI))^9KgO^%zJt)ZFT1E zSq`2Na_$%_BDR^Zl}@Hu{g(-%cbc&L`$h`9F~-$nEwN^P>*M{pwC#VO24EjjMme9V z>su;-^Q6GvmPjG8sya)1ew!yv{fCTM*xz0+&hGCTExvTNh!^0JCtT%V9qU)r3l@bf zF**fzZan%x*VFDJV)qG*uwINlW)38K2(?suIQYURuAxshg+k<69Xv>BZvf90QL??|Ea1MhY%^&YroWxm4w+fVW2VHWusCAghCnU3Bq z=e$=h)7g-Oja>iRf`|;I`>}hdvp7M9t#l3FoF&;h|N0)l!UET%Y#^M%?TKef1f0!8 zTbCqMpM3IU6G~!~`#{8YAnf5yFE_v2LL$oT)D&*n~o|v2w3(t8+A0e%VhUsc|WM zG$6ezBY?sPwh!Q|u|x``Fubgk;lk4i@7FDM5_!5H(Y8L~NI-i2oruIVnch48X9Cb_ zT#xYY)OR*`DD7(|B)ppp;QA#y2{L;D+A60&aC?9C@-2r>sHf>HAxYS1|5y%InKi-( zlFjlJY5=;#Jq1=@DL@RJ7FlxeI{Ix+fre88s?9nAorT9R!v7N7D6Aj4n~xRb1yf!q zl?0#-pFX^2A9Zm6)q#^$vIhj-hY#{>7x>!FGHzLc+5A6Y)OIj4YCA+pZE;WZ(HQl) zzs!H$fok?akOrSXrw#K>qaW1V>VEovsyh#;td4DupLcIwsz#IC#F(N+uq81!5di^> zl_n@6RZ+3Uf`ZbUC@2ajq9SUrq5=Yuk0OE;K|yH(ii!n`Dd$*I&}Fb zFbD&3RUrry`$X(kxs57C9NwpUoA-f;UR>5u~s-r@E!f!Uih+$?mXh<9#A{QfjocU zE>@<%n$v zSs9ND6(PMp5*JS?!jC-PnP??Ex~7PAc1noaPXN{_;g8?j1IT68j*aPWGX+a}3ZKRG z5QfFm(R_k%#22fCwO_ajb_3jn-qVDYBzrj{!Tps0M)YLP+VP(|XrEk8kcIMKL?>;M zy>^NTD_d&EzsCX)`^m|x2*iJz4%*2tli7SKCAGmu0G5G!yNX&oeo&5Qk1O~s7j?A_ zSUzJTbQP^%N@wIs2;7!MO1lN0%?Y;tBLMv%m~6V!8Gu0-D-GOK?Zm$+8a-fQ}t z89#MH#)R2{`HG7oOXUlOd2Y4nu`bD$jVt>$eM`2gp-=im!=$@kr&t{` z4S9D-tnpV)`%S)f-mfbQVCW8|mJN=|s3}pzxf6;A^j5}QnuddSDkD2ti3cQ-eXj-Z zq0DbKdXVmP7r^812{wNTJ%l64J%ytQ9|?!3JWg!W6P)K63vQc?1rI-c!PU!1a8QyR zYo~Qm-%%$e&2dWFXqtvI7;x?3cG5~1;G`4xiJeB`7X)D*BY}~kV2h8r3J%Qn`js)HcOlDG80f8Guw<2U8I;DSL$5cMO7H;mQDbk#NgHGuswPeUpc1XQ=5|* z=bH`5%|;d>%L3RXWMr>}lZ|b^A3ZUC!}m1JHcd!ckMVJ9TbOv6>R4O*z3ZKMD%f#O z1rgVWVyR^ISYdx&+V zFWWFM0AEhQ{z@(0E=st5R*4dzBN4Jw3C&MN;%2TQHj^jZ;!aarmRsQ3?sgAtUj(HERmOog?ZW(z(WL>Ye&gxnKyPnYot0d9E zQZOl^=W{oT;C)=Cru3mck4Vqmjf&p27?;+A%GX)S=H+zS=G8<1w|Inb4@aVQYdpO7 z49vWpg9tn;Xfutlguu-r;*JQQ2SL~VMylZ4I~d^_2H&_mG`wgAGtbD(Te3k&MmZ39 zTZ;5YQtW@uc>>*ld<-TKSA<_df9F$}ec&QOFI6Dpu@pycNm2N`rIiIC?b0y(Np)`x zpzO3tp3Y0-tS^g*o0wRc)yeh|jji|mvc}?A>37iF?PMU#$_yXiwj2Mj55~tfN37PJ z(ww*N!U*i56w9`((c$k}MjJBlc(U3#h_3;o4~%~*Ma{^TsC^WK&@}72S_!9*DIzXd z2`9sqfO-Xl>`=za1*4E0u1FqGu_bcP%OIpjJE)pTGuX4c03QEPSR;ZbDyfI?$FZKm zP<_E=nFyXJ<_Qf1r-5uNt?3pLdXTTR)lvIO zO3Qyl@TpXhfyPAu-Uc&2_Yejem!66Z9zQGxv(0M`Lu-U3X*rj`ZQ;Q`L;!C*sYQEx zUekcRsh3bs@QJp3Z}M@OG>mI?3y|;#@S%L)E=t2hmcGD_GY@b$`vC$8$Ug|qZP%pO zOkOgx0;p@o3jiAJ6VW6F*PGPo8ps`gCP;s^hH7pr(k~C>|3|pM+mYbeVq3z@61;owL4$=NWeMOBinP-7JOnIJiO=1h(mpy z_lMG!oIfRjKHtaEFx8`g$0M7wC=IjKLm3{n%Gj|%2_E*eCM;r!Xhr0+G|Ur)W>kNv zV87q!i?nOGc53Yge61vIu^$QxQrmgJM4FD{dI_IQ7aR;{3F|k$3gDVe+JYtj z^Pu&dCxK)mv>A(fSL@~Q;Df!3(J{*p^1wr!wkIblQ(X?9P8CF1;aVGjw~FuM+}R@J zWnRIf2OK`W4m8trh2}5IUP|C*9`Jty?R3-$)(KdfSPapM?mmN6P%0*SOR#Wv5`MHl zh-;MBx%sG~E&QMA3X6KbW@7FXDzfNB83;d@4X3}Blv2h z$b$5RVcXY!Kw{v@PQhJ@+B?A4sTVx4b|H&;nOIr2P1ZiO3svcD8#4V9oA7_hf@S=B z->wRhqkUeZPaT2{2e@zP{qvSBy?fDAOsN>do(>U1*v|+kajn_cDahap=O8r}xlUF8 zb?Q!UwcOhUDj@I16VY*p6fAtaHWu^$Q6tc^{z(*>8cW*kDV4KoA}UjxC}Tqg0n zguGj@Y)ZynCuNM7@1vyjLh^ifU33zE6ax}IPAkQnykN?oQz?@rSK+xE95h)~Rn#CS z;}Vw5^ybiM{A}@3!b>ytnJAe0N&hy}55pY}LU~mv4>o!)*n#ouA~1i{_5i-N2*k(p zwxjPt|4xsCqpq$mC6_(!*5hIP6JQ5{cbsyA+po8Rf%)tOO3>7}5@ltdh-2EV0lNVn z>2)Tvy)_|m-9@I(+C-y(qpqiQ1U_1E6rb6J=zXul%p(xp==l;(5kf=3dHQt0$-+ReQVB&L|fyZPP5D(YzGnlqH2KFJRp|mQvRxtJ^_+D?QDgQy*g54!G zt<^VbfID?~ik221G(7M3Kf2zwnWlAe%|}l~ zntq?Q)m`iAIM%?g#*OxNR!Q@;Q#tY3$D@`18^^KaNfOe&|I14`We*lO=$=%f>3Eu> zPNJ$i+wp&BGsj8Ey&NW|jdapEX=JaRq(P~ekHoR;NEHKV@<_`@8Q5MY?)lglHdgrH zgAYK5C)sy@x#-6;{GFb!tK;u%tk4ZR|K#SN3y(|m0le`LCVgVRA6>`mURG9?LBCVJ z$HdC4j@tfp=i=zvkX19cI_|I!_2K`MUSkg*K2v|9U%)zjBc^eHA<1AoxTa44^yq!s1kxlbPkM-{8asuK#!uNGT4lKK z|G{M8W4~!oR#xWU=v7cq;P={*c$w;W8}*Te@QncGKQ8^L;Bm=`({~HqlCdgQgMD>3QB&rOBWYjQelxl`FQbk|*cQ+9xc5UuY zKmCNTurQFPVb_WAuMv@Wnd*2O_2GTRal&h?@KMQx^N&j|oqbRwjlGq9z{1*EUVWmv zji$PKypEoprYwB)X|C|57ccNIFBmt&&2T-&0k>}5;v%ns2M->wEgde_w;K>*dOv?J zr1l%~)(~#8+xe5h4~uS1k(&oweb0+N^S6K1RbTak7w)C<QzA4mZvzW%!0B-icoqBTafs!^h%CH#Lon+Q_Be*HlAnIIq_fd7z&ehpTionrb_5ZtT_Uv~&vfvtDR3B4ZRjHrUf+3-;P&|$=#XcXp zqU+8E_N(rDEah*y7uG)e^oA&@Ydm7AoJQD!fqmA?n6Awuap;eXMpjOF~R zjpUx!7|KUf8p@&4NWQk(P|o&k0pwHd!cFZ-(E;mHW8fFIHuav9I4XbykGS)!KP-p zP+zr7SXs7I_@q)sAeCEEvivnxZ!B-j;1g9vsxch6romWlSDk;6{DL_ahhg&631G0>gR*t2I37nNBZZ(Fr$74J)9It4K2!L^a+9~YO0CPrhv#Uf~FXhK_8 z2QwX(V#&VsF!!>1pg(tpy4aru7a%JwE<|<3ZB$lPA}=cyWl@W9D<=$(pWH?Er4`7} z&*W`nd^%>v#&&-Pz-HmSZULBfAnpCVn?k&Q)3U8L9<>lthMB`eVJTMVttsE{9kR5m zaf7xM_z&>Sg51`;M(wz!2JHkuCjm8LyUOq9YENCcjj4w(HjapBcrlH*n-tx$W5DLZ zQLn(KHyYTp4XCdJ{Y?Z?5`e;dptJ;7We;wv8Gz$Ce9(WTJZSdJ>R#kvJLzU~c;{mCJ-$*a#pHAJ$q5p|w`Rks3=OjH!0HaHP>n_=C#3 zVL{u5omj2WfG=x|zojlR<&iM&Av=+yU=b8V{UA-f}MJ_bP&D3?vE&AdyJm z=H`ar;9!3oKYpBDvcv01yi9exjXtZ-`%*oJ@RdMq0L3$lxu0l1qz8`rbfqVm}dWG08>ykreBbAym^HX5z1 zts;1QO~{Om?Fv3o>jxMx0K2so4B8fn1kh!1u%=gTR%1q z(2SG9C>cDW=KzYHZ>=5BA_W4sfk(XBRHsYNxh80TNR`C| z-2HzS6pYZi@EnrH@M)QpO#o)M|IIFer`NJVxKy=N(1E+~F7RqQ>(9WfwiKoao!HZ< zLwdFYkl>R)O5QKA)>uBc$#l?x1{3*20`dsGZz0Wk1;CJy5YP=y=+&zi7A#l*x>}5X z9Hz9il#9x|ZsEd(ybr;}#&iJCzc~KAU9o>5M;AG+z#OOLu-LT@t557hz?n!KN{MQW zOpEuuSV_AeGFDt%e2=a3@{%2KCu=53GmKG|ITP2j+>jjMiKv)xoIZUKH8nMSI%a*v zCmZ`l00juQ{LnL}Y0&RC8^(m*$J9ie6~}=` zyCl6a!1-JtBbC5YrFSviLel&duwK>%pbMZefx$=8h9F~q0ypY9O|>Ag)pqM{ve0K z)`1*8Be_fD{T|mC%9-*tqS3&aRPO+7`S&V~zEiI>l-GD-^uu4Clm!$X9v;}bbt}JA z+tJYxbTu#k94dV;og7R^bqVQ zJdVigXKX7H89w zXg0dhDS&Kjr|@<3fN%7Ie%5{;_}cs);b`XheCqe+FjZPi@HxS0fd}koyTf7DI@lU} zVCiJXy`80Ha#Avie^S~q%5~bIE^@*TUX0VaRv#+-jR?xdCm1k602=cER#~^ucJ0zroMcP_^r2<;af7+ojmk3^3tihff-SC8&VDQ$cj@iC30V`?-GBnU&ra392~!vhmS7puJCsB!@3oluzHC%oaT69v8H{6m7c3=`|;!4 z)86U7DYIsH;8jeHYigc&92g$aQvIKv=c;?Tr(j&f(|Y}r#8Q8pv`Y3sEKjxQ6M!>y zfalKuuhrD)R}nsv2E9)JR#>zF=qdt8^^+mA8H;XlZ1m`+C}o8viOL*;?a_;)Dnpwk z%IYoAD!W=^)ub#iX^c{pdmTswni;M8_A_vJLYuY>+w|^(MZ$;V8Fkro&8BVHajXwb zxdk-MMlg?9F>QZ9?`lK&>N;b2R2axTAWsaNJ-3G4}Zd*~iX(xuGi zxYAr~&5x<}Dv<2*Iv+KllPxGQ2od4pfkshL5nuBKmF9mS_U@~2R;SNhZ zSFF@`o8Rd)?3)`fXlow&Y|L$%7FSo3^9YS0XD>F4+;zU{*O(TmPJAo05?Wr#5%N5r ze%mg`;8GtPCsQoh#2^Ylz67q%RcCADfq9cwVAlA>SgdCQyIE^sZQ=%+olBKgHD5y z-4_PSZ_Y*U^=C11SAI>|-CK=~wN-Uuna3O>%(Gf&r* z$!^1`tE(e4G!*m|B)%4;G8dJ39hG?>>f2==P;<-37mCY!?9ue15o}Cn@O_o}j;uJ0 z>*fCTMlT59KRnHM*!e6CEcLeBiH){9VLxXLew(@yR;EsHx9|aF0}-?>^nS2^#P>oM zHe`El{;+NN=;e6^pLu6jOgN5;2`nuW*F*q+Hs`eO&*2k;4W02o=s}>N0mwK7>}&^(H(qY?Y83Zv6ZDP zcpX6`S+4jyQv1Ktr59Xlwte{4l?P9TZ;xwr-hUXaB~-2x3y2)^~ijgPyWwG5P$)!wA39M{5?i+s3+|4awYjF6LlzA>H(oW(3x&0RghFJ*uiYGt- O0000 diff --git a/assets/images/docs-1@2x.png b/assets/images/docs-1@2x.png index 33eeaa4fb7c5899e9170d3ff45d4bf3e44cfaa5e..1f81ecd969fc963fe40a7a897016f9db2bd0f4c7 100644 GIT binary patch delta 36574 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

s;sVlS^K)6@SmIDfUG0wWA=b@?ld{X?nrM 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 u`KiKQXx + © 2011–2017 JS Foundation and contributors
Licensed under the Creative Commons Attribution 4.0 International License. HTML end diff --git a/public/icons/docs/mocha/16.png b/public/icons/docs/mocha/16.png index b78709df4d739e52592dee614148b0de1effc2ee..9060cb2659d6a07964f5d9bd6da4a6fb865f3fef 100644 GIT binary patch delta 266 zcmdnMIE!h5WIZzj1A~Sxe=v};4DbnY1=0--4SgBz4G9kYY3{x09zfKS?%taTVt^4y zu%W@BKg+u>-3ug==GmL>&L+(+2GlHE666=mz?8!w`Omr0@7?iP*I6`8HcVcq!NS@J zl&hmH=?+#he8Yp;-XQdFH8xQ_km z>tLk|d)`*uZ}V4}rHv+L@ul2g{o3m@FhOA`@rtW~&}-gCl3*J{^8fe!~aKc2HG z-nOLR;p~T-+GaR)#BjWH7l@u&D8DdvZH`^VjrtooECws|@6Q6dgu&C*&t)C6Q$iB} D)U;-J delta 159 zcmV;Q0AT-`0PmLr)S2x3 z41_^!kQhh~ujcL)Cnuod2SEHE2YvujgHQ86JepznABG`dXXCdS!zC!*f%^GBNf@XH zVE`zQNHqYc2jK-sNRwm$NDuW4px6r(2O`DMNO3}ZjuW*8y|007S~VSvzl{#5_~ N002ovPDHLkV1i_>KEeP1 diff --git a/public/icons/docs/mocha/16@2x.png b/public/icons/docs/mocha/16@2x.png index 93e534d7a3872a1126d2394d25a4871db12683df..61f4e5a0d6b6a94db6a10bce7065c27cc327592e 100644 GIT binary patch delta 381 zcmeBUn!!9lrQRUGC&ZP3fuTFYtvAE7p`oEK-J=(V`ZGL%?4C5Yo-`1np}_$x<-T*T1~O@DBq6BfF=IV@SoV+TcL3BLX}ks)}8| z@0TsESaJ1d#@5c0K2253TYeo{+EYLExVy}RJML^6?oaGFYzzcjnUAX8?)~Jlz3Vtj zOVDGTL)?FLP39&p7vQ!!xIaRtV%L#1^ZK1kdK$Exjom8o_Ksd;rqVoV8R3@`6(%~IHqAA}|gWf*g?bc=$q~283`qiW51k(ev*K?WPv#%6-bG=MPTzUR~y}170ntzx* X&hsk!xbm(71{i~TYaZAW*pm*{PSR5NBGPY@`pF*JTUj3qPp?AK9|3~r|>0P z`M{073b6~+SYkPRPwbj7JD_Bt!owELgozt`Ei_EBcIa%$t1x)+8o7wxD Date: Sun, 29 Oct 2017 14:39:02 -0400 Subject: [PATCH 020/244] Update npm documentation (5.5.1) --- lib/docs/filters/npm/clean_html.rb | 2 +- lib/docs/filters/npm/entries.rb | 4 ++-- lib/docs/scrapers/npm.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/docs/filters/npm/clean_html.rb b/lib/docs/filters/npm/clean_html.rb index b1e2055e..86264799 100644 --- a/lib/docs/filters/npm/clean_html.rb +++ b/lib/docs/filters/npm/clean_html.rb @@ -9,7 +9,7 @@ module Docs css('meta', '.colophon').remove end - css('a.deep-link[id]').each do |node| + css('a.deep-link[id]', 'a.anchor[id]').each do |node| node.parent['id'] = node['id'] node.remove end diff --git a/lib/docs/filters/npm/entries.rb b/lib/docs/filters/npm/entries.rb index a816ea1e..6bf1374e 100644 --- a/lib/docs/filters/npm/entries.rb +++ b/lib/docs/filters/npm/entries.rb @@ -28,11 +28,11 @@ module Docs when 'files/package.json' css('#page > h2').each_with_object [] do |node, entries| next if node.content =~ /\A[A-Z]/ - entries << ["package.json: #{node.content}", node.at_css('.deep-link')['id']] + entries << ["package.json: #{node.content}", node.at_css('.anchor')['id']] end when 'misc/config' css('h2:contains("Config Settings") ~ h3').map do |node| - ["config: #{node.content}", node.at_css('.deep-link')['id']] + ["config: #{node.content}", node.at_css('.anchor')['id']] end else [] diff --git a/lib/docs/scrapers/npm.rb b/lib/docs/scrapers/npm.rb index d3e34f9e..f5211df7 100644 --- a/lib/docs/scrapers/npm.rb +++ b/lib/docs/scrapers/npm.rb @@ -2,7 +2,7 @@ module Docs class Npm < UrlScraper self.name = 'npm' self.type = 'npm' - self.release = '5.4.1' + self.release = '5.5.1' self.base_url = 'https://docs.npmjs.com/' self.force_gzip = true self.links = { From 6fe25a4387266222d2baaf2648289b9f84d401c6 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:44:11 -0400 Subject: [PATCH 021/244] Update pandas documentation (0.21.0) --- lib/docs/scrapers/pandas.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/docs/scrapers/pandas.rb b/lib/docs/scrapers/pandas.rb index 3688dac2..1ab3692d 100644 --- a/lib/docs/scrapers/pandas.rb +++ b/lib/docs/scrapers/pandas.rb @@ -20,8 +20,13 @@ module Docs Licensed under the 3-clause BSD License. HTML + version '0.21' do + self.release = '0.21.0' + self.base_url = "http://pandas.pydata.org/pandas-docs/version/#{self.release}/" + end + version '0.20' do - self.release = '0.20.2' + self.release = '0.20.3' self.base_url = "http://pandas.pydata.org/pandas-docs/version/#{self.release}/" end From db293a30c4875e75fb40f726cbd96587078af2fc Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:44:35 -0400 Subject: [PATCH 022/244] Update PHPUnit documentation (6.4) --- lib/docs/scrapers/phpunit.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/phpunit.rb b/lib/docs/scrapers/phpunit.rb index cde50077..aba16947 100644 --- a/lib/docs/scrapers/phpunit.rb +++ b/lib/docs/scrapers/phpunit.rb @@ -24,7 +24,7 @@ module Docs HTML version '6' do - self.release = '6.3' + self.release = '6.4' self.base_url = "https://phpunit.de/manual/#{release}/en/" end From 7a0fa9967ea8afaf0d73bcd04b370166c9397b40 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:47:35 -0400 Subject: [PATCH 023/244] Update Q documentation (1.5.1) --- lib/docs/scrapers/q.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/q.rb b/lib/docs/scrapers/q.rb index 83595757..bb66c156 100644 --- a/lib/docs/scrapers/q.rb +++ b/lib/docs/scrapers/q.rb @@ -1,7 +1,7 @@ module Docs class Q < Github self.name = 'Q' - self.release = '1.5.0' + self.release = '1.5.1' self.base_url = 'https://github.com/kriskowal/q/wiki/' self.root_path = 'API-Reference' self.links = { From e3572e03902014292685415c78d4c0b23528f1d9 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:47:51 -0400 Subject: [PATCH 024/244] Update Ramda documentation (0.25.0) --- lib/docs/scrapers/ramda.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/ramda.rb b/lib/docs/scrapers/ramda.rb index 3fe0bb06..09ff46c8 100644 --- a/lib/docs/scrapers/ramda.rb +++ b/lib/docs/scrapers/ramda.rb @@ -1,7 +1,7 @@ module Docs class Ramda < UrlScraper self.type = 'ramda' - self.release = '0.24.1' + self.release = '0.25.0' self.base_url = "http://ramdajs.com/#{release}/docs/" self.links = { home: 'http://ramdajs.com/', From 76b741d0cbb0773b6d1ed275acfc28a8e3e2d65e Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:51:57 -0400 Subject: [PATCH 025/244] Update Rust documentation (1.21.0) --- lib/docs/scrapers/rust.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/rust.rb b/lib/docs/scrapers/rust.rb index 4effca80..b4e89b66 100644 --- a/lib/docs/scrapers/rust.rb +++ b/lib/docs/scrapers/rust.rb @@ -1,7 +1,7 @@ module Docs class Rust < UrlScraper self.type = 'rust' - self.release = '1.20.0' + self.release = '1.21.0' self.base_url = 'https://doc.rust-lang.org/' self.root_path = 'book/first-edition/index.html' self.initial_paths = %w( From 457d8209b6fe8d2306fc9a2f2f9370345a0e0a49 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:52:10 -0400 Subject: [PATCH 026/244] Update Sass documentation (3.5.3) --- lib/docs/scrapers/sass.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/sass.rb b/lib/docs/scrapers/sass.rb index 39131ffc..244a88e7 100644 --- a/lib/docs/scrapers/sass.rb +++ b/lib/docs/scrapers/sass.rb @@ -1,7 +1,7 @@ module Docs class Sass < UrlScraper self.type = 'yard' - self.release = '3.5.1' + self.release = '3.5.3' self.base_url = 'http://sass-lang.com/documentation/' self.root_path = 'file.SASS_REFERENCE.html' self.links = { From f67bce9dce4a43bf82775c7d7a9625be6befcee9 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 14:52:57 -0400 Subject: [PATCH 027/244] Update scikit-image documentation (0.13.1) --- lib/docs/scrapers/scikit_image.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/scikit_image.rb b/lib/docs/scrapers/scikit_image.rb index d6b39eb4..d229f6bb 100644 --- a/lib/docs/scrapers/scikit_image.rb +++ b/lib/docs/scrapers/scikit_image.rb @@ -3,7 +3,7 @@ module Docs self.name = 'scikit-image' self.slug = 'scikit_image' self.type = 'sphinx' - self.release = '0.13.0' + self.release = '0.13.1' self.base_url = 'http://scikit-image.org/docs/0.13.x/' self.links = { home: 'http://scikit-image.org/', From c1e78ae9a89528b083c767317282118667c11fa0 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 15:01:45 -0400 Subject: [PATCH 028/244] Update scikit-learn documentation (0.19.1) --- lib/docs/filters/scikit_learn/entries.rb | 1 + lib/docs/scrapers/scikit_learn.rb | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/docs/filters/scikit_learn/entries.rb b/lib/docs/filters/scikit_learn/entries.rb index bef8a77b..9bb2f1c9 100644 --- a/lib/docs/filters/scikit_learn/entries.rb +++ b/lib/docs/filters/scikit_learn/entries.rb @@ -27,6 +27,7 @@ module Docs type = at_css('dt > .descclassname').content.strip type.remove! 'sklearn.' type.remove! %r{\.\z} + type = 'sklearn' if type.blank? type elsif subpath.start_with?('tutorial') 'Tutorials' diff --git a/lib/docs/scrapers/scikit_learn.rb b/lib/docs/scrapers/scikit_learn.rb index b6e0bca3..01b89e3b 100644 --- a/lib/docs/scrapers/scikit_learn.rb +++ b/lib/docs/scrapers/scikit_learn.rb @@ -3,9 +3,10 @@ module Docs self.name = 'scikit-learn' self.slug = 'scikit_learn' self.type = 'sphinx' - self.release = '0.19' + self.release = '0.19.1' self.base_url = 'http://scikit-learn.org/stable/' self.root_path = 'documentation.html' + self.force_gzip = true self.links = { home: 'http://scikit-learn.org/', code: 'https://github.com/scikit-learn/scikit-learn' From b13081ba594355326e0fc6f608f5a006f9d7a5a2 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 15:03:02 -0400 Subject: [PATCH 029/244] Update TypeScript documentation (2.6.0) --- lib/docs/scrapers/typescript.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/typescript.rb b/lib/docs/scrapers/typescript.rb index 5ec6d89e..755adb0f 100644 --- a/lib/docs/scrapers/typescript.rb +++ b/lib/docs/scrapers/typescript.rb @@ -2,7 +2,7 @@ module Docs class Typescript < UrlScraper self.name = 'TypeScript' self.type = 'typescript' - self.release = '2.5.0' + self.release = '2.6.0' self.base_url = 'https://www.typescriptlang.org/docs/' self.root_path = 'tutorial.html' self.links = { From c76161b1f765cb4de4f2306a439efda001a72ecc Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 15:03:43 -0400 Subject: [PATCH 030/244] Update Vue.js documentation (2.5.2) --- lib/docs/scrapers/vue.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/vue.rb b/lib/docs/scrapers/vue.rb index fc002775..8e947049 100644 --- a/lib/docs/scrapers/vue.rb +++ b/lib/docs/scrapers/vue.rb @@ -20,7 +20,7 @@ module Docs HTML version '2' do - self.release = '2.4.1' + self.release = '2.5.2' self.base_url = 'https://vuejs.org/v2/' self.root_path = 'guide/index.html' self.initial_paths = %w(api/) From a2c0a508940a056562f8bda49498797ecf346f10 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 15:07:41 -0400 Subject: [PATCH 031/244] Update webpack documentation (3.8.1) --- lib/docs/filters/webpack/entries.rb | 4 ++-- lib/docs/scrapers/webpack.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/docs/filters/webpack/entries.rb b/lib/docs/filters/webpack/entries.rb index 2e019685..cd943a72 100644 --- a/lib/docs/filters/webpack/entries.rb +++ b/lib/docs/filters/webpack/entries.rb @@ -26,9 +26,9 @@ module Docs next if node.previous.try(:content).present? entries << [node.content, node.parent['id']] end - elsif slug.start_with?('api') && slug != 'api/plugins/parser' + elsif slug.start_with?('api') && slug != 'api/parser' css('.header[id] code').each_with_object [] do |node, entries| - next if node.previous.try(:content).present? + next if node.previous.try(:content).present? || node.next.try(:content).present? name = node.content.sub(/\(.*\)/, '()') name.prepend "#{self.name.split(':').first}: " entries << [name, node.parent['id']] diff --git a/lib/docs/scrapers/webpack.rb b/lib/docs/scrapers/webpack.rb index 52ed107d..02f1e599 100644 --- a/lib/docs/scrapers/webpack.rb +++ b/lib/docs/scrapers/webpack.rb @@ -4,7 +4,7 @@ module Docs self.type = 'webpack' version do - self.release = '3.6.0' + self.release = '3.8.1' self.base_url = 'https://webpack.js.org/' self.root_path = 'guides/' self.initial_paths = %w( From 621dd8ea3a04f26e69755718d17ae5aee0bb082c Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 15:07:58 -0400 Subject: [PATCH 032/244] Update Yarn documentation (1.2.1) --- lib/docs/scrapers/yarn.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/yarn.rb b/lib/docs/scrapers/yarn.rb index bfd68497..124459fe 100644 --- a/lib/docs/scrapers/yarn.rb +++ b/lib/docs/scrapers/yarn.rb @@ -1,7 +1,7 @@ module Docs class Yarn < UrlScraper self.type = 'yarn' - self.release = '1.1.0' + self.release = '1.2.1' self.base_url = 'https://yarnpkg.com/en/docs/' self.links = { home: 'https://yarnpkg.com/', From e66d0c810b40354cf87c1815fd1b43f4d82bb676 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 15:18:07 -0400 Subject: [PATCH 033/244] Update Symfony documentation (3.3.10) --- lib/docs/scrapers/symfony.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/docs/scrapers/symfony.rb b/lib/docs/scrapers/symfony.rb index bd32308e..fed9a45a 100644 --- a/lib/docs/scrapers/symfony.rb +++ b/lib/docs/scrapers/symfony.rb @@ -27,7 +27,7 @@ module Docs HTML version '3.3' do - self.release = '3.3.6' + self.release = '3.3.10' self.base_url = "http://api.symfony.com/#{version}/" end @@ -47,12 +47,12 @@ module Docs end version '2.8' do - self.release = '2.8.26' + self.release = '2.8.28' self.base_url = "http://api.symfony.com/#{version}/" end version '2.7' do - self.release = '2.7.33' + self.release = '2.7.35' self.base_url = "http://api.symfony.com/#{version}/" end end From 0342854a1fb0fdeb7632ffe43f9e4c8e3edf414a Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 29 Oct 2017 15:19:35 -0400 Subject: [PATCH 034/244] Update SQLite documentation (3.21.0) --- lib/docs/scrapers/sqlite.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/sqlite.rb b/lib/docs/scrapers/sqlite.rb index d4b12a3b..1f54bfdf 100644 --- a/lib/docs/scrapers/sqlite.rb +++ b/lib/docs/scrapers/sqlite.rb @@ -2,7 +2,7 @@ module Docs class Sqlite < FileScraper self.name = 'SQLite' self.type = 'sqlite' - self.release = '3.20.1' + self.release = '3.21.0' self.dir = '/Users/Thibaut/DevDocs/Docs/sqlite/' self.base_url = 'https://sqlite.org/' self.root_path = 'docs.html' From e7048a87f67aabdd72249a4e953114ecfb5e0455 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 11:40:21 -0500 Subject: [PATCH 035/244] Update PostgreSQL documentation (10.1) --- assets/stylesheets/pages/_postgres.scss | 17 ++++--- lib/docs/filters/postgresql/clean_html.rb | 39 +++++++++++++--- lib/docs/filters/postgresql/entries.rb | 44 ++++++++++--------- .../filters/postgresql/extract_metadata.rb | 18 ++++---- .../postgresql/normalize_class_names.rb | 13 ++++++ lib/docs/scrapers/postgresql.rb | 17 +++++-- 6 files changed, 105 insertions(+), 43 deletions(-) create mode 100644 lib/docs/filters/postgresql/normalize_class_names.rb diff --git a/assets/stylesheets/pages/_postgres.scss b/assets/stylesheets/pages/_postgres.scss index 487f984d..69e202c1 100644 --- a/assets/stylesheets/pages/_postgres.scss +++ b/assets/stylesheets/pages/_postgres.scss @@ -1,19 +1,24 @@ ._postgres { padding-left: 1rem; - h1, h1 ~ p, h1 ~ pre, h1 ~ blockquote, h2, .NAVFOOTER { margin-left: -1rem; } + h1, h1 ~ p, h1 ~ pre, h1 ~ ul, h1 ~ blockquote, h2, .navfooter { margin-left: -1rem; } h2 { @extend %block-heading; } - .VARIABLELIST dt { @extend %block-label, %label-blue; } + .variablelist dt { @extend %block-label, %label-blue; } - blockquote.NOTE, blockquote.IMPORTANT, blockquote.TIP, blockquote.CAUTION { @extend %note; } - blockquote.TIP { @extend %note-green; } - blockquote.CAUTION { @extend %note-orange; } + blockquote.note, blockquote.important, blockquote.tip, blockquote.caution { @extend %note; } + blockquote.tip { @extend %note-green; } + blockquote.caution { @extend %note-orange; } + + blockquote > h3 { + font-size: .875rem; + margin: 0 0 .25rem; + } p > code { @extend %label; } p.c2 { font-weight: $boldFontWeight; } - .NAVFOOTER > table { width: 100%; } + .navfooter > table { width: 100%; } td[align=center] { text-align: center; } td[align=right] { text-align: right; } } diff --git a/lib/docs/filters/postgresql/clean_html.rb b/lib/docs/filters/postgresql/clean_html.rb index 40f0a35b..b3da126c 100644 --- a/lib/docs/filters/postgresql/clean_html.rb +++ b/lib/docs/filters/postgresql/clean_html.rb @@ -13,18 +13,22 @@ module Docs def other @doc = at_css('#docContent') - css('.NAVHEADER', 'hr', '.NAVFOOTER a[accesskey="H"]').remove + css('.navheader', 'hr', '.navfooter a[accesskey="H"]').remove + + unless at_css('h1') + at_css('.refnamediv h2, .titlepage h2').name = 'h1' + end css('a[name]').each do |node| node.parent['id'] = node['name'] node.before(node.children).remove end - css('div.SECT1', 'pre > kbd', 'tt > code', 'h1 > tt', '> .CHAPTER', 'div.NOTE', '.APPENDIX').each do |node| + css('div.sect1', '.refentry', '.refnamediv', '.refentrytitle', '.refsynopsisdiv', 'pre > kbd', 'tt > code', 'h1 > tt', '> .chapter', '.appendix', '.titlepage', 'div:not([class]):not([id])', 'br', 'a.indexterm', 'acronym', '.productname', 'div.itemizedlist', 'span.sect2', 'span.application', 'em.replaceable', 'span.term').each do |node| node.before(node.children).remove end - css('div.CAUTION table.CAUTION').each do |node| + css('div.caution table.caution').each do |node| parent = node.parent title = node.at_css('.c2, .c3, .c4, .c5').content node.replace(node.css('p')) @@ -43,11 +47,27 @@ module Docs node.remove_attribute 'valign' end + css('.sect2 > h3').each do |node| + node.name = 'h2' + end + + css('.sect3 > h4').each do |node| + node.name = 'h3' + end + css('tt').each do |node| node.name = 'code' end - css('.REFSYNOPSISDIV > p').each do |node| + css('div.note', 'div.important', 'div.tip', 'div.caution').each do |node| + if node.at_css('blockquote') + node.before(node.children).remove + else + node.name = 'blockquote' + end + end + + css('.refsynopsisdiv > p').each do |node| node.name = 'pre' node.content = node.content end @@ -56,9 +76,18 @@ module Docs node.before(node.children).remove end - css('pre.SYNOPSIS', 'pre.PROGRAMLISTING').each do |node| + css('code').each do |node| + node.inner_html = node.inner_html.gsub(/\s*\n\s*/, ' ') + end + + css('pre.synopsis', 'pre.programlisting').each do |node| node['data-language'] = 'sql' end + + css('h1', 'ul', 'li', 'pre').each do |node| + node.remove_attribute 'class' + node.remove_attribute 'style' + end end end end diff --git a/lib/docs/filters/postgresql/entries.rb b/lib/docs/filters/postgresql/entries.rb index e222f310..4ddac456 100644 --- a/lib/docs/filters/postgresql/entries.rb +++ b/lib/docs/filters/postgresql/entries.rb @@ -90,33 +90,33 @@ module Docs return config_additional_entries if type && type.include?('Configuration') return data_types_additional_entries if type == 'Data Types' return command_additional_entries if type == 'Commands' - return get_heading_entries('h3[id]') if slug == 'functions-xml' + return get_heading_entries('h3[id], .sect3[id] > h3:first-child') if slug == 'functions-xml' - entries = get_heading_entries('h2[id]') + entries = get_heading_entries('h2[id], .sect2[id] > h2:first-child') case slug when 'queries-union' - entries.concat get_custom_entries('p > .LITERAL:first-child') + entries.concat get_custom_entries('p > .literal:first-child') when 'queries-table-expressions' - entries.concat get_heading_entries('h3[id]') - entries.concat get_custom_entries('dt > .LITERAL:first-child') + entries.concat get_heading_entries('h3[id], .sect3[id] > h3:first-child') + entries.concat get_custom_entries('dt > .literal:first-child') when 'functions-logical' entries.concat get_custom_entries('> table td:first-child > code') when 'functions-formatting' entries.concat get_custom_entries('#FUNCTIONS-FORMATTING-TABLE td:first-child > code') when 'functions-admin' - entries.concat get_custom_entries('.TABLE td:first-child > code') + entries.concat get_custom_entries('.table td:first-child > code') when 'functions-string' entries.concat get_custom_entries('> div[id^="FUNC"] td:first-child > code') entries.concat get_custom_entries('> div[id^="FORMAT"] td:first-child > code') else if type && type.start_with?('Functions') - entries.concat get_custom_entries('> .TABLE td:first-child > code.LITERAL:first-child') - entries.concat get_custom_entries('> .TABLE td:first-child > code.FUNCTION:first-child') - entries.concat get_custom_entries('> .TABLE td:first-child > code:not(.LITERAL):first-child + code.LITERAL') - entries.concat get_custom_entries('> .TABLE td:first-child > p > code.LITERAL:first-child') - entries.concat get_custom_entries('> .TABLE td:first-child > p > code.FUNCTION:first-child') - entries.concat get_custom_entries('> .TABLE td:first-child > p > code:not(.LITERAL):first-child + code.LITERAL') + entries.concat get_custom_entries('> .table td:first-child > code.literal:first-child') + entries.concat get_custom_entries('> .table td:first-child > code.function:first-child') + entries.concat get_custom_entries('> .table td:first-child > code:not(.literal):first-child + code.literal') + entries.concat get_custom_entries('> .table td:first-child > p > code.literal:first-child') + entries.concat get_custom_entries('> .table td:first-child > p > code.function:first-child') + entries.concat get_custom_entries('> .table td:first-child > p > code:not(.literal):first-child + code.literal') if slug == 'functions-comparison' && !at_css('#FUNCTIONS-COMPARISON-PRED-TABLE') # before 9.6 entries.concat %w(IS NULL BETWEEN DISTINCT\ FROM).map { |name| ["#{self.name}: #{name}"] } end @@ -127,8 +127,8 @@ module Docs end def config_additional_entries - css('.VARIABLELIST dt[id]').map do |node| - name = node.at_css('.VARNAME').content + css('.variablelist dt[id]').map do |node| + name = node.at_css('.varname').content ["Config: #{name}", node['id']] end end @@ -136,27 +136,27 @@ module Docs def data_types_additional_entries selector = case slug when 'rangetypes' - 'li > p > .TYPE:first-child' + 'li > p > .type:first-child' when 'datatype-textsearch' - '.SECT2 > .TYPE' + '.title > .type, .sect2 > .type' else - '.CALSTABLE td:first-child > .TYPE' + '.table-contents td:first-child > .type, .calstable td:first-child > .type' end get_custom_entries(selector) end def command_additional_entries - css('.REFSECT2[id^="SQL"]').each_with_object([]) do |node, entries| + css('.refsect2[id^="SQL"]').each_with_object([]) do |node, entries| next unless heading = node.at_css('h3') next unless heading.content.strip =~ /[A-Z_\-]+ Clause/ - name = heading.at_css('.LITERAL').content + name = heading.at_css('.literal').content name.prepend "#{self.name} ... " entries << [name, node['id']] end end def include_default_entry? - !initial_page? && !at_css('.TOC') && type + !initial_page? && (!at_css('.toc') || at_css('.sect2, .variablelist, .refsect1')) && type end SKIP_ENTRIES_SLUGS = [ @@ -199,7 +199,9 @@ module Docs css(selector).each_with_object([]) do |node, entries| name = node.content clean_heading_name(name) - entries << ["#{additional_entry_prefix}: #{name}", node['id']] unless skip_heading?(name) + id = node['id'] || node.parent['id'] + raise "missing ids for selector #{selector}" unless id + entries << ["#{additional_entry_prefix}: #{name}", id] unless skip_heading?(name) end end diff --git a/lib/docs/filters/postgresql/extract_metadata.rb b/lib/docs/filters/postgresql/extract_metadata.rb index ba313dca..260d05d0 100644 --- a/lib/docs/filters/postgresql/extract_metadata.rb +++ b/lib/docs/filters/postgresql/extract_metadata.rb @@ -8,19 +8,21 @@ module Docs end def extract_up_path - if node = at_css('.NAVHEADER a[accesskey="U"]') + if node = at_css('.navheader a[accesskey="u"], .navheader a[accesskey="U"]') result[:pg_up_path] = node['href'] end end def extract_chapter - return unless text = at_css('.NAVHEADER td[align="center"]').content - if match = text.match(/\AChapter (\d+)\. (.+)\z/) - result[:pg_chapter] = match[1].to_i - result[:pg_chapter_name] = match[2].strip - elsif match = text.match(/\AAppendix ([A-Z])\. (.+)\z/) - result[:pg_appendix] = match[1] - result[:pg_appendix_name] = match[2].strip + css('.navheader td[align="center"], .navheader th[align="center"]').each do |node| + text = node.content.strip + if match = text.match(/\AChapter (\d+)\. (.+)\z/) + result[:pg_chapter] = match[1].to_i + result[:pg_chapter_name] = match[2].strip + elsif match = text.match(/\AAppendix ([A-Z])\. (.+)\z/) + result[:pg_appendix] = match[1] + result[:pg_appendix_name] = match[2].strip + end end end end diff --git a/lib/docs/filters/postgresql/normalize_class_names.rb b/lib/docs/filters/postgresql/normalize_class_names.rb new file mode 100644 index 00000000..01c6cfa7 --- /dev/null +++ b/lib/docs/filters/postgresql/normalize_class_names.rb @@ -0,0 +1,13 @@ +module Docs + class Postgresql + class NormalizeClassNamesFilter < Filter + def call + doc.css('*').each do |node| + node['class'] = node['class'].downcase if node['class'].present? + end + + doc + end + end + end +end diff --git a/lib/docs/scrapers/postgresql.rb b/lib/docs/scrapers/postgresql.rb index cb810c6b..5cb71f03 100644 --- a/lib/docs/scrapers/postgresql.rb +++ b/lib/docs/scrapers/postgresql.rb @@ -55,19 +55,30 @@ module Docs Licensed under the PostgreSQL License. HTML + version '10' do + self.release = '10.1' + self.base_url = 'https://www.postgresql.org/docs/10/static/' + end + version '9.6' do - self.release = '9.6.5' + self.release = '9.6.6' self.base_url = 'https://www.postgresql.org/docs/9.6/static/' + + html_filters.insert_before 'postgresql/extract_metadata', 'postgresql/normalize_class_names' end version '9.5' do - self.release = '9.5.9' + self.release = '9.5.10' self.base_url = 'https://www.postgresql.org/docs/9.5/static/' + + html_filters.insert_before 'postgresql/extract_metadata', 'postgresql/normalize_class_names' end version '9.4' do - self.release = '9.4.14' + self.release = '9.4.15' self.base_url = 'https://www.postgresql.org/docs/9.4/static/' + + html_filters.insert_before 'postgresql/extract_metadata', 'postgresql/normalize_class_names' end end end From 8a41604685aa18e9a9e7cd86c533f0fddeaddde1 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 11:41:31 -0500 Subject: [PATCH 036/244] Update gems --- Gemfile.lock | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index ec112f54..cd08f432 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,21 +6,21 @@ GEM i18n (~> 0.7) minitest (~> 5.1) tzinfo (~> 1.1) - backports (3.9.1) - better_errors (2.3.0) + backports (3.10.3) + better_errors (2.4.0) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) - browser (2.5.1) + browser (2.5.2) coderay (1.1.2) coffee-script (2.4.1) coffee-script-source execjs coffee-script-source (1.12.2) concurrent-ruby (1.0.5) - daemons (1.2.4) - erubi (1.6.1) - ethon (0.10.1) + daemons (1.2.5) + erubi (1.7.0) + ethon (0.11.0) ffi (>= 1.3.0) eventmachine (1.2.5) execjs (2.7.0) @@ -31,14 +31,15 @@ GEM html-pipeline (2.7.1) activesupport (>= 2) nokogiri (>= 1.4) - i18n (0.8.6) + i18n (0.9.1) + concurrent-ruby (~> 1.0) image_optim (0.25.0) exifr (~> 1.2, >= 1.2.2) fspath (~> 3.0) image_size (~> 1.5) in_threads (~> 1.3) progress (~> 3.0, >= 3.0.1) - image_optim_pack (0.5.0.20171001) + image_optim_pack (0.5.0.20171101) fspath (>= 2.1, < 4) image_optim (~> 0.19) image_size (1.5.0) @@ -51,11 +52,11 @@ GEM nokogiri (1.8.1) mini_portile2 (~> 2.3.0) options (2.3.2) - progress (3.3.1) + progress (3.4.0) progress_bar (1.1.0) highline (~> 1.6) options (~> 2.3.0) - pry (0.11.1) + pry (0.11.2) coderay (~> 1.1.0) method_source (~> 0.9.0) rack (2.0.3) @@ -63,12 +64,12 @@ GEM rack rack-test (0.7.0) rack (>= 1.0, < 3) - rake (12.1.0) + rake (12.2.1) rb-fsevent (0.10.2) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) rr (1.2.1) - sass (3.5.2) + sass (3.5.3) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) @@ -97,15 +98,15 @@ GEM thor (0.20.0) thread_safe (0.3.6) tilt (2.0.8) - tty-pager (0.9.0) - tty-screen (~> 0.5.0) + tty-pager (0.10.0) + tty-screen (~> 0.6.0) tty-which (~> 0.3.0) verse (~> 0.5.0) - tty-screen (0.5.0) + tty-screen (0.6.2) tty-which (0.3.0) typhoeus (1.3.0) ethon (>= 0.9.0) - tzinfo (1.2.3) + tzinfo (1.2.4) thread_safe (~> 0.1) uglifier (3.2.0) execjs (>= 0.3.0, < 3) @@ -115,7 +116,7 @@ GEM verse (0.5.0) unicode-display_width (~> 1.1.0) unicode_utils (~> 1.4.0) - yajl-ruby (1.3.0) + yajl-ruby (1.3.1) PLATFORMS ruby From b55a2946e94c4d6ceeeb8c18a4e739152ab38e27 Mon Sep 17 00:00:00 2001 From: Felix Yan Date: Sun, 22 Oct 2017 00:17:12 +0800 Subject: [PATCH 037/244] Fix a typo in javascripts/lib/util.coffee --- assets/javascripts/lib/util.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/javascripts/lib/util.coffee b/assets/javascripts/lib/util.coffee index 59e2a1a1..058106fd 100644 --- a/assets/javascripts/lib/util.coffee +++ b/assets/javascripts/lib/util.coffee @@ -124,7 +124,7 @@ $.empty = (el) -> return # Calls the function while the element is off the DOM to avoid triggering -# unecessary reflows and repaints. +# unnecessary reflows and repaints. $.batchUpdate = (el, fn) -> parent = el.parentNode sibling = el.nextSibling From 131524ab7fb037badb69c51a4a5b7e39d25a5882 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 11:42:57 -0500 Subject: [PATCH 038/244] Update React documentation (16.1.0) --- lib/docs/scrapers/react.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/react.rb b/lib/docs/scrapers/react.rb index 4506f019..11872e5e 100644 --- a/lib/docs/scrapers/react.rb +++ b/lib/docs/scrapers/react.rb @@ -2,7 +2,7 @@ module Docs class React < UrlScraper self.name = 'React' self.type = 'simple' - self.release = '16.0.0' + self.release = '16.1.0' self.base_url = 'https://reactjs.org/docs/' self.root_path = 'hello-world.html' self.links = { From a84935631c461effbfceb7a1ee5a64cad1543c6d Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 11:43:29 -0500 Subject: [PATCH 039/244] Update Marionette.js documentation (3.5.1) --- lib/docs/scrapers/marionette.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/marionette.rb b/lib/docs/scrapers/marionette.rb index 0e27d349..fbcc71cf 100644 --- a/lib/docs/scrapers/marionette.rb +++ b/lib/docs/scrapers/marionette.rb @@ -19,7 +19,7 @@ module Docs HTML version '3' do - self.release = '3.4.3' + self.release = '3.5.1' self.base_url = "https://marionettejs.com/docs/v#{release}/" html_filters.push 'marionette/entries_v3' From d9716ab04834fcbd103f19f6514147c7653a5221 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 11:45:18 -0500 Subject: [PATCH 040/244] Update Mongoose documentation (4.13.1) --- lib/docs/scrapers/mongoose.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/docs/scrapers/mongoose.rb b/lib/docs/scrapers/mongoose.rb index 3b70c150..d6ca8a01 100644 --- a/lib/docs/scrapers/mongoose.rb +++ b/lib/docs/scrapers/mongoose.rb @@ -2,10 +2,11 @@ module Docs class Mongoose < UrlScraper self.name = 'Mongoose' self.type = 'mongoose' - self.release = '4.12.0' + self.release = '4.13.1' self.base_url = 'http://mongoosejs.com/docs/' self.root_path = 'index.html' self.initial_paths = %w(guide.html api.html) + self.force_gzip = true self.links = { home: 'http://mongoosejs.com/', code: 'https://github.com/Automattic/mongoose' From f90e3214e0dd35fb55f3c17c5c2cb7f99a28afab Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 11:46:28 -0500 Subject: [PATCH 041/244] Update Flow documentation (0.59.0) --- lib/docs/scrapers/flow.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/flow.rb b/lib/docs/scrapers/flow.rb index 53ee0406..e184a591 100644 --- a/lib/docs/scrapers/flow.rb +++ b/lib/docs/scrapers/flow.rb @@ -1,7 +1,7 @@ module Docs class Flow < UrlScraper self.type = 'flow' - self.release = '0.57.3' + self.release = '0.59.0' self.base_url = 'https://flow.org/en/docs/' self.links = { home: 'https://flow.org/', From 976d7a836c75911314da4569d44b70d9c80ffc90 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 11:50:07 -0500 Subject: [PATCH 042/244] Update Node.js documentation (9.1.0) --- lib/docs/scrapers/node.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/docs/scrapers/node.rb b/lib/docs/scrapers/node.rb index c8cc3105..fc725779 100644 --- a/lib/docs/scrapers/node.rb +++ b/lib/docs/scrapers/node.rb @@ -23,17 +23,22 @@ module Docs HTML version do - self.release = '8.8.1' + self.release = '9.1.0' + self.base_url = 'https://nodejs.org/dist/latest-v9.x/docs/api/' + end + + version '8 LTS' do + self.release = '8.9.1' self.base_url = 'https://nodejs.org/dist/latest-v8.x/docs/api/' end version '6 LTS' do - self.release = '6.11.5' + self.release = '6.12.0' self.base_url = 'https://nodejs.org/dist/latest-v6.x/docs/api/' end version '4 LTS' do - self.release = '4.8.5' + self.release = '4.8.6' self.base_url = 'https://nodejs.org/dist/latest-v4.x/docs/api/' end end From acd06aaa68c9aecf8e76d542d5f6e20f2a58d3b1 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 11:50:42 -0500 Subject: [PATCH 043/244] Update Async documentation (2.6.0) --- lib/docs/scrapers/async.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/async.rb b/lib/docs/scrapers/async.rb index fad92975..2969bd01 100644 --- a/lib/docs/scrapers/async.rb +++ b/lib/docs/scrapers/async.rb @@ -1,7 +1,7 @@ module Docs class Async < UrlScraper self.type = 'async' - self.release = '2.5.0' + self.release = '2.6.0' self.base_url = 'https://caolan.github.io/async/' self.root_path = 'docs.html' self.links = { From f432e2149daa9a1d7e1f00cc1a8badd354703143 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 11:51:11 -0500 Subject: [PATCH 044/244] Update Vagrant documentation (2.0.1) --- lib/docs/scrapers/vagrant.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/vagrant.rb b/lib/docs/scrapers/vagrant.rb index 0034f964..4b84eae2 100644 --- a/lib/docs/scrapers/vagrant.rb +++ b/lib/docs/scrapers/vagrant.rb @@ -2,7 +2,7 @@ module Docs class Vagrant < UrlScraper self.name = 'Vagrant' self.type = 'vagrant' - self.release = '2.0.0' + self.release = '2.0.1' self.base_url = 'https://www.vagrantup.com/docs/' self.root_path = 'index.html' self.links = { From 00507c24530c4fcc207acd36a90242cfeb88bf74 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 11:51:25 -0500 Subject: [PATCH 045/244] Update Yarn documentation (1.3.2) --- lib/docs/scrapers/yarn.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/yarn.rb b/lib/docs/scrapers/yarn.rb index 124459fe..8231ff52 100644 --- a/lib/docs/scrapers/yarn.rb +++ b/lib/docs/scrapers/yarn.rb @@ -1,7 +1,7 @@ module Docs class Yarn < UrlScraper self.type = 'yarn' - self.release = '1.2.1' + self.release = '1.3.2' self.base_url = 'https://yarnpkg.com/en/docs/' self.links = { home: 'https://yarnpkg.com/', From 391a1644df41b2557264ce1abae8e038698535cf Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 11:51:42 -0500 Subject: [PATCH 046/244] Update Sinon.JS documentation (4.1.2) --- lib/docs/scrapers/sinon.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/sinon.rb b/lib/docs/scrapers/sinon.rb index 9489c81d..9822a00f 100644 --- a/lib/docs/scrapers/sinon.rb +++ b/lib/docs/scrapers/sinon.rb @@ -19,7 +19,7 @@ module Docs HTML version '4' do - self.release = '4.0.1' + self.release = '4.1.2' self.base_url = "http://sinonjs.org/releases/v#{release}/" end From 187e09ed93a6eddb75eff502b5a96c918803994c Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 13:11:57 -0500 Subject: [PATCH 047/244] Update Angular documentation (5.0.1) --- lib/docs/scrapers/angular.rb | 68 +++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/lib/docs/scrapers/angular.rb b/lib/docs/scrapers/angular.rb index 8ff7c728..17fd32dc 100644 --- a/lib/docs/scrapers/angular.rb +++ b/lib/docs/scrapers/angular.rb @@ -15,29 +15,13 @@ module Docs Licensed under the Creative Commons Attribution License 4.0. HTML - version do - self.release = '4.4.6' - self.base_url = 'https://angular.io/' - self.root_path = 'docs' - - html_filters.push 'angular/clean_html', 'angular/entries' - - options[:follow_links] = false - options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/] - options[:fix_urls_before_parse] = ->(url) do - url.sub! %r{\Aguide/}, '/guide/' - url.sub! %r{\Atutorial/}, '/tutorial/' - url.sub! %r{\Aapi/}, '/api/' - url.sub! %r{\Agenerated/}, '/generated/' - url - end - + module Common private def initial_urls initial_urls = [] - Request.run 'https://angular.io/generated/navigation.json' do |response| + Request.run "#{self.class.base_url}generated/navigation.json" do |response| data = JSON.parse(response.body) dig = ->(entry) do initial_urls << url_for("generated/docs/#{entry['url']}.json") if entry['url'] && entry['url'] != 'api' @@ -46,7 +30,7 @@ module Docs data['SideNav'].each(&dig) end - Request.run 'https://angular.io/generated/docs/api/api-list.json' do |response| + Request.run "#{self.class.base_url}generated/docs/api/api-list.json" do |response| data = JSON.parse(response.body) dig = ->(entry) do initial_urls << url_for("generated/docs/#{entry['path']}.json") if entry['path'] @@ -61,7 +45,11 @@ module Docs def handle_response(response) if response.mime_type.include?('json') - response.options[:response_body] = JSON.parse(response.body)['contents'] + begin + response.options[:response_body] = JSON.parse(response.body)['contents'] + rescue JSON::ParserError + response.options[:response_body] = '' + end response.headers['Content-Type'] = 'text/html' response.url.path = response.url.path.sub('/generated/docs/', '/').remove('.json') response.effective_url.path = response.effective_url.path.sub('/generated/docs/', '/').remove('.json') @@ -70,6 +58,46 @@ module Docs end end + version do + self.release = '5.0.1' + self.base_url = 'https://angular.io/' + self.root_path = 'docs' + + html_filters.push 'angular/clean_html', 'angular/entries' + + options[:follow_links] = false + options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/] + options[:fix_urls_before_parse] = ->(url) do + url.sub! %r{\Aguide/}, '/guide/' + url.sub! %r{\Atutorial/}, '/tutorial/' + url.sub! %r{\Aapi/}, '/api/' + url.sub! %r{\Agenerated/}, '/generated/' + url + end + + include Docs::Angular::Common + end + + version '4' do + self.release = '4.4.6' + self.base_url = 'https://v4.angular.io/' + self.root_path = 'docs' + + html_filters.push 'angular/clean_html', 'angular/entries' + + options[:follow_links] = false + options[:only_patterns] = [/\Aguide/, /\Atutorial/, /\Aapi/] + options[:fix_urls_before_parse] = ->(url) do + url.sub! %r{\Aguide/}, '/guide/' + url.sub! %r{\Atutorial/}, '/tutorial/' + url.sub! %r{\Aapi/}, '/api/' + url.sub! %r{\Agenerated/}, '/generated/' + url + end + + include Docs::Angular::Common + end + version '2' do self.release = '2.4.10' self.base_url = 'https://v2.angular.io/docs/ts/latest/' From c91bf6f36984966a21d8c8a764cc21e3e63f01b9 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 10 Nov 2017 13:12:04 -0500 Subject: [PATCH 048/244] Update TensorFlow documentation (1.4) --- lib/docs/scrapers/tensorflow.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/tensorflow.rb b/lib/docs/scrapers/tensorflow.rb index 8fa2d423..a318cc5a 100644 --- a/lib/docs/scrapers/tensorflow.rb +++ b/lib/docs/scrapers/tensorflow.rb @@ -4,7 +4,7 @@ module Docs class Tensorflow < UrlScraper self.name = 'TensorFlow' self.type = 'tensorflow' - self.release = '1.3' + self.release = '1.4' self.root_path = 'index.html' self.links = { home: 'https://www.tensorflow.org/', From b681c80ed0c552fae369bb145344b41e4044eca2 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Sat, 28 Oct 2017 18:48:30 -0400 Subject: [PATCH 049/244] Add a print stylesheet removing the DevDocs UI --- assets/stylesheets/application.css.scss | 4 ++ assets/stylesheets/global/_classes.scss | 13 ++++ assets/stylesheets/global/_print.scss | 85 +++++++++++++++++++++++++ assets/stylesheets/pages/_rdoc.scss | 4 ++ 4 files changed, 106 insertions(+) create mode 100644 assets/stylesheets/global/_print.scss diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss index 4fdc2a14..d2370e7f 100644 --- a/assets/stylesheets/application.css.scss +++ b/assets/stylesheets/application.css.scss @@ -98,3 +98,7 @@ 'pages/webpack', 'pages/yard', 'pages/yii'; + +html { // specificity hack + @import 'global/print'; +} diff --git a/assets/stylesheets/global/_classes.scss b/assets/stylesheets/global/_classes.scss index f96f617b..c08c7f4c 100644 --- a/assets/stylesheets/global/_classes.scss +++ b/assets/stylesheets/global/_classes.scss @@ -2,6 +2,19 @@ // Utilities // +/* Usage: + * + * @include print { + * // print styles here + * } + * + */ +@mixin print { + @media print { + @content; + } +} + %border-box { -moz-box-sizing: border-box; box-sizing: border-box; diff --git a/assets/stylesheets/global/_print.scss b/assets/stylesheets/global/_print.scss new file mode 100644 index 00000000..69059fcf --- /dev/null +++ b/assets/stylesheets/global/_print.scss @@ -0,0 +1,85 @@ +// Style overrides for printing + +@include print { + + ._header, ._sidebar, ._path, ._notif, ._toc, ._pre-clip, ._notice { + display: none !important; + } + + // make the docs fill the page and scroll the instead of ._container + body { + height: initial; + &::after { + content: ''; + clear: both; + } + } + ._app { + height: initial; + } + ._container { + margin: 0; + padding: 0; + height: initial; + + ._content { + margin: 0; + } + } + + // Hide the scrollbars + ::-webkit-scrollbar { + display: none; + } + + // empty the boxes. + %box, + %heading-box { + background: transparent; + } + %heading-box { + border-radius: 0; + border: { + top: none; + left: none; + right: none; + } + } + + + // Underline links, put the destination after the link text + %external-link { + text-decoration: underline; + &::after { + content: ' (' attr(href) ')'; + background-image: none; + display: inline; + margin: 0; + } + } + + // Link back to DevDocs + ._attribution-p { + background: transparent; + border: 2px solid $labelBackground; + + &:after { + content: 'Exported from DevDocs (https://devdocs.io)'; + font-style: italic; + } + } + + // Fix page breaks + pre { + page-break-before: avoid; + } + pre { + orphans: 5; + widows: 5; + } + + p { + orphans: 2; + widows: 2; + } +} diff --git a/assets/stylesheets/pages/_rdoc.scss b/assets/stylesheets/pages/_rdoc.scss index 7fc9adda..f1c8b2cb 100644 --- a/assets/stylesheets/pages/_rdoc.scss +++ b/assets/stylesheets/pages/_rdoc.scss @@ -27,6 +27,10 @@ @extend %user-select-none; &:hover { text-decoration: underline; } + + @include print { + display: none; + } } .method-description { position: relative; } From 0bd828989143d7238e7f4aea9197df87fbcf4b64 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 17 Nov 2017 11:57:44 -0500 Subject: [PATCH 050/244] Tweak print stylesheet --- assets/stylesheets/application-dark.css.scss | 1 + assets/stylesheets/application.css.scss | 5 +- assets/stylesheets/global/_base.scss | 3 + assets/stylesheets/global/_classes.scss | 13 ---- assets/stylesheets/global/_mixins.scss | 9 +++ assets/stylesheets/global/_print.scss | 74 ++++++-------------- 6 files changed, 37 insertions(+), 68 deletions(-) create mode 100644 assets/stylesheets/global/_mixins.scss diff --git a/assets/stylesheets/application-dark.css.scss b/assets/stylesheets/application-dark.css.scss index d480f720..c88ada20 100644 --- a/assets/stylesheets/application-dark.css.scss +++ b/assets/stylesheets/application-dark.css.scss @@ -12,6 +12,7 @@ */ @import 'global/variables-dark', + 'global/mixins', 'global/icons', 'global/classes', 'global/base'; diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss index d2370e7f..f8b8a3c0 100644 --- a/assets/stylesheets/application.css.scss +++ b/assets/stylesheets/application.css.scss @@ -12,6 +12,7 @@ */ @import 'global/variables', + 'global/mixins', 'global/icons', 'global/classes', 'global/base'; @@ -98,7 +99,3 @@ 'pages/webpack', 'pages/yard', 'pages/yii'; - -html { // specificity hack - @import 'global/print'; -} diff --git a/assets/stylesheets/global/_base.scss b/assets/stylesheets/global/_base.scss index 659b8615..33c77a5e 100644 --- a/assets/stylesheets/global/_base.scss +++ b/assets/stylesheets/global/_base.scss @@ -4,6 +4,9 @@ html { background: $documentBackground; @media #{$mediumScreen} { font-size: 93.75%; } + + @include print { background: none; } + @import 'global/print'; } body { diff --git a/assets/stylesheets/global/_classes.scss b/assets/stylesheets/global/_classes.scss index c08c7f4c..f96f617b 100644 --- a/assets/stylesheets/global/_classes.scss +++ b/assets/stylesheets/global/_classes.scss @@ -2,19 +2,6 @@ // Utilities // -/* Usage: - * - * @include print { - * // print styles here - * } - * - */ -@mixin print { - @media print { - @content; - } -} - %border-box { -moz-box-sizing: border-box; box-sizing: border-box; diff --git a/assets/stylesheets/global/_mixins.scss b/assets/stylesheets/global/_mixins.scss new file mode 100644 index 00000000..604b9ac7 --- /dev/null +++ b/assets/stylesheets/global/_mixins.scss @@ -0,0 +1,9 @@ +// +// Mixins +// + +@mixin print { + @media print { + @content; + } +} diff --git a/assets/stylesheets/global/_print.scss b/assets/stylesheets/global/_print.scss index 69059fcf..30fa64c1 100644 --- a/assets/stylesheets/global/_print.scss +++ b/assets/stylesheets/global/_print.scss @@ -1,79 +1,51 @@ -// Style overrides for printing - @include print { - - ._header, ._sidebar, ._path, ._notif, ._toc, ._pre-clip, ._notice { + ._header, ._sidebar, ._path, ._notif, ._toc, ._pre-clip, ._notice, ._links { display: none !important; } - // make the docs fill the page and scroll the instead of ._container - body { - height: initial; - &::after { - content: ''; - clear: both; - } - } - ._app { - height: initial; - } - ._container { + body, ._app, ._container, ._content { margin: 0; padding: 0; height: initial; + background: none; - ._content { - margin: 0; + &:after { + content: ''; + clear: both; } } - // Hide the scrollbars ::-webkit-scrollbar { display: none; } - // empty the boxes. - %box, - %heading-box { - background: transparent; - } - %heading-box { - border-radius: 0; - border: { - top: none; - left: none; - right: none; - } + %external-link:after { + display: none; } + ._attribution-p { + background: none; + border: 2px solid $boxBorder; + } - // Underline links, put the destination after the link text - %external-link { - text-decoration: underline; - &::after { - content: ' (' attr(href) ')'; - background-image: none; - display: inline; - margin: 0; - } + ._attribution:last-child:after { + content: 'Exported from DevDocs — https://devdocs.io'; + display: block; + margin-top: 1rem; + font-weight: $bolderFontWeight; } - // Link back to DevDocs - ._attribution-p { - background: transparent; - border: 2px solid $labelBackground; + ._attribution { + page-break-inside: avoid; + } - &:after { - content: 'Exported from DevDocs (https://devdocs.io)'; - font-style: italic; - } + h1, h2, h3, h4, h5, h6 { + page-break-inside: avoid; + page-break-after: avoid; } - // Fix page breaks pre { page-break-before: avoid; - } - pre { orphans: 5; widows: 5; } From 4dc85f8eaa1436ecbecdf307ec95fcb576a49db4 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 17 Nov 2017 12:01:25 -0500 Subject: [PATCH 051/244] Update Raven.js --- assets/javascripts/vendor/raven.js | 5199 ++++++++++++++-------------- 1 file changed, 2544 insertions(+), 2655 deletions(-) diff --git a/assets/javascripts/vendor/raven.js b/assets/javascripts/vendor/raven.js index 591b6767..f36c41b2 100644 --- a/assets/javascripts/vendor/raven.js +++ b/assets/javascripts/vendor/raven.js @@ -1,4 +1,4 @@ -/*! Raven.js 3.18.0 (b771bb2) | github.com/getsentry/raven-js */ +/*! Raven.js 3.20.1 (42adaf5) | github.com/getsentry/raven-js */ /* * Includes TraceKit @@ -10,322 +10,270 @@ * */ -(function(f) { - if (typeof exports === 'object' && typeof module !== 'undefined') { - module.exports = f(); - } else if (typeof define === 'function' && define.amd) { - define([], f); - } else { - var g; - if (typeof window !== 'undefined') { - g = window; - } else if (typeof global !== 'undefined') { - g = global; - } else if (typeof self !== 'undefined') { - g = self; - } else { - g = this; - } - g.Raven = f(); - } -})(function() { - var define, module, exports; - return (function e(t, n, r) { - function s(o, u) { - if (!n[o]) { - if (!t[o]) { - var a = typeof require == 'function' && require; - if (!u && a) return a(o, !0); - if (i) return i(o, !0); - var f = new Error("Cannot find module '" + o + "'"); - throw ((f.code = 'MODULE_NOT_FOUND'), f); - } - var l = (n[o] = {exports: {}}); - t[o][0].call( - l.exports, - function(e) { - var n = t[o][1][e]; - return s(n ? n : e); - }, - l, - l.exports, - e, - t, - n, - r - ); - } - return n[o].exports; - } - var i = typeof require == 'function' && require; - for (var o = 0; o < r.length; o++) s(r[o]); - return s; - })( - { - 1: [ - function(_dereq_, module, exports) { - function RavenConfigError(message) { - this.name = 'RavenConfigError'; - this.message = message; - } - RavenConfigError.prototype = new Error(); - RavenConfigError.prototype.constructor = RavenConfigError; - - module.exports = RavenConfigError; - }, - {} - ], - 2: [ - function(_dereq_, module, exports) { - var wrapMethod = function(console, level, callback) { - var originalConsoleLevel = console[level]; - var originalConsole = console; - - if (!(level in console)) { - return; - } +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Raven = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o this._globalOptions.maxBreadcrumbs) { - this._breadcrumbs.shift(); - } - return this; - }, + if (isFunction(this._globalOptions.breadcrumbCallback)) { + var result = this._globalOptions.breadcrumbCallback(crumb); + + if (isObject(result) && !isEmptyObject(result)) { + crumb = result; + } else if (result === false) { + return this; + } + } - addPlugin: function(plugin /*arg1, arg2, ... argN*/) { - var pluginArgs = [].slice.call(arguments, 1); + this._breadcrumbs.push(crumb); + if (this._breadcrumbs.length > this._globalOptions.maxBreadcrumbs) { + this._breadcrumbs.shift(); + } + return this; + }, - this._plugins.push([plugin, pluginArgs]); - if (this._isRavenInstalled) { - this._drainPlugins(); - } + addPlugin: function(plugin /*arg1, arg2, ... argN*/) { + var pluginArgs = [].slice.call(arguments, 1); - return this; - }, + this._plugins.push([plugin, pluginArgs]); + if (this._isRavenInstalled) { + this._drainPlugins(); + } + + return this; + }, - /* + /* * Set/clear a user to be sent along with the payload. * * @param {object} user An object representing user data [optional] * @return {Raven} */ - setUserContext: function(user) { - // Intentionally do not merge here since that's an unexpected behavior. - this._globalContext.user = user; + setUserContext: function(user) { + // Intentionally do not merge here since that's an unexpected behavior. + this._globalContext.user = user; - return this; - }, + return this; + }, - /* + /* * Merge extra attributes to be sent along with the payload. * * @param {object} extra An object representing extra data [optional] * @return {Raven} */ - setExtraContext: function(extra) { - this._mergeContext('extra', extra); + setExtraContext: function(extra) { + this._mergeContext('extra', extra); - return this; - }, + return this; + }, - /* + /* * Merge tags to be sent along with the payload. * * @param {object} tags An object representing tags [optional] * @return {Raven} */ - setTagsContext: function(tags) { - this._mergeContext('tags', tags); + setTagsContext: function(tags) { + this._mergeContext('tags', tags); - return this; - }, + return this; + }, - /* + /* * Clear all of the context. * * @return {Raven} */ - clearContext: function() { - this._globalContext = {}; + clearContext: function() { + this._globalContext = {}; - return this; - }, + return this; + }, - /* + /* * Get a copy of the current context. This cannot be mutated. * * @return {object} copy of context */ - getContext: function() { - // lol javascript - return JSON.parse(stringify(this._globalContext)); - }, + getContext: function() { + // lol javascript + return JSON.parse(stringify(this._globalContext)); + }, - /* + /* * Set environment of application * * @param {string} environment Typically something like 'production'. * @return {Raven} */ - setEnvironment: function(environment) { - this._globalOptions.environment = environment; + setEnvironment: function(environment) { + this._globalOptions.environment = environment; - return this; - }, + return this; + }, - /* + /* * Set release version of application * * @param {string} release Typically something like a git SHA to identify version * @return {Raven} */ - setRelease: function(release) { - this._globalOptions.release = release; + setRelease: function(release) { + this._globalOptions.release = release; - return this; - }, + return this; + }, - /* + /* * Set the dataCallback option * * @param {function} callback The callback to run which allows the * data blob to be mutated before sending * @return {Raven} */ - setDataCallback: function(callback) { - var original = this._globalOptions.dataCallback; - this._globalOptions.dataCallback = keepOriginalCallback( - original, - callback - ); - return this; - }, - - /* + setDataCallback: function(callback) { + var original = this._globalOptions.dataCallback; + this._globalOptions.dataCallback = keepOriginalCallback(original, callback); + return this; + }, + + /* * Set the breadcrumbCallback option * * @param {function} callback The callback to run which allows filtering * or mutating breadcrumbs * @return {Raven} */ - setBreadcrumbCallback: function(callback) { - var original = this._globalOptions.breadcrumbCallback; - this._globalOptions.breadcrumbCallback = keepOriginalCallback( - original, - callback - ); - return this; - }, - - /* + setBreadcrumbCallback: function(callback) { + var original = this._globalOptions.breadcrumbCallback; + this._globalOptions.breadcrumbCallback = keepOriginalCallback(original, callback); + return this; + }, + + /* * Set the shouldSendCallback option * * @param {function} callback The callback to run which allows * introspecting the blob before sending * @return {Raven} */ - setShouldSendCallback: function(callback) { - var original = this._globalOptions.shouldSendCallback; - this._globalOptions.shouldSendCallback = keepOriginalCallback( - original, - callback - ); - return this; - }, - - /** + setShouldSendCallback: function(callback) { + var original = this._globalOptions.shouldSendCallback; + this._globalOptions.shouldSendCallback = keepOriginalCallback(original, callback); + return this; + }, + + /** * Override the default HTTP transport mechanism that transmits data * to the Sentry server. * @@ -798,438 +757,443 @@ * * @return {Raven} */ - setTransport: function(transport) { - this._globalOptions.transport = transport; + setTransport: function(transport) { + this._globalOptions.transport = transport; - return this; - }, + return this; + }, - /* + /* * Get the latest raw exception that was captured by Raven. * * @return {error} */ - lastException: function() { - return this._lastCapturedException; - }, + lastException: function() { + return this._lastCapturedException; + }, - /* + /* * Get the last event id * * @return {string} */ - lastEventId: function() { - return this._lastEventId; - }, + lastEventId: function() { + return this._lastEventId; + }, - /* + /* * Determine if Raven is setup and ready to go. * * @return {boolean} */ - isSetup: function() { - if (!this._hasJSON) return false; // needs JSON support - if (!this._globalServer) { - if (!this.ravenNotConfiguredError) { - this.ravenNotConfiguredError = true; - this._logDebug('error', 'Error: Raven has not been configured.'); - } - return false; - } - return true; - }, + isSetup: function() { + if (!this._hasJSON) return false; // needs JSON support + if (!this._globalServer) { + if (!this.ravenNotConfiguredError) { + this.ravenNotConfiguredError = true; + this._logDebug('error', 'Error: Raven has not been configured.'); + } + return false; + } + return true; + }, - afterLoad: function() { - // TODO: remove window dependence? + afterLoad: function() { + // TODO: remove window dependence? - // Attempt to initialize Raven on load - var RavenConfig = _window.RavenConfig; - if (RavenConfig) { - this.config(RavenConfig.dsn, RavenConfig.config).install(); - } - }, + // Attempt to initialize Raven on load + var RavenConfig = _window.RavenConfig; + if (RavenConfig) { + this.config(RavenConfig.dsn, RavenConfig.config).install(); + } + }, - showReportDialog: function(options) { - if ( - !_document // doesn't work without a document (React native) - ) - return; + showReportDialog: function(options) { + if ( + !_document // doesn't work without a document (React native) + ) + return; - options = options || {}; + options = options || {}; - var lastEventId = options.eventId || this.lastEventId(); - if (!lastEventId) { - throw new RavenConfigError('Missing eventId'); - } + var lastEventId = options.eventId || this.lastEventId(); + if (!lastEventId) { + throw new RavenConfigError('Missing eventId'); + } - var dsn = options.dsn || this._dsn; - if (!dsn) { - throw new RavenConfigError('Missing DSN'); - } + var dsn = options.dsn || this._dsn; + if (!dsn) { + throw new RavenConfigError('Missing DSN'); + } - var encode = encodeURIComponent; - var qs = ''; - qs += '?eventId=' + encode(lastEventId); - qs += '&dsn=' + encode(dsn); + var encode = encodeURIComponent; + var qs = ''; + qs += '?eventId=' + encode(lastEventId); + qs += '&dsn=' + encode(dsn); - var user = options.user || this._globalContext.user; - if (user) { - if (user.name) qs += '&name=' + encode(user.name); - if (user.email) qs += '&email=' + encode(user.email); - } + var user = options.user || this._globalContext.user; + if (user) { + if (user.name) qs += '&name=' + encode(user.name); + if (user.email) qs += '&email=' + encode(user.email); + } - var globalServer = this._getGlobalServer(this._parseDSN(dsn)); - - var script = _document.createElement('script'); - script.async = true; - script.src = globalServer + '/api/embed/error-page/' + qs; - (_document.head || _document.body).appendChild(script); - }, - - /**** Private functions ****/ - _ignoreNextOnError: function() { - var self = this; - this._ignoreOnError += 1; - setTimeout(function() { - // onerror should trigger before setTimeout - self._ignoreOnError -= 1; - }); - }, + var globalServer = this._getGlobalServer(this._parseDSN(dsn)); - _triggerEvent: function(eventType, options) { - // NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it - var evt, key; + var script = _document.createElement('script'); + script.async = true; + script.src = globalServer + '/api/embed/error-page/' + qs; + (_document.head || _document.body).appendChild(script); + }, - if (!this._hasDocument) return; + /**** Private functions ****/ + _ignoreNextOnError: function() { + var self = this; + this._ignoreOnError += 1; + setTimeout(function() { + // onerror should trigger before setTimeout + self._ignoreOnError -= 1; + }); + }, - options = options || {}; + _triggerEvent: function(eventType, options) { + // NOTE: `event` is a native browser thing, so let's avoid conflicting wiht it + var evt, key; - eventType = - 'raven' + eventType.substr(0, 1).toUpperCase() + eventType.substr(1); + if (!this._hasDocument) return; - if (_document.createEvent) { - evt = _document.createEvent('HTMLEvents'); - evt.initEvent(eventType, true, true); - } else { - evt = _document.createEventObject(); - evt.eventType = eventType; - } + options = options || {}; - for (key in options) - if (hasKey(options, key)) { - evt[key] = options[key]; - } + eventType = 'raven' + eventType.substr(0, 1).toUpperCase() + eventType.substr(1); - if (_document.createEvent) { - // IE9 if standards - _document.dispatchEvent(evt); - } else { - // IE8 regardless of Quirks or Standards - // IE9 if quirks - try { - _document.fireEvent('on' + evt.eventType.toLowerCase(), evt); - } catch (e) { - // Do nothing - } - } - }, + if (_document.createEvent) { + evt = _document.createEvent('HTMLEvents'); + evt.initEvent(eventType, true, true); + } else { + evt = _document.createEventObject(); + evt.eventType = eventType; + } + + for (key in options) + if (hasKey(options, key)) { + evt[key] = options[key]; + } + + if (_document.createEvent) { + // IE9 if standards + _document.dispatchEvent(evt); + } else { + // IE8 regardless of Quirks or Standards + // IE9 if quirks + try { + _document.fireEvent('on' + evt.eventType.toLowerCase(), evt); + } catch (e) { + // Do nothing + } + } + }, - /** + /** * Wraps addEventListener to capture UI breadcrumbs * @param evtName the event name (e.g. "click") * @returns {Function} * @private */ - _breadcrumbEventHandler: function(evtName) { - var self = this; - return function(evt) { - // reset keypress timeout; e.g. triggering a 'click' after - // a 'keypress' will reset the keypress debounce so that a new - // set of keypresses can be recorded - self._keypressTimeout = null; - - // It's possible this handler might trigger multiple times for the same - // event (e.g. event propagation through node ancestors). Ignore if we've - // already captured the event. - if (self._lastCapturedEvent === evt) return; - - self._lastCapturedEvent = evt; - - // try/catch both: - // - accessing evt.target (see getsentry/raven-js#838, #768) - // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly - // can throw an exception in some circumstances. - var target; - try { - target = htmlTreeAsString(evt.target); - } catch (e) { - target = ''; - } + _breadcrumbEventHandler: function(evtName) { + var self = this; + return function(evt) { + // reset keypress timeout; e.g. triggering a 'click' after + // a 'keypress' will reset the keypress debounce so that a new + // set of keypresses can be recorded + self._keypressTimeout = null; + + // It's possible this handler might trigger multiple times for the same + // event (e.g. event propagation through node ancestors). Ignore if we've + // already captured the event. + if (self._lastCapturedEvent === evt) return; + + self._lastCapturedEvent = evt; + + // try/catch both: + // - accessing evt.target (see getsentry/raven-js#838, #768) + // - `htmlTreeAsString` because it's complex, and just accessing the DOM incorrectly + // can throw an exception in some circumstances. + var target; + try { + target = htmlTreeAsString(evt.target); + } catch (e) { + target = ''; + } - self.captureBreadcrumb({ - category: 'ui.' + evtName, // e.g. ui.click, ui.input - message: target - }); - }; - }, + self.captureBreadcrumb({ + category: 'ui.' + evtName, // e.g. ui.click, ui.input + message: target + }); + }; + }, - /** + /** * Wraps addEventListener to capture keypress UI events * @returns {Function} * @private */ - _keypressEventHandler: function() { - var self = this, - debounceDuration = 1000; // milliseconds - - // TODO: if somehow user switches keypress target before - // debounce timeout is triggered, we will only capture - // a single breadcrumb from the FIRST target (acceptable?) - return function(evt) { - var target; - try { - target = evt.target; - } catch (e) { - // just accessing event properties can throw an exception in some rare circumstances - // see: https://github.com/getsentry/raven-js/issues/838 - return; - } - var tagName = target && target.tagName; - - // only consider keypress events on actual input elements - // this will disregard keypresses targeting body (e.g. tabbing - // through elements, hotkeys, etc) - if ( - !tagName || - (tagName !== 'INPUT' && - tagName !== 'TEXTAREA' && - !target.isContentEditable) - ) - return; - - // record first keypress in a series, but ignore subsequent - // keypresses until debounce clears - var timeout = self._keypressTimeout; - if (!timeout) { - self._breadcrumbEventHandler('input')(evt); - } - clearTimeout(timeout); - self._keypressTimeout = setTimeout(function() { - self._keypressTimeout = null; - }, debounceDuration); - }; - }, - - /** + _keypressEventHandler: function() { + var self = this, + debounceDuration = 1000; // milliseconds + + // TODO: if somehow user switches keypress target before + // debounce timeout is triggered, we will only capture + // a single breadcrumb from the FIRST target (acceptable?) + return function(evt) { + var target; + try { + target = evt.target; + } catch (e) { + // just accessing event properties can throw an exception in some rare circumstances + // see: https://github.com/getsentry/raven-js/issues/838 + return; + } + var tagName = target && target.tagName; + + // only consider keypress events on actual input elements + // this will disregard keypresses targeting body (e.g. tabbing + // through elements, hotkeys, etc) + if ( + !tagName || + (tagName !== 'INPUT' && tagName !== 'TEXTAREA' && !target.isContentEditable) + ) + return; + + // record first keypress in a series, but ignore subsequent + // keypresses until debounce clears + var timeout = self._keypressTimeout; + if (!timeout) { + self._breadcrumbEventHandler('input')(evt); + } + clearTimeout(timeout); + self._keypressTimeout = setTimeout(function() { + self._keypressTimeout = null; + }, debounceDuration); + }; + }, + + /** * Captures a breadcrumb of type "navigation", normalizing input URLs * @param to the originating URL * @param from the target URL * @private */ - _captureUrlChange: function(from, to) { - var parsedLoc = parseUrl(this._location.href); - var parsedTo = parseUrl(to); - var parsedFrom = parseUrl(from); - - // because onpopstate only tells you the "new" (to) value of location.href, and - // not the previous (from) value, we need to track the value of the current URL - // state ourselves - this._lastHref = to; - - // Use only the path component of the URL if the URL matches the current - // document (almost all the time when using pushState) - if ( - parsedLoc.protocol === parsedTo.protocol && - parsedLoc.host === parsedTo.host - ) - to = parsedTo.relative; - if ( - parsedLoc.protocol === parsedFrom.protocol && - parsedLoc.host === parsedFrom.host - ) - from = parsedFrom.relative; - - this.captureBreadcrumb({ - category: 'navigation', - data: { - to: to, - from: from - } - }); - }, + _captureUrlChange: function(from, to) { + var parsedLoc = parseUrl(this._location.href); + var parsedTo = parseUrl(to); + var parsedFrom = parseUrl(from); + + // because onpopstate only tells you the "new" (to) value of location.href, and + // not the previous (from) value, we need to track the value of the current URL + // state ourselves + this._lastHref = to; + + // Use only the path component of the URL if the URL matches the current + // document (almost all the time when using pushState) + if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) + to = parsedTo.relative; + if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) + from = parsedFrom.relative; + + this.captureBreadcrumb({ + category: 'navigation', + data: { + to: to, + from: from + } + }); + }, + + _patchFunctionToString: function() { + var self = this; + self._originalFunctionToString = Function.prototype.toString; + // eslint-disable-next-line no-extend-native + Function.prototype.toString = function() { + if (typeof this === 'function' && this.__raven__) { + return self._originalFunctionToString.apply(this.__orig__, arguments); + } + return self._originalFunctionToString.apply(this, arguments); + }; + }, + + _unpatchFunctionToString: function() { + if (this._originalFunctionToString) { + // eslint-disable-next-line no-extend-native + Function.prototype.toString = this._originalFunctionToString; + } + }, - /** + /** * Wrap timer functions and event targets to catch errors and provide * better metadata. */ - _instrumentTryCatch: function() { - var self = this; - - var wrappedBuiltIns = self._wrappedBuiltIns; - - function wrapTimeFn(orig) { - return function(fn, t) { - // preserve arity - // Make a copy of the arguments to prevent deoptimization - // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments - var args = new Array(arguments.length); - for (var i = 0; i < args.length; ++i) { - args[i] = arguments[i]; - } - var originalCallback = args[0]; - if (isFunction(originalCallback)) { - args[0] = self.wrap(originalCallback); - } - - // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it - // also supports only two arguments and doesn't care what this is, so we - // can just call the original function directly. - if (orig.apply) { - return orig.apply(this, args); - } else { - return orig(args[0], args[1]); - } - }; - } + _instrumentTryCatch: function() { + var self = this; + + var wrappedBuiltIns = self._wrappedBuiltIns; + + function wrapTimeFn(orig) { + return function(fn, t) { + // preserve arity + // Make a copy of the arguments to prevent deoptimization + // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) { + args[i] = arguments[i]; + } + var originalCallback = args[0]; + if (isFunction(originalCallback)) { + args[0] = self.wrap(originalCallback); + } + + // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it + // also supports only two arguments and doesn't care what this is, so we + // can just call the original function directly. + if (orig.apply) { + return orig.apply(this, args); + } else { + return orig(args[0], args[1]); + } + }; + } + + var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs; + + function wrapEventTarget(global) { + var proto = _window[global] && _window[global].prototype; + if (proto && proto.hasOwnProperty && proto.hasOwnProperty('addEventListener')) { + fill( + proto, + 'addEventListener', + function(orig) { + return function(evtName, fn, capture, secure) { + // preserve arity + try { + if (fn && fn.handleEvent) { + fn.handleEvent = self.wrap(fn.handleEvent); + } + } catch (err) { + // can sometimes get 'Permission denied to access property "handle Event' + } - var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs; - - function wrapEventTarget(global) { - var proto = _window[global] && _window[global].prototype; - if ( - proto && - proto.hasOwnProperty && - proto.hasOwnProperty('addEventListener') - ) { - fill( - proto, - 'addEventListener', - function(orig) { - return function(evtName, fn, capture, secure) { - // preserve arity - try { - if (fn && fn.handleEvent) { - fn.handleEvent = self.wrap(fn.handleEvent); - } - } catch (err) { - // can sometimes get 'Permission denied to access property "handle Event' - } - - // More breadcrumb DOM capture ... done here and not in `_instrumentBreadcrumbs` - // so that we don't have more than one wrapper function - var before, clickHandler, keypressHandler; - - if ( - autoBreadcrumbs && - autoBreadcrumbs.dom && - (global === 'EventTarget' || global === 'Node') - ) { - // NOTE: generating multiple handlers per addEventListener invocation, should - // revisit and verify we can just use one (almost certainly) - clickHandler = self._breadcrumbEventHandler('click'); - keypressHandler = self._keypressEventHandler(); - before = function(evt) { - // need to intercept every DOM event in `before` argument, in case that - // same wrapped method is re-used for different events (e.g. mousemove THEN click) - // see #724 - if (!evt) return; - - var eventType; - try { - eventType = evt.type; - } catch (e) { - // just accessing event properties can throw an exception in some rare circumstances - // see: https://github.com/getsentry/raven-js/issues/838 - return; - } - if (eventType === 'click') return clickHandler(evt); - else if (eventType === 'keypress') - return keypressHandler(evt); - }; - } - return orig.call( - this, - evtName, - self.wrap(fn, undefined, before), - capture, - secure - ); - }; - }, - wrappedBuiltIns - ); - fill( - proto, - 'removeEventListener', - function(orig) { - return function(evt, fn, capture, secure) { - try { - fn = fn && (fn.__raven_wrapper__ ? fn.__raven_wrapper__ : fn); - } catch (e) { - // ignore, accessing __raven_wrapper__ will throw in some Selenium environments - } - return orig.call(this, evt, fn, capture, secure); - }; - }, - wrappedBuiltIns - ); + // More breadcrumb DOM capture ... done here and not in `_instrumentBreadcrumbs` + // so that we don't have more than one wrapper function + var before, clickHandler, keypressHandler; + + if ( + autoBreadcrumbs && + autoBreadcrumbs.dom && + (global === 'EventTarget' || global === 'Node') + ) { + // NOTE: generating multiple handlers per addEventListener invocation, should + // revisit and verify we can just use one (almost certainly) + clickHandler = self._breadcrumbEventHandler('click'); + keypressHandler = self._keypressEventHandler(); + before = function(evt) { + // need to intercept every DOM event in `before` argument, in case that + // same wrapped method is re-used for different events (e.g. mousemove THEN click) + // see #724 + if (!evt) return; + + var eventType; + try { + eventType = evt.type; + } catch (e) { + // just accessing event properties can throw an exception in some rare circumstances + // see: https://github.com/getsentry/raven-js/issues/838 + return; } - } + if (eventType === 'click') return clickHandler(evt); + else if (eventType === 'keypress') return keypressHandler(evt); + }; + } + return orig.call( + this, + evtName, + self.wrap(fn, undefined, before), + capture, + secure + ); + }; + }, + wrappedBuiltIns + ); + fill( + proto, + 'removeEventListener', + function(orig) { + return function(evt, fn, capture, secure) { + try { + fn = fn && (fn.__raven_wrapper__ ? fn.__raven_wrapper__ : fn); + } catch (e) { + // ignore, accessing __raven_wrapper__ will throw in some Selenium environments + } + return orig.call(this, evt, fn, capture, secure); + }; + }, + wrappedBuiltIns + ); + } + } - fill(_window, 'setTimeout', wrapTimeFn, wrappedBuiltIns); - fill(_window, 'setInterval', wrapTimeFn, wrappedBuiltIns); - if (_window.requestAnimationFrame) { - fill( - _window, - 'requestAnimationFrame', - function(orig) { - return function(cb) { - return orig(self.wrap(cb)); - }; - }, - wrappedBuiltIns - ); - } + fill(_window, 'setTimeout', wrapTimeFn, wrappedBuiltIns); + fill(_window, 'setInterval', wrapTimeFn, wrappedBuiltIns); + if (_window.requestAnimationFrame) { + fill( + _window, + 'requestAnimationFrame', + function(orig) { + return function(cb) { + return orig(self.wrap(cb)); + }; + }, + wrappedBuiltIns + ); + } - // event targets borrowed from bugsnag-js: - // https://github.com/bugsnag/bugsnag-js/blob/master/src/bugsnag.js#L666 - var eventTargets = [ - 'EventTarget', - 'Window', - 'Node', - 'ApplicationCache', - 'AudioTrackList', - 'ChannelMergerNode', - 'CryptoOperation', - 'EventSource', - 'FileReader', - 'HTMLUnknownElement', - 'IDBDatabase', - 'IDBRequest', - 'IDBTransaction', - 'KeyOperation', - 'MediaController', - 'MessagePort', - 'ModalWindow', - 'Notification', - 'SVGElementInstance', - 'Screen', - 'TextTrack', - 'TextTrackCue', - 'TextTrackList', - 'WebSocket', - 'WebSocketWorker', - 'Worker', - 'XMLHttpRequest', - 'XMLHttpRequestEventTarget', - 'XMLHttpRequestUpload' - ]; - for (var i = 0; i < eventTargets.length; i++) { - wrapEventTarget(eventTargets[i]); - } - }, + // event targets borrowed from bugsnag-js: + // https://github.com/bugsnag/bugsnag-js/blob/master/src/bugsnag.js#L666 + var eventTargets = [ + 'EventTarget', + 'Window', + 'Node', + 'ApplicationCache', + 'AudioTrackList', + 'ChannelMergerNode', + 'CryptoOperation', + 'EventSource', + 'FileReader', + 'HTMLUnknownElement', + 'IDBDatabase', + 'IDBRequest', + 'IDBTransaction', + 'KeyOperation', + 'MediaController', + 'MessagePort', + 'ModalWindow', + 'Notification', + 'SVGElementInstance', + 'Screen', + 'TextTrack', + 'TextTrackCue', + 'TextTrackList', + 'WebSocket', + 'WebSocketWorker', + 'Worker', + 'XMLHttpRequest', + 'XMLHttpRequestEventTarget', + 'XMLHttpRequestUpload' + ]; + for (var i = 0; i < eventTargets.length; i++) { + wrapEventTarget(eventTargets[i]); + } + }, - /** + /** * Instrument browser built-ins w/ breadcrumb capturing * - XMLHttpRequests * - DOM interactions (click/typing) @@ -1238,546 +1202,515 @@ * * Can be disabled or individually configured via the `autoBreadcrumbs` config option */ - _instrumentBreadcrumbs: function() { - var self = this; - var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs; + _instrumentBreadcrumbs: function() { + var self = this; + var autoBreadcrumbs = this._globalOptions.autoBreadcrumbs; - var wrappedBuiltIns = self._wrappedBuiltIns; + var wrappedBuiltIns = self._wrappedBuiltIns; - function wrapProp(prop, xhr) { - if (prop in xhr && isFunction(xhr[prop])) { - fill(xhr, prop, function(orig) { - return self.wrap(orig); - }); // intentionally don't track filled methods on XHR instances - } - } + function wrapProp(prop, xhr) { + if (prop in xhr && isFunction(xhr[prop])) { + fill(xhr, prop, function(orig) { + return self.wrap(orig); + }); // intentionally don't track filled methods on XHR instances + } + } - if (autoBreadcrumbs.xhr && 'XMLHttpRequest' in _window) { - var xhrproto = XMLHttpRequest.prototype; - fill( - xhrproto, - 'open', - function(origOpen) { - return function(method, url) { - // preserve arity - - // if Sentry key appears in URL, don't capture - if (isString(url) && url.indexOf(self._globalKey) === -1) { - this.__raven_xhr = { - method: method, - url: url, - status_code: null - }; - } - - return origOpen.apply(this, arguments); - }; - }, - wrappedBuiltIns - ); - - fill( - xhrproto, - 'send', - function(origSend) { - return function(data) { - // preserve arity - var xhr = this; - - function onreadystatechangeHandler() { - if (xhr.__raven_xhr && xhr.readyState === 4) { - try { - // touching statusCode in some platforms throws - // an exception - xhr.__raven_xhr.status_code = xhr.status; - } catch (e) { - /* do nothing */ - } - - self.captureBreadcrumb({ - type: 'http', - category: 'xhr', - data: xhr.__raven_xhr - }); - } - } - - var props = ['onload', 'onerror', 'onprogress']; - for (var j = 0; j < props.length; j++) { - wrapProp(props[j], xhr); - } - - if ( - 'onreadystatechange' in xhr && - isFunction(xhr.onreadystatechange) - ) { - fill( - xhr, - 'onreadystatechange', - function(orig) { - return self.wrap( - orig, - undefined, - onreadystatechangeHandler - ); - } /* intentionally don't track this instrumentation */ - ); - } else { - // if onreadystatechange wasn't actually set by the page on this xhr, we - // are free to set our own and capture the breadcrumb - xhr.onreadystatechange = onreadystatechangeHandler; - } - - return origSend.apply(this, arguments); - }; - }, - wrappedBuiltIns - ); - } + if (autoBreadcrumbs.xhr && 'XMLHttpRequest' in _window) { + var xhrproto = XMLHttpRequest.prototype; + fill( + xhrproto, + 'open', + function(origOpen) { + return function(method, url) { + // preserve arity + + // if Sentry key appears in URL, don't capture + if (isString(url) && url.indexOf(self._globalKey) === -1) { + this.__raven_xhr = { + method: method, + url: url, + status_code: null + }; + } - if (autoBreadcrumbs.xhr && 'fetch' in _window) { - fill( - _window, - 'fetch', - function(origFetch) { - return function(fn, t) { - // preserve arity - // Make a copy of the arguments to prevent deoptimization - // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments - var args = new Array(arguments.length); - for (var i = 0; i < args.length; ++i) { - args[i] = arguments[i]; - } - - var fetchInput = args[0]; - var method = 'GET'; - var url; - - if (typeof fetchInput === 'string') { - url = fetchInput; - } else { - url = fetchInput.url; - if (fetchInput.method) { - method = fetchInput.method; - } - } - - if (args[1] && args[1].method) { - method = args[1].method; - } - - var fetchData = { - method: method, - url: url, - status_code: null - }; - - self.captureBreadcrumb({ - type: 'http', - category: 'fetch', - data: fetchData - }); - - return origFetch.apply(this, args).then(function(response) { - fetchData.status_code = response.status; - - return response; - }); - }; - }, - wrappedBuiltIns - ); + return origOpen.apply(this, arguments); + }; + }, + wrappedBuiltIns + ); + + fill( + xhrproto, + 'send', + function(origSend) { + return function(data) { + // preserve arity + var xhr = this; + + function onreadystatechangeHandler() { + if (xhr.__raven_xhr && xhr.readyState === 4) { + try { + // touching statusCode in some platforms throws + // an exception + xhr.__raven_xhr.status_code = xhr.status; + } catch (e) { + /* do nothing */ } - // Capture breadcrumbs from any click that is unhandled / bubbled up all the way - // to the document. Do this before we instrument addEventListener. - if (autoBreadcrumbs.dom && this._hasDocument) { - if (_document.addEventListener) { - _document.addEventListener( - 'click', - self._breadcrumbEventHandler('click'), - false - ); - _document.addEventListener( - 'keypress', - self._keypressEventHandler(), - false - ); - } else { - // IE8 Compatibility - _document.attachEvent( - 'onclick', - self._breadcrumbEventHandler('click') - ); - _document.attachEvent('onkeypress', self._keypressEventHandler()); - } - } + self.captureBreadcrumb({ + type: 'http', + category: 'xhr', + data: xhr.__raven_xhr + }); + } + } - // record navigation (URL) changes - // NOTE: in Chrome App environment, touching history.pushState, *even inside - // a try/catch block*, will cause Chrome to output an error to console.error - // borrowed from: https://github.com/angular/angular.js/pull/13945/files - var chrome = _window.chrome; - var isChromePackagedApp = chrome && chrome.app && chrome.app.runtime; - var hasPushState = - !isChromePackagedApp && _window.history && history.pushState; - if (autoBreadcrumbs.location && hasPushState) { - // TODO: remove onpopstate handler on uninstall() - var oldOnPopState = _window.onpopstate; - _window.onpopstate = function() { - var currentHref = self._location.href; - self._captureUrlChange(self._lastHref, currentHref); - - if (oldOnPopState) { - return oldOnPopState.apply(this, arguments); - } - }; - - fill( - history, - 'pushState', - function(origPushState) { - // note history.pushState.length is 0; intentionally not declaring - // params to preserve 0 arity - return function(/* state, title, url */) { - var url = arguments.length > 2 ? arguments[2] : undefined; - - // url argument is optional - if (url) { - // coerce to string (this is what pushState does) - self._captureUrlChange(self._lastHref, url + ''); - } - - return origPushState.apply(this, arguments); - }; - }, - wrappedBuiltIns - ); - } + var props = ['onload', 'onerror', 'onprogress']; + for (var j = 0; j < props.length; j++) { + wrapProp(props[j], xhr); + } - if (autoBreadcrumbs.console && 'console' in _window && console.log) { - // console - var consoleMethodCallback = function(msg, data) { - self.captureBreadcrumb({ - message: msg, - level: data.level, - category: 'console' - }); - }; - - each(['debug', 'info', 'warn', 'error', 'log'], function(_, level) { - wrapConsoleMethod(console, level, consoleMethodCallback); - }); - } - }, + if ('onreadystatechange' in xhr && isFunction(xhr.onreadystatechange)) { + fill( + xhr, + 'onreadystatechange', + function(orig) { + return self.wrap(orig, undefined, onreadystatechangeHandler); + } /* intentionally don't track this instrumentation */ + ); + } else { + // if onreadystatechange wasn't actually set by the page on this xhr, we + // are free to set our own and capture the breadcrumb + xhr.onreadystatechange = onreadystatechangeHandler; + } + + return origSend.apply(this, arguments); + }; + }, + wrappedBuiltIns + ); + } - _restoreBuiltIns: function() { - // restore any wrapped builtins - var builtin; - while (this._wrappedBuiltIns.length) { - builtin = this._wrappedBuiltIns.shift(); + if (autoBreadcrumbs.xhr && 'fetch' in _window) { + fill( + _window, + 'fetch', + function(origFetch) { + return function(fn, t) { + // preserve arity + // Make a copy of the arguments to prevent deoptimization + // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments + var args = new Array(arguments.length); + for (var i = 0; i < args.length; ++i) { + args[i] = arguments[i]; + } - var obj = builtin[0], - name = builtin[1], - orig = builtin[2]; + var fetchInput = args[0]; + var method = 'GET'; + var url; - obj[name] = orig; - } - }, + if (typeof fetchInput === 'string') { + url = fetchInput; + } else if ('Request' in _window && fetchInput instanceof _window.Request) { + url = fetchInput.url; + if (fetchInput.method) { + method = fetchInput.method; + } + } else { + url = '' + fetchInput; + } - _drainPlugins: function() { - var self = this; + if (args[1] && args[1].method) { + method = args[1].method; + } - // FIX ME TODO - each(this._plugins, function(_, plugin) { - var installer = plugin[0]; - var args = plugin[1]; - installer.apply(self, [self].concat(args)); - }); - }, + var fetchData = { + method: method, + url: url, + status_code: null + }; - _parseDSN: function(str) { - var m = dsnPattern.exec(str), - dsn = {}, - i = 7; + self.captureBreadcrumb({ + type: 'http', + category: 'fetch', + data: fetchData + }); - try { - while (i--) dsn[dsnKeys[i]] = m[i] || ''; - } catch (e) { - throw new RavenConfigError('Invalid DSN: ' + str); - } + return origFetch.apply(this, args).then(function(response) { + fetchData.status_code = response.status; - if (dsn.pass && !this._globalOptions.allowSecretKey) { - throw new RavenConfigError( - 'Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key' - ); - } + return response; + }); + }; + }, + wrappedBuiltIns + ); + } - return dsn; - }, + // Capture breadcrumbs from any click that is unhandled / bubbled up all the way + // to the document. Do this before we instrument addEventListener. + if (autoBreadcrumbs.dom && this._hasDocument) { + if (_document.addEventListener) { + _document.addEventListener('click', self._breadcrumbEventHandler('click'), false); + _document.addEventListener('keypress', self._keypressEventHandler(), false); + } else { + // IE8 Compatibility + _document.attachEvent('onclick', self._breadcrumbEventHandler('click')); + _document.attachEvent('onkeypress', self._keypressEventHandler()); + } + } - _getGlobalServer: function(uri) { - // assemble the endpoint from the uri pieces - var globalServer = '//' + uri.host + (uri.port ? ':' + uri.port : ''); + // record navigation (URL) changes + // NOTE: in Chrome App environment, touching history.pushState, *even inside + // a try/catch block*, will cause Chrome to output an error to console.error + // borrowed from: https://github.com/angular/angular.js/pull/13945/files + var chrome = _window.chrome; + var isChromePackagedApp = chrome && chrome.app && chrome.app.runtime; + var hasPushAndReplaceState = + !isChromePackagedApp && + _window.history && + history.pushState && + history.replaceState; + if (autoBreadcrumbs.location && hasPushAndReplaceState) { + // TODO: remove onpopstate handler on uninstall() + var oldOnPopState = _window.onpopstate; + _window.onpopstate = function() { + var currentHref = self._location.href; + self._captureUrlChange(self._lastHref, currentHref); + + if (oldOnPopState) { + return oldOnPopState.apply(this, arguments); + } + }; + + var historyReplacementFunction = function(origHistFunction) { + // note history.pushState.length is 0; intentionally not declaring + // params to preserve 0 arity + return function(/* state, title, url */) { + var url = arguments.length > 2 ? arguments[2] : undefined; + + // url argument is optional + if (url) { + // coerce to string (this is what pushState does) + self._captureUrlChange(self._lastHref, url + ''); + } - if (uri.protocol) { - globalServer = uri.protocol + ':' + globalServer; - } - return globalServer; - }, + return origHistFunction.apply(this, arguments); + }; + }; - _handleOnErrorStackInfo: function() { - // if we are intentionally ignoring errors via onerror, bail out - if (!this._ignoreOnError) { - this._handleStackInfo.apply(this, arguments); - } - }, + fill(history, 'pushState', historyReplacementFunction, wrappedBuiltIns); + fill(history, 'replaceState', historyReplacementFunction, wrappedBuiltIns); + } - _handleStackInfo: function(stackInfo, options) { - var frames = this._prepareFrames(stackInfo, options); + if (autoBreadcrumbs.console && 'console' in _window && console.log) { + // console + var consoleMethodCallback = function(msg, data) { + self.captureBreadcrumb({ + message: msg, + level: data.level, + category: 'console' + }); + }; + + each(['debug', 'info', 'warn', 'error', 'log'], function(_, level) { + wrapConsoleMethod(console, level, consoleMethodCallback); + }); + } + }, - this._triggerEvent('handle', { - stackInfo: stackInfo, - options: options - }); + _restoreBuiltIns: function() { + // restore any wrapped builtins + var builtin; + while (this._wrappedBuiltIns.length) { + builtin = this._wrappedBuiltIns.shift(); - this._processException( - stackInfo.name, - stackInfo.message, - stackInfo.url, - stackInfo.lineno, - frames, - options - ); - }, - - _prepareFrames: function(stackInfo, options) { - var self = this; - var frames = []; - if (stackInfo.stack && stackInfo.stack.length) { - each(stackInfo.stack, function(i, stack) { - var frame = self._normalizeFrame(stack, stackInfo.url); - if (frame) { - frames.push(frame); - } - }); - - // e.g. frames captured via captureMessage throw - if (options && options.trimHeadFrames) { - for ( - var j = 0; - j < options.trimHeadFrames && j < frames.length; - j++ - ) { - frames[j].in_app = false; - } - } - } - frames = frames.slice(0, this._globalOptions.stackTraceLimit); - return frames; - }, - - _normalizeFrame: function(frame, stackInfoUrl) { - // normalize the frames data - var normalized = { - filename: frame.url, - lineno: frame.line, - colno: frame.column, - function: frame.func || '?' - }; + var obj = builtin[0], + name = builtin[1], + orig = builtin[2]; - // Case when we don't have any information about the error - // E.g. throwing a string or raw object, instead of an `Error` in Firefox - // Generating synthetic error doesn't add any value here - // - // We should probably somehow let a user know that they should fix their code - if (!frame.url) { - normalized.filename = stackInfoUrl; // fallback to whole stacks url from onerror handler - } + obj[name] = orig; + } + }, + + _drainPlugins: function() { + var self = this; + + // FIX ME TODO + each(this._plugins, function(_, plugin) { + var installer = plugin[0]; + var args = plugin[1]; + installer.apply(self, [self].concat(args)); + }); + }, + + _parseDSN: function(str) { + var m = dsnPattern.exec(str), + dsn = {}, + i = 7; + + try { + while (i--) dsn[dsnKeys[i]] = m[i] || ''; + } catch (e) { + throw new RavenConfigError('Invalid DSN: ' + str); + } - normalized.in_app = !// determine if an exception came from outside of our app - // first we check the global includePaths list. - ( - (!!this._globalOptions.includePaths.test && - !this._globalOptions.includePaths.test(normalized.filename)) || - // Now we check for fun, if the function name is Raven or TraceKit - /(Raven|TraceKit)\./.test(normalized['function']) || - // finally, we do a last ditch effort and check for raven.min.js - /raven\.(min\.)?js$/.test(normalized.filename) - ); - - return normalized; - }, - - _processException: function( - type, - message, - fileurl, - lineno, - frames, - options - ) { - var testString = (type || '') + ': ' + (message || ''); - - if ( - !!this._globalOptions.ignoreErrors.test && - this._globalOptions.ignoreErrors.test(testString) - ) - return; - - var stacktrace; - - if (frames && frames.length) { - fileurl = frames[0].filename || fileurl; - // Sentry expects frames oldest to newest - // and JS sends them as newest to oldest - frames.reverse(); - stacktrace = {frames: frames}; - } else if (fileurl) { - stacktrace = { - frames: [ - { - filename: fileurl, - lineno: lineno, - in_app: true - } - ] - }; - } + if (dsn.pass && !this._globalOptions.allowSecretKey) { + throw new RavenConfigError( + 'Do not specify your secret key in the DSN. See: http://bit.ly/raven-secret-key' + ); + } - if ( - !!this._globalOptions.ignoreUrls.test && - this._globalOptions.ignoreUrls.test(fileurl) - ) - return; - if ( - !!this._globalOptions.whitelistUrls.test && - !this._globalOptions.whitelistUrls.test(fileurl) - ) - return; - - var data = objectMerge( - { - // sentry.interfaces.Exception - exception: { - values: [ - { - type: type, - value: message, - stacktrace: stacktrace - } - ] - }, - culprit: fileurl - }, - options - ); - - // Fire away! - this._send(data); - }, - - _trimPacket: function(data) { - // For now, we only want to truncate the two different messages - // but this could/should be expanded to just trim everything - var max = this._globalOptions.maxMessageLength; - if (data.message) { - data.message = truncate(data.message, max); - } - if (data.exception) { - var exception = data.exception.values[0]; - exception.value = truncate(exception.value, max); - } + return dsn; + }, - var request = data.request; - if (request) { - if (request.url) { - request.url = truncate(request.url, this._globalOptions.maxUrlLength); - } - if (request.Referer) { - request.Referer = truncate( - request.Referer, - this._globalOptions.maxUrlLength - ); - } - } + _getGlobalServer: function(uri) { + // assemble the endpoint from the uri pieces + var globalServer = '//' + uri.host + (uri.port ? ':' + uri.port : ''); + + if (uri.protocol) { + globalServer = uri.protocol + ':' + globalServer; + } + return globalServer; + }, + + _handleOnErrorStackInfo: function() { + // if we are intentionally ignoring errors via onerror, bail out + if (!this._ignoreOnError) { + this._handleStackInfo.apply(this, arguments); + } + }, + + _handleStackInfo: function(stackInfo, options) { + var frames = this._prepareFrames(stackInfo, options); + + this._triggerEvent('handle', { + stackInfo: stackInfo, + options: options + }); + + this._processException( + stackInfo.name, + stackInfo.message, + stackInfo.url, + stackInfo.lineno, + frames, + options + ); + }, + + _prepareFrames: function(stackInfo, options) { + var self = this; + var frames = []; + if (stackInfo.stack && stackInfo.stack.length) { + each(stackInfo.stack, function(i, stack) { + var frame = self._normalizeFrame(stack, stackInfo.url); + if (frame) { + frames.push(frame); + } + }); + + // e.g. frames captured via captureMessage throw + if (options && options.trimHeadFrames) { + for (var j = 0; j < options.trimHeadFrames && j < frames.length; j++) { + frames[j].in_app = false; + } + } + } + frames = frames.slice(0, this._globalOptions.stackTraceLimit); + return frames; + }, + + _normalizeFrame: function(frame, stackInfoUrl) { + // normalize the frames data + var normalized = { + filename: frame.url, + lineno: frame.line, + colno: frame.column, + function: frame.func || '?' + }; + + // Case when we don't have any information about the error + // E.g. throwing a string or raw object, instead of an `Error` in Firefox + // Generating synthetic error doesn't add any value here + // + // We should probably somehow let a user know that they should fix their code + if (!frame.url) { + normalized.filename = stackInfoUrl; // fallback to whole stacks url from onerror handler + } + + normalized.in_app = !// determine if an exception came from outside of our app + // first we check the global includePaths list. + ( + (!!this._globalOptions.includePaths.test && + !this._globalOptions.includePaths.test(normalized.filename)) || + // Now we check for fun, if the function name is Raven or TraceKit + /(Raven|TraceKit)\./.test(normalized['function']) || + // finally, we do a last ditch effort and check for raven.min.js + /raven\.(min\.)?js$/.test(normalized.filename) + ); + + return normalized; + }, + + _processException: function(type, message, fileurl, lineno, frames, options) { + var prefixedMessage = (type ? type + ': ' : '') + (message || ''); + if ( + !!this._globalOptions.ignoreErrors.test && + (this._globalOptions.ignoreErrors.test(message) || + this._globalOptions.ignoreErrors.test(prefixedMessage)) + ) { + return; + } + + var stacktrace; + + if (frames && frames.length) { + fileurl = frames[0].filename || fileurl; + // Sentry expects frames oldest to newest + // and JS sends them as newest to oldest + frames.reverse(); + stacktrace = {frames: frames}; + } else if (fileurl) { + stacktrace = { + frames: [ + { + filename: fileurl, + lineno: lineno, + in_app: true + } + ] + }; + } + + if ( + !!this._globalOptions.ignoreUrls.test && + this._globalOptions.ignoreUrls.test(fileurl) + ) { + return; + } - if (data.breadcrumbs && data.breadcrumbs.values) - this._trimBreadcrumbs(data.breadcrumbs); + if ( + !!this._globalOptions.whitelistUrls.test && + !this._globalOptions.whitelistUrls.test(fileurl) + ) { + return; + } + + var data = objectMerge( + { + // sentry.interfaces.Exception + exception: { + values: [ + { + type: type, + value: message, + stacktrace: stacktrace + } + ] + }, + culprit: fileurl + }, + options + ); + + // Fire away! + this._send(data); + }, + + _trimPacket: function(data) { + // For now, we only want to truncate the two different messages + // but this could/should be expanded to just trim everything + var max = this._globalOptions.maxMessageLength; + if (data.message) { + data.message = truncate(data.message, max); + } + if (data.exception) { + var exception = data.exception.values[0]; + exception.value = truncate(exception.value, max); + } - return data; - }, + var request = data.request; + if (request) { + if (request.url) { + request.url = truncate(request.url, this._globalOptions.maxUrlLength); + } + if (request.Referer) { + request.Referer = truncate(request.Referer, this._globalOptions.maxUrlLength); + } + } - /** + if (data.breadcrumbs && data.breadcrumbs.values) + this._trimBreadcrumbs(data.breadcrumbs); + + return data; + }, + + /** * Truncate breadcrumb values (right now just URLs) */ - _trimBreadcrumbs: function(breadcrumbs) { - // known breadcrumb properties with urls - // TODO: also consider arbitrary prop values that start with (https?)?:// - var urlProps = ['to', 'from', 'url'], - urlProp, - crumb, - data; - - for (var i = 0; i < breadcrumbs.values.length; ++i) { - crumb = breadcrumbs.values[i]; - if ( - !crumb.hasOwnProperty('data') || - !isObject(crumb.data) || - objectFrozen(crumb.data) - ) - continue; - - data = objectMerge({}, crumb.data); - for (var j = 0; j < urlProps.length; ++j) { - urlProp = urlProps[j]; - if (data.hasOwnProperty(urlProp) && data[urlProp]) { - data[urlProp] = truncate( - data[urlProp], - this._globalOptions.maxUrlLength - ); - } - } - breadcrumbs.values[i].data = data; - } - }, + _trimBreadcrumbs: function(breadcrumbs) { + // known breadcrumb properties with urls + // TODO: also consider arbitrary prop values that start with (https?)?:// + var urlProps = ['to', 'from', 'url'], + urlProp, + crumb, + data; + + for (var i = 0; i < breadcrumbs.values.length; ++i) { + crumb = breadcrumbs.values[i]; + if ( + !crumb.hasOwnProperty('data') || + !isObject(crumb.data) || + objectFrozen(crumb.data) + ) + continue; + + data = objectMerge({}, crumb.data); + for (var j = 0; j < urlProps.length; ++j) { + urlProp = urlProps[j]; + if (data.hasOwnProperty(urlProp) && data[urlProp]) { + data[urlProp] = truncate(data[urlProp], this._globalOptions.maxUrlLength); + } + } + breadcrumbs.values[i].data = data; + } + }, - _getHttpData: function() { - if (!this._hasNavigator && !this._hasDocument) return; - var httpData = {}; + _getHttpData: function() { + if (!this._hasNavigator && !this._hasDocument) return; + var httpData = {}; - if (this._hasNavigator && _navigator.userAgent) { - httpData.headers = { - 'User-Agent': navigator.userAgent - }; - } + if (this._hasNavigator && _navigator.userAgent) { + httpData.headers = { + 'User-Agent': navigator.userAgent + }; + } - if (this._hasDocument) { - if (_document.location && _document.location.href) { - httpData.url = _document.location.href; - } - if (_document.referrer) { - if (!httpData.headers) httpData.headers = {}; - httpData.headers.Referer = _document.referrer; - } - } + if (this._hasDocument) { + if (_document.location && _document.location.href) { + httpData.url = _document.location.href; + } + if (_document.referrer) { + if (!httpData.headers) httpData.headers = {}; + httpData.headers.Referer = _document.referrer; + } + } - return httpData; - }, + return httpData; + }, - _resetBackoff: function() { - this._backoffDuration = 0; - this._backoffStart = null; - }, + _resetBackoff: function() { + this._backoffDuration = 0; + this._backoffStart = null; + }, - _shouldBackoff: function() { - return ( - this._backoffDuration && - now() - this._backoffStart < this._backoffDuration - ); - }, + _shouldBackoff: function() { + return this._backoffDuration && now() - this._backoffStart < this._backoffDuration; + }, - /** + /** * Returns true if the in-process data payload matches the signature * of the previously-sent data * @@ -1786,362 +1719,449 @@ * other old browsers). This can take the form of an "exception" * data object with a single frame (derived from the onerror args). */ - _isRepeatData: function(current) { - var last = this._lastData; - - if ( - !last || - current.message !== last.message || // defined for captureMessage - current.culprit !== last.culprit // defined for captureException/onerror - ) - return false; - - // Stacktrace interface (i.e. from captureMessage) - if (current.stacktrace || last.stacktrace) { - return isSameStacktrace(current.stacktrace, last.stacktrace); - } else if (current.exception || last.exception) { - // Exception interface (i.e. from captureException/onerror) - return isSameException(current.exception, last.exception); - } + _isRepeatData: function(current) { + var last = this._lastData; + + if ( + !last || + current.message !== last.message || // defined for captureMessage + current.culprit !== last.culprit // defined for captureException/onerror + ) + return false; + + // Stacktrace interface (i.e. from captureMessage) + if (current.stacktrace || last.stacktrace) { + return isSameStacktrace(current.stacktrace, last.stacktrace); + } else if (current.exception || last.exception) { + // Exception interface (i.e. from captureException/onerror) + return isSameException(current.exception, last.exception); + } - return true; - }, + return true; + }, - _setBackoffState: function(request) { - // If we are already in a backoff state, don't change anything - if (this._shouldBackoff()) { - return; - } + _setBackoffState: function(request) { + // If we are already in a backoff state, don't change anything + if (this._shouldBackoff()) { + return; + } - var status = request.status; + var status = request.status; + + // 400 - project_id doesn't exist or some other fatal + // 401 - invalid/revoked dsn + // 429 - too many requests + if (!(status === 400 || status === 401 || status === 429)) return; + + var retry; + try { + // If Retry-After is not in Access-Control-Expose-Headers, most + // browsers will throw an exception trying to access it + retry = request.getResponseHeader('Retry-After'); + retry = parseInt(retry, 10) * 1000; // Retry-After is returned in seconds + } catch (e) { + /* eslint no-empty:0 */ + } - // 400 - project_id doesn't exist or some other fatal - // 401 - invalid/revoked dsn - // 429 - too many requests - if (!(status === 400 || status === 401 || status === 429)) return; + this._backoffDuration = retry + ? // If Sentry server returned a Retry-After value, use it + retry + : // Otherwise, double the last backoff duration (starts at 1 sec) + this._backoffDuration * 2 || 1000; - var retry; - try { - // If Retry-After is not in Access-Control-Expose-Headers, most - // browsers will throw an exception trying to access it - retry = request.getResponseHeader('Retry-After'); - retry = parseInt(retry, 10) * 1000; // Retry-After is returned in seconds - } catch (e) { - /* eslint no-empty:0 */ - } + this._backoffStart = now(); + }, - this._backoffDuration = retry - ? // If Sentry server returned a Retry-After value, use it - retry - : // Otherwise, double the last backoff duration (starts at 1 sec) - this._backoffDuration * 2 || 1000; + _send: function(data) { + var globalOptions = this._globalOptions; - this._backoffStart = now(); - }, + var baseData = { + project: this._globalProject, + logger: globalOptions.logger, + platform: 'javascript' + }, + httpData = this._getHttpData(); - _send: function(data) { - var globalOptions = this._globalOptions; + if (httpData) { + baseData.request = httpData; + } - var baseData = { - project: this._globalProject, - logger: globalOptions.logger, - platform: 'javascript' - }, - httpData = this._getHttpData(); + // HACK: delete `trimHeadFrames` to prevent from appearing in outbound payload + if (data.trimHeadFrames) delete data.trimHeadFrames; - if (httpData) { - baseData.request = httpData; - } + data = objectMerge(baseData, data); - // HACK: delete `trimHeadFrames` to prevent from appearing in outbound payload - if (data.trimHeadFrames) delete data.trimHeadFrames; - - data = objectMerge(baseData, data); - - // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge - data.tags = objectMerge( - objectMerge({}, this._globalContext.tags), - data.tags - ); - data.extra = objectMerge( - objectMerge({}, this._globalContext.extra), - data.extra - ); - - // Send along our own collected metadata with extra - data.extra['session:duration'] = now() - this._startTime; - - if (this._breadcrumbs && this._breadcrumbs.length > 0) { - // intentionally make shallow copy so that additions - // to breadcrumbs aren't accidentally sent in this request - data.breadcrumbs = { - values: [].slice.call(this._breadcrumbs, 0) - }; - } + // Merge in the tags and extra separately since objectMerge doesn't handle a deep merge + data.tags = objectMerge(objectMerge({}, this._globalContext.tags), data.tags); + data.extra = objectMerge(objectMerge({}, this._globalContext.extra), data.extra); - // If there are no tags/extra, strip the key from the payload alltogther. - if (isEmptyObject(data.tags)) delete data.tags; + // Send along our own collected metadata with extra + data.extra['session:duration'] = now() - this._startTime; - if (this._globalContext.user) { - // sentry.interfaces.User - data.user = this._globalContext.user; - } + if (this._breadcrumbs && this._breadcrumbs.length > 0) { + // intentionally make shallow copy so that additions + // to breadcrumbs aren't accidentally sent in this request + data.breadcrumbs = { + values: [].slice.call(this._breadcrumbs, 0) + }; + } - // Include the environment if it's defined in globalOptions - if (globalOptions.environment) - data.environment = globalOptions.environment; + // If there are no tags/extra, strip the key from the payload alltogther. + if (isEmptyObject(data.tags)) delete data.tags; - // Include the release if it's defined in globalOptions - if (globalOptions.release) data.release = globalOptions.release; + if (this._globalContext.user) { + // sentry.interfaces.User + data.user = this._globalContext.user; + } - // Include server_name if it's defined in globalOptions - if (globalOptions.serverName) data.server_name = globalOptions.serverName; + // Include the environment if it's defined in globalOptions + if (globalOptions.environment) data.environment = globalOptions.environment; - if (isFunction(globalOptions.dataCallback)) { - data = globalOptions.dataCallback(data) || data; - } + // Include the release if it's defined in globalOptions + if (globalOptions.release) data.release = globalOptions.release; - // Why?????????? - if (!data || isEmptyObject(data)) { - return; - } + // Include server_name if it's defined in globalOptions + if (globalOptions.serverName) data.server_name = globalOptions.serverName; - // Check if the request should be filtered or not - if ( - isFunction(globalOptions.shouldSendCallback) && - !globalOptions.shouldSendCallback(data) - ) { - return; - } + if (isFunction(globalOptions.dataCallback)) { + data = globalOptions.dataCallback(data) || data; + } - // Backoff state: Sentry server previously responded w/ an error (e.g. 429 - too many requests), - // so drop requests until "cool-off" period has elapsed. - if (this._shouldBackoff()) { - this._logDebug('warn', 'Raven dropped error due to backoff: ', data); - return; - } + // Why?????????? + if (!data || isEmptyObject(data)) { + return; + } - if (typeof globalOptions.sampleRate === 'number') { - if (Math.random() < globalOptions.sampleRate) { - this._sendProcessedPayload(data); - } - } else { - this._sendProcessedPayload(data); - } - }, + // Check if the request should be filtered or not + if ( + isFunction(globalOptions.shouldSendCallback) && + !globalOptions.shouldSendCallback(data) + ) { + return; + } + + // Backoff state: Sentry server previously responded w/ an error (e.g. 429 - too many requests), + // so drop requests until "cool-off" period has elapsed. + if (this._shouldBackoff()) { + this._logDebug('warn', 'Raven dropped error due to backoff: ', data); + return; + } - _getUuid: function() { - return uuid4(); - }, + if (typeof globalOptions.sampleRate === 'number') { + if (Math.random() < globalOptions.sampleRate) { + this._sendProcessedPayload(data); + } + } else { + this._sendProcessedPayload(data); + } + }, - _sendProcessedPayload: function(data, callback) { - var self = this; - var globalOptions = this._globalOptions; + _getUuid: function() { + return uuid4(); + }, - if (!this.isSetup()) return; + _sendProcessedPayload: function(data, callback) { + var self = this; + var globalOptions = this._globalOptions; - // Try and clean up the packet before sending by truncating long values - data = this._trimPacket(data); + if (!this.isSetup()) return; - // ideally duplicate error testing should occur *before* dataCallback/shouldSendCallback, - // but this would require copying an un-truncated copy of the data packet, which can be - // arbitrarily deep (extra_data) -- could be worthwhile? will revisit - if (!this._globalOptions.allowDuplicates && this._isRepeatData(data)) { - this._logDebug('warn', 'Raven dropped repeat event: ', data); - return; - } + // Try and clean up the packet before sending by truncating long values + data = this._trimPacket(data); - // Send along an event_id if not explicitly passed. - // This event_id can be used to reference the error within Sentry itself. - // Set lastEventId after we know the error should actually be sent - this._lastEventId = data.event_id || (data.event_id = this._getUuid()); + // ideally duplicate error testing should occur *before* dataCallback/shouldSendCallback, + // but this would require copying an un-truncated copy of the data packet, which can be + // arbitrarily deep (extra_data) -- could be worthwhile? will revisit + if (!this._globalOptions.allowDuplicates && this._isRepeatData(data)) { + this._logDebug('warn', 'Raven dropped repeat event: ', data); + return; + } - // Store outbound payload after trim - this._lastData = data; + // Send along an event_id if not explicitly passed. + // This event_id can be used to reference the error within Sentry itself. + // Set lastEventId after we know the error should actually be sent + this._lastEventId = data.event_id || (data.event_id = this._getUuid()); - this._logDebug('debug', 'Raven about to send:', data); + // Store outbound payload after trim + this._lastData = data; - var auth = { - sentry_version: '7', - sentry_client: 'raven-js/' + this.VERSION, - sentry_key: this._globalKey - }; + this._logDebug('debug', 'Raven about to send:', data); - if (this._globalSecret) { - auth.sentry_secret = this._globalSecret; - } + var auth = { + sentry_version: '7', + sentry_client: 'raven-js/' + this.VERSION, + sentry_key: this._globalKey + }; - var exception = data.exception && data.exception.values[0]; - this.captureBreadcrumb({ - category: 'sentry', - message: exception - ? (exception.type ? exception.type + ': ' : '') + exception.value - : data.message, - event_id: data.event_id, - level: data.level || 'error' // presume error unless specified - }); + if (this._globalSecret) { + auth.sentry_secret = this._globalSecret; + } - var url = this._globalEndpoint; - (globalOptions.transport || this._makeRequest).call(this, { - url: url, - auth: auth, - data: data, - options: globalOptions, - onSuccess: function success() { - self._resetBackoff(); - - self._triggerEvent('success', { - data: data, - src: url - }); - callback && callback(); - }, - onError: function failure(error) { - self._logDebug('error', 'Raven transport failed to send: ', error); - - if (error.request) { - self._setBackoffState(error.request); - } - - self._triggerEvent('failure', { - data: data, - src: url - }); - error = - error || - new Error('Raven send failed (no additional details provided)'); - callback && callback(error); - } - }); - }, - - _makeRequest: function(opts) { - var request = _window.XMLHttpRequest && new _window.XMLHttpRequest(); - if (!request) return; - - // if browser doesn't support CORS (e.g. IE7), we are out of luck - var hasCORS = - 'withCredentials' in request || typeof XDomainRequest !== 'undefined'; - - if (!hasCORS) return; - - var url = opts.url; - - if ('withCredentials' in request) { - request.onreadystatechange = function() { - if (request.readyState !== 4) { - return; - } else if (request.status === 200) { - opts.onSuccess && opts.onSuccess(); - } else if (opts.onError) { - var err = new Error('Sentry error code: ' + request.status); - err.request = request; - opts.onError(err); - } - }; - } else { - request = new XDomainRequest(); - // xdomainrequest cannot go http -> https (or vice versa), - // so always use protocol relative - url = url.replace(/^https?:/, ''); - - // onreadystatechange not supported by XDomainRequest - if (opts.onSuccess) { - request.onload = opts.onSuccess; - } - if (opts.onError) { - request.onerror = function() { - var err = new Error('Sentry error code: XDomainRequest'); - err.request = request; - opts.onError(err); - }; - } - } + var exception = data.exception && data.exception.values[0]; + + // only capture 'sentry' breadcrumb is autoBreadcrumbs is truthy + if ( + this._globalOptions.autoBreadcrumbs && + this._globalOptions.autoBreadcrumbs.sentry + ) { + this.captureBreadcrumb({ + category: 'sentry', + message: exception + ? (exception.type ? exception.type + ': ' : '') + exception.value + : data.message, + event_id: data.event_id, + level: data.level || 'error' // presume error unless specified + }); + } - // NOTE: auth is intentionally sent as part of query string (NOT as custom - // HTTP header) so as to avoid preflight CORS requests - request.open('POST', url + '?' + urlencode(opts.auth)); - request.send(stringify(opts.data)); - }, - - _logDebug: function(level) { - if (this._originalConsoleMethods[level] && this.debug) { - // In IE<10 console methods do not have their own 'apply' method - Function.prototype.apply.call( - this._originalConsoleMethods[level], - this._originalConsole, - [].slice.call(arguments, 1) - ); - } - }, - - _mergeContext: function(key, context) { - if (isUndefined(context)) { - delete this._globalContext[key]; - } else { - this._globalContext[key] = objectMerge( - this._globalContext[key] || {}, - context - ); - } - } - }; + var url = this._globalEndpoint; + (globalOptions.transport || this._makeRequest).call(this, { + url: url, + auth: auth, + data: data, + options: globalOptions, + onSuccess: function success() { + self._resetBackoff(); + + self._triggerEvent('success', { + data: data, + src: url + }); + callback && callback(); + }, + onError: function failure(error) { + self._logDebug('error', 'Raven transport failed to send: ', error); + + if (error.request) { + self._setBackoffState(error.request); + } + + self._triggerEvent('failure', { + data: data, + src: url + }); + error = error || new Error('Raven send failed (no additional details provided)'); + callback && callback(error); + } + }); + }, + + _makeRequest: function(opts) { + var request = _window.XMLHttpRequest && new _window.XMLHttpRequest(); + if (!request) return; + + // if browser doesn't support CORS (e.g. IE7), we are out of luck + var hasCORS = 'withCredentials' in request || typeof XDomainRequest !== 'undefined'; + + if (!hasCORS) return; + + var url = opts.url; + + if ('withCredentials' in request) { + request.onreadystatechange = function() { + if (request.readyState !== 4) { + return; + } else if (request.status === 200) { + opts.onSuccess && opts.onSuccess(); + } else if (opts.onError) { + var err = new Error('Sentry error code: ' + request.status); + err.request = request; + opts.onError(err); + } + }; + } else { + request = new XDomainRequest(); + // xdomainrequest cannot go http -> https (or vice versa), + // so always use protocol relative + url = url.replace(/^https?:/, ''); + + // onreadystatechange not supported by XDomainRequest + if (opts.onSuccess) { + request.onload = opts.onSuccess; + } + if (opts.onError) { + request.onerror = function() { + var err = new Error('Sentry error code: XDomainRequest'); + err.request = request; + opts.onError(err); + }; + } + } + + // NOTE: auth is intentionally sent as part of query string (NOT as custom + // HTTP header) so as to avoid preflight CORS requests + request.open('POST', url + '?' + urlencode(opts.auth)); + request.send(stringify(opts.data)); + }, + + _logDebug: function(level) { + if (this._originalConsoleMethods[level] && this.debug) { + // In IE<10 console methods do not have their own 'apply' method + Function.prototype.apply.call( + this._originalConsoleMethods[level], + this._originalConsole, + [].slice.call(arguments, 1) + ); + } + }, + + _mergeContext: function(key, context) { + if (isUndefined(context)) { + delete this._globalContext[key]; + } else { + this._globalContext[key] = objectMerge(this._globalContext[key] || {}, context); + } + } +}; + +// Deprecations +Raven.prototype.setUser = Raven.prototype.setUserContext; +Raven.prototype.setReleaseContext = Raven.prototype.setRelease; + +module.exports = Raven; - /*------------------------------------------------ - * utils +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"1":1,"2":2,"5":5,"6":6,"7":7}],4:[function(_dereq_,module,exports){ +(function (global){ +/** + * Enforces a single instance of the Raven client, and the + * main entry point for Raven. If you are a consumer of the + * Raven library, you SHOULD load this file (vs raven.js). + **/ + +var RavenConstructor = _dereq_(3); + +// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785) +var _window = + typeof window !== 'undefined' + ? window + : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; +var _Raven = _window.Raven; + +var Raven = new RavenConstructor(); + +/* + * Allow multiple versions of Raven to be installed. + * Strip Raven from the global context and returns the instance. * - * conditionally exported for test via Raven.utils - ================================================= + * @return {Raven} */ - var objectPrototype = Object.prototype; +Raven.noConflict = function() { + _window.Raven = _Raven; + return Raven; +}; + +Raven.afterLoad(); + +module.exports = Raven; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"3":3}],5:[function(_dereq_,module,exports){ +(function (global){ +var _window = + typeof window !== 'undefined' + ? window + : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function isObject(what) { + return typeof what === 'object' && what !== null; +} + +// Yanked from https://git.io/vS8DV re-used under CC0 +// with some tiny modifications +function isError(value) { + switch ({}.toString.call(value)) { + case '[object Error]': + return true; + case '[object Exception]': + return true; + case '[object DOMException]': + return true; + default: + return value instanceof Error; + } +} - function isUndefined(what) { - return what === void 0; - } +function isErrorEvent(value) { + return supportsErrorEvent() && {}.toString.call(value) === '[object ErrorEvent]'; +} - function isFunction(what) { - return typeof what === 'function'; - } +function isUndefined(what) { + return what === void 0; +} - function isString(what) { - return objectPrototype.toString.call(what) === '[object String]'; - } +function isFunction(what) { + return typeof what === 'function'; +} - function isEmptyObject(what) { - for (var _ in what) return false; // eslint-disable-line guard-for-in, no-unused-vars - return true; - } +function isString(what) { + return Object.prototype.toString.call(what) === '[object String]'; +} - function each(obj, callback) { - var i, j; +function isArray(what) { + return Object.prototype.toString.call(what) === '[object Array]'; +} - if (isUndefined(obj.length)) { - for (i in obj) { - if (hasKey(obj, i)) { - callback.call(null, i, obj[i]); - } - } - } else { - j = obj.length; - if (j) { - for (i = 0; i < j; i++) { - callback.call(null, i, obj[i]); - } - } - } - } +function isEmptyObject(what) { + for (var _ in what) { + if (what.hasOwnProperty(_)) { + return false; + } + } + return true; +} + +function supportsErrorEvent() { + try { + new ErrorEvent(''); // eslint-disable-line no-new + return true; + } catch (e) { + return false; + } +} - function objectMerge(obj1, obj2) { - if (!obj2) { - return obj1; - } - each(obj2, function(key, value) { - obj1[key] = value; - }); - return obj1; - } +function wrappedCallback(callback) { + function dataCallback(data, original) { + var normalizedData = callback(data) || data; + if (original) { + return original(normalizedData) || normalizedData; + } + return normalizedData; + } + + return dataCallback; +} + +function each(obj, callback) { + var i, j; + + if (isUndefined(obj.length)) { + for (i in obj) { + if (hasKey(obj, i)) { + callback.call(null, i, obj[i]); + } + } + } else { + j = obj.length; + if (j) { + for (i = 0; i < j; i++) { + callback.call(null, i, obj[i]); + } + } + } +} + +function objectMerge(obj1, obj2) { + if (!obj2) { + return obj1; + } + each(obj2, function(key, value) { + obj1[key] = value; + }); + return obj1; +} - /** +/** * This function is only used for react-native. * react-native freezes object that have already been sent over the * js bridge. We need this function in order to check if the object is frozen. @@ -2149,398 +2169,298 @@ * supported because it's not relevant for other "platforms". See related issue: * https://github.com/getsentry/react-native-sentry/issues/57 */ - function objectFrozen(obj) { - if (!Object.isFrozen) { - return false; - } - return Object.isFrozen(obj); - } +function objectFrozen(obj) { + if (!Object.isFrozen) { + return false; + } + return Object.isFrozen(obj); +} - function truncate(str, max) { - return !max || str.length <= max ? str : str.substr(0, max) + '\u2026'; - } +function truncate(str, max) { + return !max || str.length <= max ? str : str.substr(0, max) + '\u2026'; +} - /** +/** * hasKey, a better form of hasOwnProperty * Example: hasKey(MainHostObject, property) === true/false * * @param {Object} host object to check property * @param {string} key to check */ - function hasKey(object, key) { - return objectPrototype.hasOwnProperty.call(object, key); - } - - function joinRegExp(patterns) { - // Combine an array of regular expressions and strings into one large regexp - // Be mad. - var sources = [], - i = 0, - len = patterns.length, - pattern; - - for (; i < len; i++) { - pattern = patterns[i]; - if (isString(pattern)) { - // If it's a string, we need to escape it - // Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions - sources.push(pattern.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1')); - } else if (pattern && pattern.source) { - // If it's a regexp already, we want to extract the source - sources.push(pattern.source); - } - // Intentionally skip other cases - } - return new RegExp(sources.join('|'), 'i'); - } - - function urlencode(o) { - var pairs = []; - each(o, function(key, value) { - pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); - }); - return pairs.join('&'); - } - - // borrowed from https://tools.ietf.org/html/rfc3986#appendix-B - // intentionally using regex and not href parsing trick because React Native and other - // environments where DOM might not be available - function parseUrl(url) { - var match = url.match( - /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/ - ); - if (!match) return {}; - - // coerce to undefined values to empty string so we don't get 'undefined' - var query = match[6] || ''; - var fragment = match[8] || ''; - return { - protocol: match[2], - host: match[4], - path: match[5], - relative: match[5] + query + fragment // everything minus origin - }; - } - function uuid4() { - var crypto = _window.crypto || _window.msCrypto; - - if (!isUndefined(crypto) && crypto.getRandomValues) { - // Use window.crypto API if available - // eslint-disable-next-line no-undef - var arr = new Uint16Array(8); - crypto.getRandomValues(arr); - - // set 4 in byte 7 - arr[3] = (arr[3] & 0xfff) | 0x4000; - // set 2 most significant bits of byte 9 to '10' - arr[4] = (arr[4] & 0x3fff) | 0x8000; - - var pad = function(num) { - var v = num.toString(16); - while (v.length < 4) { - v = '0' + v; - } - return v; - }; - - return ( - pad(arr[0]) + - pad(arr[1]) + - pad(arr[2]) + - pad(arr[3]) + - pad(arr[4]) + - pad(arr[5]) + - pad(arr[6]) + - pad(arr[7]) - ); - } else { - // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523 - return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = (Math.random() * 16) | 0, - v = c === 'x' ? r : (r & 0x3) | 0x8; - return v.toString(16); - }); - } - } +function hasKey(object, key) { + return Object.prototype.hasOwnProperty.call(object, key); +} + +function joinRegExp(patterns) { + // Combine an array of regular expressions and strings into one large regexp + // Be mad. + var sources = [], + i = 0, + len = patterns.length, + pattern; + + for (; i < len; i++) { + pattern = patterns[i]; + if (isString(pattern)) { + // If it's a string, we need to escape it + // Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions + sources.push(pattern.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1')); + } else if (pattern && pattern.source) { + // If it's a regexp already, we want to extract the source + sources.push(pattern.source); + } + // Intentionally skip other cases + } + return new RegExp(sources.join('|'), 'i'); +} + +function urlencode(o) { + var pairs = []; + each(o, function(key, value) { + pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); + }); + return pairs.join('&'); +} + +// borrowed from https://tools.ietf.org/html/rfc3986#appendix-B +// intentionally using regex and not href parsing trick because React Native and other +// environments where DOM might not be available +function parseUrl(url) { + var match = url.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/); + if (!match) return {}; + + // coerce to undefined values to empty string so we don't get 'undefined' + var query = match[6] || ''; + var fragment = match[8] || ''; + return { + protocol: match[2], + host: match[4], + path: match[5], + relative: match[5] + query + fragment // everything minus origin + }; +} +function uuid4() { + var crypto = _window.crypto || _window.msCrypto; + + if (!isUndefined(crypto) && crypto.getRandomValues) { + // Use window.crypto API if available + // eslint-disable-next-line no-undef + var arr = new Uint16Array(8); + crypto.getRandomValues(arr); + + // set 4 in byte 7 + arr[3] = (arr[3] & 0xfff) | 0x4000; + // set 2 most significant bits of byte 9 to '10' + arr[4] = (arr[4] & 0x3fff) | 0x8000; + + var pad = function(num) { + var v = num.toString(16); + while (v.length < 4) { + v = '0' + v; + } + return v; + }; + + return ( + pad(arr[0]) + + pad(arr[1]) + + pad(arr[2]) + + pad(arr[3]) + + pad(arr[4]) + + pad(arr[5]) + + pad(arr[6]) + + pad(arr[7]) + ); + } else { + // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523 + return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = (Math.random() * 16) | 0, + v = c === 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); + } +} - /** +/** * Given a child DOM element, returns a query-selector statement describing that * and its ancestors * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz] * @param elem * @returns {string} */ - function htmlTreeAsString(elem) { - /* eslint no-extra-parens:0*/ - var MAX_TRAVERSE_HEIGHT = 5, - MAX_OUTPUT_LEN = 80, - out = [], - height = 0, - len = 0, - separator = ' > ', - sepLength = separator.length, - nextStr; - - while (elem && height++ < MAX_TRAVERSE_HEIGHT) { - nextStr = htmlElementAsString(elem); - // bail out if - // - nextStr is the 'html' element - // - the length of the string that would be created exceeds MAX_OUTPUT_LEN - // (ignore this limit if we are on the first iteration) - if ( - nextStr === 'html' || - (height > 1 && - len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN) - ) { - break; - } +function htmlTreeAsString(elem) { + /* eslint no-extra-parens:0*/ + var MAX_TRAVERSE_HEIGHT = 5, + MAX_OUTPUT_LEN = 80, + out = [], + height = 0, + len = 0, + separator = ' > ', + sepLength = separator.length, + nextStr; + + while (elem && height++ < MAX_TRAVERSE_HEIGHT) { + nextStr = htmlElementAsString(elem); + // bail out if + // - nextStr is the 'html' element + // - the length of the string that would be created exceeds MAX_OUTPUT_LEN + // (ignore this limit if we are on the first iteration) + if ( + nextStr === 'html' || + (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN) + ) { + break; + } - out.push(nextStr); + out.push(nextStr); - len += nextStr.length; - elem = elem.parentNode; - } + len += nextStr.length; + elem = elem.parentNode; + } - return out.reverse().join(separator); - } + return out.reverse().join(separator); +} - /** +/** * Returns a simple, query-selector representation of a DOM element * e.g. [HTMLElement] => input#foo.btn[name=baz] * @param HTMLElement * @returns {string} */ - function htmlElementAsString(elem) { - var out = [], - className, - classes, - key, - attr, - i; - - if (!elem || !elem.tagName) { - return ''; - } +function htmlElementAsString(elem) { + var out = [], + className, + classes, + key, + attr, + i; + + if (!elem || !elem.tagName) { + return ''; + } - out.push(elem.tagName.toLowerCase()); - if (elem.id) { - out.push('#' + elem.id); - } + out.push(elem.tagName.toLowerCase()); + if (elem.id) { + out.push('#' + elem.id); + } - className = elem.className; - if (className && isString(className)) { - classes = className.split(/\s+/); - for (i = 0; i < classes.length; i++) { - out.push('.' + classes[i]); - } - } - var attrWhitelist = ['type', 'name', 'title', 'alt']; - for (i = 0; i < attrWhitelist.length; i++) { - key = attrWhitelist[i]; - attr = elem.getAttribute(key); - if (attr) { - out.push('[' + key + '="' + attr + '"]'); - } - } - return out.join(''); - } + className = elem.className; + if (className && isString(className)) { + classes = className.split(/\s+/); + for (i = 0; i < classes.length; i++) { + out.push('.' + classes[i]); + } + } + var attrWhitelist = ['type', 'name', 'title', 'alt']; + for (i = 0; i < attrWhitelist.length; i++) { + key = attrWhitelist[i]; + attr = elem.getAttribute(key); + if (attr) { + out.push('[' + key + '="' + attr + '"]'); + } + } + return out.join(''); +} - /** +/** * Returns true if either a OR b is truthy, but not both */ - function isOnlyOneTruthy(a, b) { - return !!(!!a ^ !!b); - } +function isOnlyOneTruthy(a, b) { + return !!(!!a ^ !!b); +} - /** +/** * Returns true if the two input exception interfaces have the same content */ - function isSameException(ex1, ex2) { - if (isOnlyOneTruthy(ex1, ex2)) return false; +function isSameException(ex1, ex2) { + if (isOnlyOneTruthy(ex1, ex2)) return false; - ex1 = ex1.values[0]; - ex2 = ex2.values[0]; + ex1 = ex1.values[0]; + ex2 = ex2.values[0]; - if (ex1.type !== ex2.type || ex1.value !== ex2.value) return false; + if (ex1.type !== ex2.type || ex1.value !== ex2.value) return false; - return isSameStacktrace(ex1.stacktrace, ex2.stacktrace); - } + return isSameStacktrace(ex1.stacktrace, ex2.stacktrace); +} - /** +/** * Returns true if the two input stack trace interfaces have the same content */ - function isSameStacktrace(stack1, stack2) { - if (isOnlyOneTruthy(stack1, stack2)) return false; - - var frames1 = stack1.frames; - var frames2 = stack2.frames; - - // Exit early if frame count differs - if (frames1.length !== frames2.length) return false; - - // Iterate through every frame; bail out if anything differs - var a, b; - for (var i = 0; i < frames1.length; i++) { - a = frames1[i]; - b = frames2[i]; - if ( - a.filename !== b.filename || - a.lineno !== b.lineno || - a.colno !== b.colno || - a['function'] !== b['function'] - ) - return false; - } - return true; - } +function isSameStacktrace(stack1, stack2) { + if (isOnlyOneTruthy(stack1, stack2)) return false; + + var frames1 = stack1.frames; + var frames2 = stack2.frames; + + // Exit early if frame count differs + if (frames1.length !== frames2.length) return false; + + // Iterate through every frame; bail out if anything differs + var a, b; + for (var i = 0; i < frames1.length; i++) { + a = frames1[i]; + b = frames2[i]; + if ( + a.filename !== b.filename || + a.lineno !== b.lineno || + a.colno !== b.colno || + a['function'] !== b['function'] + ) + return false; + } + return true; +} - /** +/** * Polyfill a method * @param obj object e.g. `document` * @param name method name present on object e.g. `addEventListener` * @param replacement replacement function * @param track {optional} record instrumentation to an array */ - function fill(obj, name, replacement, track) { - var orig = obj[name]; - obj[name] = replacement(orig); - if (track) { - track.push([obj, name, orig]); - } - } - - if (typeof __DEV__ !== 'undefined' && __DEV__) { - Raven.utils = { - isUndefined: isUndefined, - isFunction: isFunction, - isString: isString, - isObject: isObject, - isEmptyObject: isEmptyObject, - isError: isError, - each: each, - objectMerge: objectMerge, - truncate: truncate, - hasKey: hasKey, - joinRegExp: joinRegExp, - urlencode: urlencode, - uuid4: uuid4, - htmlTreeAsString: htmlTreeAsString, - htmlElementAsString: htmlElementAsString, - parseUrl: parseUrl, - fill: fill - }; - } - - // Deprecations - Raven.prototype.setUser = Raven.prototype.setUserContext; - Raven.prototype.setReleaseContext = Raven.prototype.setRelease; - - module.exports = Raven; - }.call( - this, - typeof global !== 'undefined' - ? global - : typeof self !== 'undefined' - ? self - : typeof window !== 'undefined' ? window : {} - )); - }, - {'1': 1, '2': 2, '5': 5, '6': 6, '7': 7} - ], - 4: [ - function(_dereq_, module, exports) { - (function(global) { - /** - * Enforces a single instance of the Raven client, and the - * main entry point for Raven. If you are a consumer of the - * Raven library, you SHOULD load this file (vs raven.js). - **/ - - var RavenConstructor = _dereq_(3); - - // This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785) - var _window = - typeof window !== 'undefined' - ? window - : typeof global !== 'undefined' - ? global - : typeof self !== 'undefined' ? self : {}; - var _Raven = _window.Raven; - - var Raven = new RavenConstructor(); - - /* - * Allow multiple versions of Raven to be installed. - * Strip Raven from the global context and returns the instance. - * - * @return {Raven} - */ - Raven.noConflict = function() { - _window.Raven = _Raven; - return Raven; - }; - - Raven.afterLoad(); - - module.exports = Raven; - }.call( - this, - typeof global !== 'undefined' - ? global - : typeof self !== 'undefined' - ? self - : typeof window !== 'undefined' ? window : {} - )); - }, - {'3': 3} - ], - 5: [ - function(_dereq_, module, exports) { - function isObject(what) { - return typeof what === 'object' && what !== null; - } - - // Yanked from https://git.io/vS8DV re-used under CC0 - // with some tiny modifications - function isError(value) { - switch ({}.toString.call(value)) { - case '[object Error]': - return true; - case '[object Exception]': - return true; - case '[object DOMException]': - return true; - default: - return value instanceof Error; - } - } - - function wrappedCallback(callback) { - function dataCallback(data, original) { - var normalizedData = callback(data) || data; - if (original) { - return original(normalizedData) || normalizedData; - } - return normalizedData; - } - - return dataCallback; - } +function fill(obj, name, replacement, track) { + var orig = obj[name]; + obj[name] = replacement(orig); + obj[name].__raven__ = true; + obj[name].__orig__ = orig; + if (track) { + track.push([obj, name, orig]); + } +} + +module.exports = { + isObject: isObject, + isError: isError, + isErrorEvent: isErrorEvent, + isUndefined: isUndefined, + isFunction: isFunction, + isString: isString, + isArray: isArray, + isEmptyObject: isEmptyObject, + supportsErrorEvent: supportsErrorEvent, + wrappedCallback: wrappedCallback, + each: each, + objectMerge: objectMerge, + truncate: truncate, + objectFrozen: objectFrozen, + hasKey: hasKey, + joinRegExp: joinRegExp, + urlencode: urlencode, + uuid4: uuid4, + htmlTreeAsString: htmlTreeAsString, + htmlElementAsString: htmlElementAsString, + isSameException: isSameException, + isSameStacktrace: isSameStacktrace, + parseUrl: parseUrl, + fill: fill +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],6:[function(_dereq_,module,exports){ +(function (global){ +var utils = _dereq_(5); - module.exports = { - isObject: isObject, - isError: isError, - wrappedCallback: wrappedCallback - }; - }, - {} - ], - 6: [ - function(_dereq_, module, exports) { - (function(global) { - var utils = _dereq_(5); - - /* +/* TraceKit - Cross brower stack traces This was originally forked from github.com/occ/TraceKit, but has since been @@ -2550,33 +2470,31 @@ MIT license */ - var TraceKit = { - collectWindowErrors: true, - debug: false - }; +var TraceKit = { + collectWindowErrors: true, + debug: false +}; - // This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785) - var _window = - typeof window !== 'undefined' - ? window - : typeof global !== 'undefined' - ? global - : typeof self !== 'undefined' ? self : {}; +// This is to be defensive in environments where window does not exist (see https://github.com/getsentry/raven-js/pull/785) +var _window = + typeof window !== 'undefined' + ? window + : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - // global reference to slice - var _slice = [].slice; - var UNKNOWN_FUNCTION = '?'; +// global reference to slice +var _slice = [].slice; +var UNKNOWN_FUNCTION = '?'; - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types - var ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/; +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types +var ERROR_TYPES_RE = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/; - function getLocationHref() { - if (typeof document === 'undefined' || document.location == null) return ''; +function getLocationHref() { + if (typeof document === 'undefined' || document.location == null) return ''; - return document.location.href; - } + return document.location.href; +} - /** +/** * TraceKit.report: cross-browser processing of unhandled exceptions * * Syntax: @@ -2615,68 +2533,68 @@ * Handlers receive a stackInfo object as described in the * TraceKit.computeStackTrace docs. */ - TraceKit.report = (function reportModuleWrapper() { - var handlers = [], - lastArgs = null, - lastException = null, - lastExceptionStack = null; +TraceKit.report = (function reportModuleWrapper() { + var handlers = [], + lastArgs = null, + lastException = null, + lastExceptionStack = null; - /** + /** * Add a crash handler. * @param {Function} handler */ - function subscribe(handler) { - installGlobalHandler(); - handlers.push(handler); - } + function subscribe(handler) { + installGlobalHandler(); + handlers.push(handler); + } - /** + /** * Remove a crash handler. * @param {Function} handler */ - function unsubscribe(handler) { - for (var i = handlers.length - 1; i >= 0; --i) { - if (handlers[i] === handler) { - handlers.splice(i, 1); - } - } - } + function unsubscribe(handler) { + for (var i = handlers.length - 1; i >= 0; --i) { + if (handlers[i] === handler) { + handlers.splice(i, 1); + } + } + } - /** + /** * Remove all crash handlers. */ - function unsubscribeAll() { - uninstallGlobalHandler(); - handlers = []; - } + function unsubscribeAll() { + uninstallGlobalHandler(); + handlers = []; + } - /** + /** * Dispatch stack information to all handlers. * @param {Object.} stack */ - function notifyHandlers(stack, isWindowError) { - var exception = null; - if (isWindowError && !TraceKit.collectWindowErrors) { - return; - } - for (var i in handlers) { - if (handlers.hasOwnProperty(i)) { - try { - handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2))); - } catch (inner) { - exception = inner; - } - } - } + function notifyHandlers(stack, isWindowError) { + var exception = null; + if (isWindowError && !TraceKit.collectWindowErrors) { + return; + } + for (var i in handlers) { + if (handlers.hasOwnProperty(i)) { + try { + handlers[i].apply(null, [stack].concat(_slice.call(arguments, 2))); + } catch (inner) { + exception = inner; + } + } + } - if (exception) { - throw exception; - } - } + if (exception) { + throw exception; + } + } - var _oldOnerrorHandler, _onErrorHandlerInstalled; + var _oldOnerrorHandler, _onErrorHandlerInstalled; - /** + /** * Ensures all global unhandled exceptions are recorded. * Supported by Gecko and IE. * @param {string} message Error message. @@ -2687,135 +2605,132 @@ * occurred. * @param {?Error} ex The actual Error object. */ - function traceKitWindowOnError(message, url, lineNo, colNo, ex) { - var stack = null; - - if (lastExceptionStack) { - TraceKit.computeStackTrace.augmentStackTraceWithInitialElement( - lastExceptionStack, - url, - lineNo, - message - ); - processLastException(); - } else if (ex && utils.isError(ex)) { - // non-string `ex` arg; attempt to extract stack trace - - // New chrome and blink send along a real error object - // Let's just report that like a normal error. - // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror - stack = TraceKit.computeStackTrace(ex); - notifyHandlers(stack, true); - } else { - var location = { - url: url, - line: lineNo, - column: colNo - }; - - var name = undefined; - var msg = message; // must be new var or will modify original `arguments` - var groups; - if ({}.toString.call(message) === '[object String]') { - var groups = message.match(ERROR_TYPES_RE); - if (groups) { - name = groups[1]; - msg = groups[2]; - } - } + function traceKitWindowOnError(message, url, lineNo, colNo, ex) { + var stack = null; + + if (lastExceptionStack) { + TraceKit.computeStackTrace.augmentStackTraceWithInitialElement( + lastExceptionStack, + url, + lineNo, + message + ); + processLastException(); + } else if (ex && utils.isError(ex)) { + // non-string `ex` arg; attempt to extract stack trace + + // New chrome and blink send along a real error object + // Let's just report that like a normal error. + // See: https://mikewest.org/2013/08/debugging-runtime-errors-with-window-onerror + stack = TraceKit.computeStackTrace(ex); + notifyHandlers(stack, true); + } else { + var location = { + url: url, + line: lineNo, + column: colNo + }; + + var name = undefined; + var msg = message; // must be new var or will modify original `arguments` + var groups; + if ({}.toString.call(message) === '[object String]') { + var groups = message.match(ERROR_TYPES_RE); + if (groups) { + name = groups[1]; + msg = groups[2]; + } + } - location.func = UNKNOWN_FUNCTION; + location.func = UNKNOWN_FUNCTION; - stack = { - name: name, - message: msg, - url: getLocationHref(), - stack: [location] - }; - notifyHandlers(stack, true); - } + stack = { + name: name, + message: msg, + url: getLocationHref(), + stack: [location] + }; + notifyHandlers(stack, true); + } - if (_oldOnerrorHandler) { - return _oldOnerrorHandler.apply(this, arguments); - } + if (_oldOnerrorHandler) { + return _oldOnerrorHandler.apply(this, arguments); + } - return false; - } + return false; + } - function installGlobalHandler() { - if (_onErrorHandlerInstalled) { - return; - } - _oldOnerrorHandler = _window.onerror; - _window.onerror = traceKitWindowOnError; - _onErrorHandlerInstalled = true; - } + function installGlobalHandler() { + if (_onErrorHandlerInstalled) { + return; + } + _oldOnerrorHandler = _window.onerror; + _window.onerror = traceKitWindowOnError; + _onErrorHandlerInstalled = true; + } - function uninstallGlobalHandler() { - if (!_onErrorHandlerInstalled) { - return; - } - _window.onerror = _oldOnerrorHandler; - _onErrorHandlerInstalled = false; - _oldOnerrorHandler = undefined; - } + function uninstallGlobalHandler() { + if (!_onErrorHandlerInstalled) { + return; + } + _window.onerror = _oldOnerrorHandler; + _onErrorHandlerInstalled = false; + _oldOnerrorHandler = undefined; + } - function processLastException() { - var _lastExceptionStack = lastExceptionStack, - _lastArgs = lastArgs; - lastArgs = null; - lastExceptionStack = null; - lastException = null; - notifyHandlers.apply( - null, - [_lastExceptionStack, false].concat(_lastArgs) - ); - } + function processLastException() { + var _lastExceptionStack = lastExceptionStack, + _lastArgs = lastArgs; + lastArgs = null; + lastExceptionStack = null; + lastException = null; + notifyHandlers.apply(null, [_lastExceptionStack, false].concat(_lastArgs)); + } - /** + /** * Reports an unhandled Error to TraceKit. * @param {Error} ex * @param {?boolean} rethrow If false, do not re-throw the exception. * Only used for window.onerror to not cause an infinite loop of * rethrowing. */ - function report(ex, rethrow) { - var args = _slice.call(arguments, 1); - if (lastExceptionStack) { - if (lastException === ex) { - return; // already caught by an inner catch block, ignore - } else { - processLastException(); - } - } + function report(ex, rethrow) { + var args = _slice.call(arguments, 1); + if (lastExceptionStack) { + if (lastException === ex) { + return; // already caught by an inner catch block, ignore + } else { + processLastException(); + } + } - var stack = TraceKit.computeStackTrace(ex); - lastExceptionStack = stack; - lastException = ex; - lastArgs = args; - - // If the stack trace is incomplete, wait for 2 seconds for - // slow slow IE to see if onerror occurs or not before reporting - // this exception; otherwise, we will end up with an incomplete - // stack trace - setTimeout(function() { - if (lastException === ex) { - processLastException(); - } - }, stack.incomplete ? 2000 : 0); + var stack = TraceKit.computeStackTrace(ex); + lastExceptionStack = stack; + lastException = ex; + lastArgs = args; + + // If the stack trace is incomplete, wait for 2 seconds for + // slow slow IE to see if onerror occurs or not before reporting + // this exception; otherwise, we will end up with an incomplete + // stack trace + setTimeout(function() { + if (lastException === ex) { + processLastException(); + } + }, stack.incomplete ? 2000 : 0); - if (rethrow !== false) { - throw ex; // re-throw to propagate to the top level (and cause window.onerror) - } - } + if (rethrow !== false) { + throw ex; // re-throw to propagate to the top level (and cause window.onerror) + } + } - report.subscribe = subscribe; - report.unsubscribe = unsubscribe; - report.uninstall = unsubscribeAll; - return report; - })(); + report.subscribe = subscribe; + report.unsubscribe = unsubscribe; + report.uninstall = unsubscribeAll; + return report; +})(); - /** +/** * TraceKit.computeStackTrace: cross-browser stack traces in JavaScript * * Syntax: @@ -2866,140 +2781,136 @@ * inner function that actually caused the exception). * */ - TraceKit.computeStackTrace = (function computeStackTraceWrapper() { - // Contents of Exception in various browsers. - // - // SAFARI: - // ex.message = Can't find variable: qq - // ex.line = 59 - // ex.sourceId = 580238192 - // ex.sourceURL = http://... - // ex.expressionBeginOffset = 96 - // ex.expressionCaretOffset = 98 - // ex.expressionEndOffset = 98 - // ex.name = ReferenceError - // - // FIREFOX: - // ex.message = qq is not defined - // ex.fileName = http://... - // ex.lineNumber = 59 - // ex.columnNumber = 69 - // ex.stack = ...stack trace... (see the example below) - // ex.name = ReferenceError - // - // CHROME: - // ex.message = qq is not defined - // ex.name = ReferenceError - // ex.type = not_defined - // ex.arguments = ['aa'] - // ex.stack = ...stack trace... - // - // INTERNET EXPLORER: - // ex.message = ... - // ex.name = ReferenceError - // - // OPERA: - // ex.message = ...message... (see the example below) - // ex.name = ReferenceError - // ex.opera#sourceloc = 11 (pretty much useless, duplicates the info in ex.message) - // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace' - - /** +TraceKit.computeStackTrace = (function computeStackTraceWrapper() { + // Contents of Exception in various browsers. + // + // SAFARI: + // ex.message = Can't find variable: qq + // ex.line = 59 + // ex.sourceId = 580238192 + // ex.sourceURL = http://... + // ex.expressionBeginOffset = 96 + // ex.expressionCaretOffset = 98 + // ex.expressionEndOffset = 98 + // ex.name = ReferenceError + // + // FIREFOX: + // ex.message = qq is not defined + // ex.fileName = http://... + // ex.lineNumber = 59 + // ex.columnNumber = 69 + // ex.stack = ...stack trace... (see the example below) + // ex.name = ReferenceError + // + // CHROME: + // ex.message = qq is not defined + // ex.name = ReferenceError + // ex.type = not_defined + // ex.arguments = ['aa'] + // ex.stack = ...stack trace... + // + // INTERNET EXPLORER: + // ex.message = ... + // ex.name = ReferenceError + // + // OPERA: + // ex.message = ...message... (see the example below) + // ex.name = ReferenceError + // ex.opera#sourceloc = 11 (pretty much useless, duplicates the info in ex.message) + // ex.stacktrace = n/a; see 'opera:config#UserPrefs|Exceptions Have Stacktrace' + + /** * Computes stack trace information from the stack property. * Chrome and Gecko use this property. * @param {Error} ex * @return {?Object.} Stack trace information. */ - function computeStackTraceFromStackProp(ex) { - if (typeof ex.stack === 'undefined' || !ex.stack) return; - - var chrome = /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack||\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i, - gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i, - winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i, - // Used to additionally parse URL/line/column from eval frames - geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i, - chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/, - lines = ex.stack.split('\n'), - stack = [], - submatch, - parts, - element, - reference = /^(.*) is undefined$/.exec(ex.message); - - for (var i = 0, j = lines.length; i < j; ++i) { - if ((parts = chrome.exec(lines[i]))) { - var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line - var isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line - if (isEval && (submatch = chromeEval.exec(parts[2]))) { - // throw out eval line/column and use top-most line/column number - parts[2] = submatch[1]; // url - parts[3] = submatch[2]; // line - parts[4] = submatch[3]; // column - } - element = { - url: !isNative ? parts[2] : null, - func: parts[1] || UNKNOWN_FUNCTION, - args: isNative ? [parts[2]] : [], - line: parts[3] ? +parts[3] : null, - column: parts[4] ? +parts[4] : null - }; - } else if ((parts = winjs.exec(lines[i]))) { - element = { - url: parts[2], - func: parts[1] || UNKNOWN_FUNCTION, - args: [], - line: +parts[3], - column: parts[4] ? +parts[4] : null - }; - } else if ((parts = gecko.exec(lines[i]))) { - var isEval = parts[3] && parts[3].indexOf(' > eval') > -1; - if (isEval && (submatch = geckoEval.exec(parts[3]))) { - // throw out eval line/column and use top-most line number - parts[3] = submatch[1]; - parts[4] = submatch[2]; - parts[5] = null; // no column when eval - } else if ( - i === 0 && - !parts[5] && - typeof ex.columnNumber !== 'undefined' - ) { - // FireFox uses this awesome columnNumber property for its top frame - // Also note, Firefox's column number is 0-based and everything else expects 1-based, - // so adding 1 - // NOTE: this hack doesn't work if top-most frame is eval - stack[0].column = ex.columnNumber + 1; - } - element = { - url: parts[3], - func: parts[1] || UNKNOWN_FUNCTION, - args: parts[2] ? parts[2].split(',') : [], - line: parts[4] ? +parts[4] : null, - column: parts[5] ? +parts[5] : null - }; - } else { - continue; - } + function computeStackTraceFromStackProp(ex) { + if (typeof ex.stack === 'undefined' || !ex.stack) return; + + var chrome = /^\s*at (.*?) ?\(((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i, + gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)((?:file|https?|blob|chrome|webpack|resource|\[native).*?|[^@]*bundle)(?::(\d+))?(?::(\d+))?\s*$/i, + winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i, + // Used to additionally parse URL/line/column from eval frames + geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i, + chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/, + lines = ex.stack.split('\n'), + stack = [], + submatch, + parts, + element, + reference = /^(.*) is undefined$/.exec(ex.message); + + for (var i = 0, j = lines.length; i < j; ++i) { + if ((parts = chrome.exec(lines[i]))) { + var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line + var isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line + if (isEval && (submatch = chromeEval.exec(parts[2]))) { + // throw out eval line/column and use top-most line/column number + parts[2] = submatch[1]; // url + parts[3] = submatch[2]; // line + parts[4] = submatch[3]; // column + } + element = { + url: !isNative ? parts[2] : null, + func: parts[1] || UNKNOWN_FUNCTION, + args: isNative ? [parts[2]] : [], + line: parts[3] ? +parts[3] : null, + column: parts[4] ? +parts[4] : null + }; + } else if ((parts = winjs.exec(lines[i]))) { + element = { + url: parts[2], + func: parts[1] || UNKNOWN_FUNCTION, + args: [], + line: +parts[3], + column: parts[4] ? +parts[4] : null + }; + } else if ((parts = gecko.exec(lines[i]))) { + var isEval = parts[3] && parts[3].indexOf(' > eval') > -1; + if (isEval && (submatch = geckoEval.exec(parts[3]))) { + // throw out eval line/column and use top-most line number + parts[3] = submatch[1]; + parts[4] = submatch[2]; + parts[5] = null; // no column when eval + } else if (i === 0 && !parts[5] && typeof ex.columnNumber !== 'undefined') { + // FireFox uses this awesome columnNumber property for its top frame + // Also note, Firefox's column number is 0-based and everything else expects 1-based, + // so adding 1 + // NOTE: this hack doesn't work if top-most frame is eval + stack[0].column = ex.columnNumber + 1; + } + element = { + url: parts[3], + func: parts[1] || UNKNOWN_FUNCTION, + args: parts[2] ? parts[2].split(',') : [], + line: parts[4] ? +parts[4] : null, + column: parts[5] ? +parts[5] : null + }; + } else { + continue; + } - if (!element.func && element.line) { - element.func = UNKNOWN_FUNCTION; - } + if (!element.func && element.line) { + element.func = UNKNOWN_FUNCTION; + } - stack.push(element); - } + stack.push(element); + } - if (!stack.length) { - return null; - } + if (!stack.length) { + return null; + } - return { - name: ex.name, - message: ex.message, - url: getLocationHref(), - stack: stack - }; - } + return { + name: ex.name, + message: ex.message, + url: getLocationHref(), + stack: stack + }; + } - /** + /** * Adds information about the first frame to incomplete stack traces. * Safari and IE require this to get complete data on the first frame. * @param {Object.} stackInfo Stack trace information from @@ -3012,49 +2923,44 @@ * @return {boolean} Whether or not the stack information was * augmented. */ - function augmentStackTraceWithInitialElement( - stackInfo, - url, - lineNo, - message - ) { - var initial = { - url: url, - line: lineNo - }; + function augmentStackTraceWithInitialElement(stackInfo, url, lineNo, message) { + var initial = { + url: url, + line: lineNo + }; - if (initial.url && initial.line) { - stackInfo.incomplete = false; + if (initial.url && initial.line) { + stackInfo.incomplete = false; - if (!initial.func) { - initial.func = UNKNOWN_FUNCTION; - } + if (!initial.func) { + initial.func = UNKNOWN_FUNCTION; + } - if (stackInfo.stack.length > 0) { - if (stackInfo.stack[0].url === initial.url) { - if (stackInfo.stack[0].line === initial.line) { - return false; // already in stack trace - } else if ( - !stackInfo.stack[0].line && - stackInfo.stack[0].func === initial.func - ) { - stackInfo.stack[0].line = initial.line; - return false; - } - } - } + if (stackInfo.stack.length > 0) { + if (stackInfo.stack[0].url === initial.url) { + if (stackInfo.stack[0].line === initial.line) { + return false; // already in stack trace + } else if ( + !stackInfo.stack[0].line && + stackInfo.stack[0].func === initial.func + ) { + stackInfo.stack[0].line = initial.line; + return false; + } + } + } - stackInfo.stack.unshift(initial); - stackInfo.partial = true; - return true; - } else { - stackInfo.incomplete = true; - } + stackInfo.stack.unshift(initial); + stackInfo.partial = true; + return true; + } else { + stackInfo.incomplete = true; + } - return false; - } + return false; + } - /** + /** * Computes stack trace information by walking the arguments.caller * chain at the time the exception occurred. This will cause earlier * frames to be missed but is the only way to get any stack trace in @@ -3063,132 +2969,122 @@ * @param {Error} ex * @return {?Object.} Stack trace information. */ - function computeStackTraceByWalkingCallerChain(ex, depth) { - var functionName = /function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i, - stack = [], - funcs = {}, - recursion = false, - parts, - item, - source; - - for ( - var curr = computeStackTraceByWalkingCallerChain.caller; - curr && !recursion; - curr = curr.caller - ) { - if (curr === computeStackTrace || curr === TraceKit.report) { - // console.log('skipping internal function'); - continue; - } + function computeStackTraceByWalkingCallerChain(ex, depth) { + var functionName = /function\s+([_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)?\s*\(/i, + stack = [], + funcs = {}, + recursion = false, + parts, + item, + source; + + for ( + var curr = computeStackTraceByWalkingCallerChain.caller; + curr && !recursion; + curr = curr.caller + ) { + if (curr === computeStackTrace || curr === TraceKit.report) { + // console.log('skipping internal function'); + continue; + } - item = { - url: null, - func: UNKNOWN_FUNCTION, - line: null, - column: null - }; - - if (curr.name) { - item.func = curr.name; - } else if ((parts = functionName.exec(curr.toString()))) { - item.func = parts[1]; - } + item = { + url: null, + func: UNKNOWN_FUNCTION, + line: null, + column: null + }; + + if (curr.name) { + item.func = curr.name; + } else if ((parts = functionName.exec(curr.toString()))) { + item.func = parts[1]; + } - if (typeof item.func === 'undefined') { - try { - item.func = parts.input.substring(0, parts.input.indexOf('{')); - } catch (e) {} - } + if (typeof item.func === 'undefined') { + try { + item.func = parts.input.substring(0, parts.input.indexOf('{')); + } catch (e) {} + } - if (funcs['' + curr]) { - recursion = true; - } else { - funcs['' + curr] = true; - } + if (funcs['' + curr]) { + recursion = true; + } else { + funcs['' + curr] = true; + } - stack.push(item); - } + stack.push(item); + } - if (depth) { - // console.log('depth is ' + depth); - // console.log('stack is ' + stack.length); - stack.splice(0, depth); - } + if (depth) { + // console.log('depth is ' + depth); + // console.log('stack is ' + stack.length); + stack.splice(0, depth); + } - var result = { - name: ex.name, - message: ex.message, - url: getLocationHref(), - stack: stack - }; - augmentStackTraceWithInitialElement( - result, - ex.sourceURL || ex.fileName, - ex.line || ex.lineNumber, - ex.message || ex.description - ); - return result; - } + var result = { + name: ex.name, + message: ex.message, + url: getLocationHref(), + stack: stack + }; + augmentStackTraceWithInitialElement( + result, + ex.sourceURL || ex.fileName, + ex.line || ex.lineNumber, + ex.message || ex.description + ); + return result; + } - /** + /** * Computes a stack trace for an exception. * @param {Error} ex * @param {(string|number)=} depth */ - function computeStackTrace(ex, depth) { - var stack = null; - depth = depth == null ? 0 : +depth; + function computeStackTrace(ex, depth) { + var stack = null; + depth = depth == null ? 0 : +depth; + + try { + stack = computeStackTraceFromStackProp(ex); + if (stack) { + return stack; + } + } catch (e) { + if (TraceKit.debug) { + throw e; + } + } - try { - stack = computeStackTraceFromStackProp(ex); - if (stack) { - return stack; - } - } catch (e) { - if (TraceKit.debug) { - throw e; - } - } + try { + stack = computeStackTraceByWalkingCallerChain(ex, depth + 1); + if (stack) { + return stack; + } + } catch (e) { + if (TraceKit.debug) { + throw e; + } + } + return { + name: ex.name, + message: ex.message, + url: getLocationHref() + }; + } - try { - stack = computeStackTraceByWalkingCallerChain(ex, depth + 1); - if (stack) { - return stack; - } - } catch (e) { - if (TraceKit.debug) { - throw e; - } - } - return { - name: ex.name, - message: ex.message, - url: getLocationHref() - }; - } + computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement; + computeStackTrace.computeStackTraceFromStackProp = computeStackTraceFromStackProp; - computeStackTrace.augmentStackTraceWithInitialElement = augmentStackTraceWithInitialElement; - computeStackTrace.computeStackTraceFromStackProp = computeStackTraceFromStackProp; - - return computeStackTrace; - })(); - - module.exports = TraceKit; - }.call( - this, - typeof global !== 'undefined' - ? global - : typeof self !== 'undefined' - ? self - : typeof window !== 'undefined' ? window : {} - )); - }, - {'5': 5} - ], - 7: [ - function(_dereq_, module, exports) { - /* + return computeStackTrace; +})(); + +module.exports = TraceKit; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"5":5}],7:[function(_dereq_,module,exports){ +/* json-stringify-safe Like JSON.stringify, but doesn't throw on circular references. @@ -3199,76 +3095,69 @@ ISC license: https://github.com/isaacs/json-stringify-safe/blob/master/LICENSE */ - exports = module.exports = stringify; - exports.getSerialize = serializer; - - function indexOf(haystack, needle) { - for (var i = 0; i < haystack.length; ++i) { - if (haystack[i] === needle) return i; - } - return -1; - } - - function stringify(obj, replacer, spaces, cycleReplacer) { - return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces); - } +exports = module.exports = stringify; +exports.getSerialize = serializer; - // https://github.com/ftlabs/js-abbreviate/blob/fa709e5f139e7770a71827b1893f22418097fbda/index.js#L95-L106 - function stringifyError(value) { - var err = { - // These properties are implemented as magical getters and don't show up in for in - stack: value.stack, - message: value.message, - name: value.name - }; +function indexOf(haystack, needle) { + for (var i = 0; i < haystack.length; ++i) { + if (haystack[i] === needle) return i; + } + return -1; +} + +function stringify(obj, replacer, spaces, cycleReplacer) { + return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces); +} + +// https://github.com/ftlabs/js-abbreviate/blob/fa709e5f139e7770a71827b1893f22418097fbda/index.js#L95-L106 +function stringifyError(value) { + var err = { + // These properties are implemented as magical getters and don't show up in for in + stack: value.stack, + message: value.message, + name: value.name + }; + + for (var i in value) { + if (Object.prototype.hasOwnProperty.call(value, i)) { + err[i] = value[i]; + } + } - for (var i in value) { - if (Object.prototype.hasOwnProperty.call(value, i)) { - err[i] = value[i]; - } - } + return err; +} - return err; - } +function serializer(replacer, cycleReplacer) { + var stack = []; + var keys = []; - function serializer(replacer, cycleReplacer) { - var stack = []; - var keys = []; + if (cycleReplacer == null) { + cycleReplacer = function(key, value) { + if (stack[0] === value) { + return '[Circular ~]'; + } + return '[Circular ~.' + keys.slice(0, indexOf(stack, value)).join('.') + ']'; + }; + } - if (cycleReplacer == null) { - cycleReplacer = function(key, value) { - if (stack[0] === value) { - return '[Circular ~]'; - } - return ( - '[Circular ~.' + keys.slice(0, indexOf(stack, value)).join('.') + ']' - ); - }; - } + return function(key, value) { + if (stack.length > 0) { + var thisPos = indexOf(stack, this); + ~thisPos ? stack.splice(thisPos + 1) : stack.push(this); + ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key); - return function(key, value) { - if (stack.length > 0) { - var thisPos = indexOf(stack, this); - ~thisPos ? stack.splice(thisPos + 1) : stack.push(this); - ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key); + if (~indexOf(stack, value)) { + value = cycleReplacer.call(this, key, value); + } + } else { + stack.push(value); + } - if (~indexOf(stack, value)) { - value = cycleReplacer.call(this, key, value); - } - } else { - stack.push(value); - } + return replacer == null + ? value instanceof Error ? stringifyError(value) : value + : replacer.call(this, key, value); + }; +} - return replacer == null - ? value instanceof Error ? stringifyError(value) : value - : replacer.call(this, key, value); - }; - } - }, - {} - ] - }, - {}, - [4] - )(4); -}); +},{}]},{},[4])(4) +}); \ No newline at end of file From 76aec2bd9592c287854c663f86e0684154c25f0f Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Fri, 17 Nov 2017 12:23:12 -0500 Subject: [PATCH 052/244] Don't reset to root page when clearing the search field Closes #718. --- assets/javascripts/views/search/search.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/assets/javascripts/views/search/search.coffee b/assets/javascripts/views/search/search.coffee index 9285cd2d..b6c83e1a 100644 --- a/assets/javascripts/views/search/search.coffee +++ b/assets/javascripts/views/search/search.coffee @@ -127,7 +127,6 @@ class app.views.Search extends app.View if event.target is @resetLink $.stopEvent(event) @reset() - app.document.onEscape() return onSubmit: (event) -> From e56343a1d584a5b294c6ee3b5c19bce0b82d1b57 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sat, 18 Nov 2017 17:30:59 -0500 Subject: [PATCH 053/244] Add changelog entry for new print stylesheet --- assets/javascripts/news.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assets/javascripts/news.json b/assets/javascripts/news.json index e53b9f10..dd82e94b 100644 --- a/assets/javascripts/news.json +++ b/assets/javascripts/news.json @@ -1,5 +1,8 @@ [ [ + "2017-11-18", + "Added print & PDF stylesheet.\nFeedback welcome on Twitter and GitHub." + ], [ "2017-09-10", "Preferences can now be exported and imported." ], [ From d1ad60e06743fee0fc8a6e5dc94b23af09293c5f Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 26 Nov 2017 16:32:57 -0500 Subject: [PATCH 054/244] Update gems --- Gemfile.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index cd08f432..e07de2b2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -27,13 +27,13 @@ GEM exifr (1.3.2) ffi (1.9.18) fspath (3.1.0) - highline (1.7.8) + highline (1.7.10) html-pipeline (2.7.1) activesupport (>= 2) nokogiri (>= 1.4) i18n (0.9.1) concurrent-ruby (~> 1.0) - image_optim (0.25.0) + image_optim (0.26.0) exifr (~> 1.2, >= 1.2.2) fspath (~> 3.0) image_size (~> 1.5) @@ -43,7 +43,7 @@ GEM fspath (>= 2.1, < 4) image_optim (~> 0.19) image_size (1.5.0) - in_threads (1.4.0) + in_threads (1.5.0) method_source (0.9.0) mini_portile2 (2.3.0) minitest (5.10.3) @@ -56,15 +56,15 @@ GEM progress_bar (1.1.0) highline (~> 1.6) options (~> 2.3.0) - pry (0.11.2) + pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) rack (2.0.3) rack-protection (2.0.0) rack - rack-test (0.7.0) + rack-test (0.8.2) rack (>= 1.0, < 3) - rake (12.2.1) + rake (12.3.0) rb-fsevent (0.10.2) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) @@ -102,7 +102,7 @@ GEM tty-screen (~> 0.6.0) tty-which (~> 0.3.0) verse (~> 0.5.0) - tty-screen (0.6.2) + tty-screen (0.6.3) tty-which (0.3.0) typhoeus (1.3.0) ethon (>= 0.9.0) @@ -155,4 +155,4 @@ RUBY VERSION ruby 2.4.2p198 BUNDLED WITH - 1.15.4 + 1.16.0 From b399a0ca6f3df771888247077ef517867de91469 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 15 Oct 2017 14:01:18 -0700 Subject: [PATCH 055/244] Add Bluebird documentation (3.5.0) The individual doc pages do not have any category hints in either their url or on the page, so get_type() has a fixed mapping of slug->type. --- lib/docs/filters/bluebird/clean_html.rb | 11 ++++ lib/docs/filters/bluebird/entries.rb | 66 ++++++++++++++++++++++++ lib/docs/scrapers/bluebird.rb | 21 ++++++++ public/icons/docs/bluebird/16.png | Bin 0 -> 1133 bytes public/icons/docs/bluebird/16@2x.png | Bin 0 -> 1652 bytes public/icons/docs/bluebird/SOURCE | 1 + 6 files changed, 99 insertions(+) create mode 100644 lib/docs/filters/bluebird/clean_html.rb create mode 100644 lib/docs/filters/bluebird/entries.rb create mode 100644 lib/docs/scrapers/bluebird.rb create mode 100644 public/icons/docs/bluebird/16.png create mode 100644 public/icons/docs/bluebird/16@2x.png create mode 100644 public/icons/docs/bluebird/SOURCE diff --git a/lib/docs/filters/bluebird/clean_html.rb b/lib/docs/filters/bluebird/clean_html.rb new file mode 100644 index 00000000..92f10b41 --- /dev/null +++ b/lib/docs/filters/bluebird/clean_html.rb @@ -0,0 +1,11 @@ +module Docs + class Bluebird + class CleanHtmlFilter < Filter + def call + css('.post-content > p:first').remove + css('pre').attr('data-language', 'javascript') + doc + end + end + end +end diff --git a/lib/docs/filters/bluebird/entries.rb b/lib/docs/filters/bluebird/entries.rb new file mode 100644 index 00000000..bebae289 --- /dev/null +++ b/lib/docs/filters/bluebird/entries.rb @@ -0,0 +1,66 @@ +module Docs + class Bluebird + class EntriesFilter < Docs::EntriesFilter + TYPE_MAP = { + Core: %w(new-promise then spread catch error finally bind promise.join + promise.try promise.method promise.resolve promise.reject core + promise.bind), + 'Synchronous inspection': %w(promiseinspection isfulfilled isrejected + ispending iscancelled value reason), + Collections: %w(promise.all promise.props promise.any promise.some + promise.map promise.reduce promise.filter promise.each + promise.mapseries promise.race all props any some map reduce filter + each mapseries), + 'Resource management': %w(promise.using disposer), + Promisification: %w(promise.promisify promise.promisifyall + promise.fromcallback ascallback), + Timers: %w(delay timeout promise.delay), + Cancellation: %w(cancel), + Generators: %w(promise.coroutine promise.coroutine.addyieldhandler), + Utility: %w(tap tapcatch call get return throw catchreturn catchthrow + reflect promise.getnewlibrarycopy promise.noconflict + promise.setscheduler), + 'Built-in error types': %w(operationalerror timeouterror + cancellationerror aggregateerror), + Configuration: %w(global-rejection-events local-rejection-events + done promise.config suppressunhandledrejections + promise.onpossiblyunhandledrejection promise.bind + promise.onunhandledrejectionhandled), + 'Progression migration': %(), + 'Deferred migration': %(), + 'Environment variables': %(), + "Beginner's Guide": %w(), + 'Error management configuration': %w(), + 'Anti-patterns': %w(), + 'Deprecated APIs': %w() + } + + def get_name + name = at_css('h1.post-title') + if name.nil? + name = at_css('.post-content h2') + end + name.text + end + + def get_type + type = nil + TYPE_MAP.each do |k,v| + if k.to_s.casecmp(name.strip) == 0 + type = k + break + else + slug_end = slug.sub(%r(^docs/api/), '') + if v.include?(slug_end.downcase) + type = k + break + end + end + end + + type.to_s + end + + end + end +end diff --git a/lib/docs/scrapers/bluebird.rb b/lib/docs/scrapers/bluebird.rb new file mode 100644 index 00000000..bfa96a03 --- /dev/null +++ b/lib/docs/scrapers/bluebird.rb @@ -0,0 +1,21 @@ +module Docs + class Bluebird < UrlScraper + self.type = 'bluebird' + self.base_url = 'http://bluebirdjs.com' + self.root_path = '/docs/api-reference.html' + self.release = '3.5.0' + self.links = { + home: 'http://bluebirdjs.com/', + code: 'https://github.com/petkaantonov/bluebird/' + } + + html_filters.push 'bluebird/clean_html', 'bluebird/entries' + + options[:container] = 'body .post' + + options[:attribution] = <<-HTML + © Petka Antonov
+ Licensed under the MIT License. + HTML + end +end diff --git a/public/icons/docs/bluebird/16.png b/public/icons/docs/bluebird/16.png new file mode 100644 index 0000000000000000000000000000000000000000..5bbe4d72b24ebc5745b82be47884763c3d3e3133 GIT binary patch literal 1133 zcmZ`(drVtp6hDmimVrDJH)i+8%#tBE9&PFKUdm&m(2jwOXQ4xS`xFsMN=d`!3}eX3 zd(hH$ZCP~=L!z6`Y);9HiY!5yiDszT{AbST7GiKFkalFt_1uw|><_=3?>mq0ch33F zxhHq9s$U0nfiBpsl) zA7BGbz4rmS1pq600MZYT))|^Rln)TISaq;gg#eNEBye*}ZQ%loS81Li>B+pNL8Zx^ zZ*&(~eIz}hYM++W4T|es;s#e<^$=-LSNIRIZ<(OumBFFl7zPX%8Cl_GubGUj^+^7^Wz5Kw}S0hZ|1^YO6cm z5^C8{n@p&+O`fiIWq-T9V4zV%F%W9-h{4(19x{&353kpCZeQ^;!^lpG$F({79` z)4R*t`d6-|Y+Q(q`nc;M-X;dClQfSa3`@YaV0A+6=)$L2k@twmBoPS_l+i;P*p^~m zL0zAMb|a?E{zf#!jZ6@c0I~0N?ATPs!6SK1LzodeiIJtc{!-h!N{g?kH7IIyY3%1v zKvk%9l{?-qX%8#SUNn| z6z#+_w%(xLU*-NgQpjHLt}+iJ7-)VQs{#Ke!)#nU-GhS!9KOu^h+!V&KDm+3+*)Ip zZ+gy1P+ef6*Uul{4cs_bkF+JRlZlJ@g!hC;TL8Y#1UQ)lat_3se#AFHjG?@&#P?^% z&W}*p+No~r0^n|8cg)wX$!Rq59GVIh@3;8mB!1i#r^Jn>Ynqbc+8sBH`rg>mbj$X7 zDJOh<`h6{zPD|sjyg&Zyt0?9X$>-G@+-NvT`h$K!SsIh&h1k_eEh(*ID6l( zB?dl=_Ai{f>sh|EHgY}d)Zk6U=RFU(Z>z5DnMt|lnQEx5ulr^B=bvOn9DXpMYx?yT zbvtSGua#B0i1^~z0Uq@+NeEs&7{f%it@KTkQd+f1#Np8t2aH+C6+0q_Ewp~hx$IBB~X hoK9y>Ye!p`k?u6-*zDHeYCa!9pixzpT-c}Y`xiP@kv0GT literal 0 HcmV?d00001 diff --git a/public/icons/docs/bluebird/16@2x.png b/public/icons/docs/bluebird/16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cad3315b93f4678bcd10c5373f120ee522f73752 GIT binary patch literal 1652 zcmV-)28;QLP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 zVoOIv0RI600RN!9r;`8x010qNS#tmY1p)v71p)!VXgFa2000McNliru;R+898VI*{ zHIo1U1wKhcK~z}7y_Q{womUlxpSAY>zH??K?aXv0jS!VIQBfO9o1~&ui>9LVLWN$K zP-9T6T1q4MQ;DKALa~(?@WzTF2x3iWFNA^@8ZClWn>Le7Y>ZSXv6@MfwwWX|XU@;} z?Y)*4CqIU&lflfa>&<$f^|Rl-g+-2=H$Q-Dftm5}?(N*WW#^5J=D-$rAI&-cL>3!h z{hbeiL$}iz9Jyxf?y}MRd`k7Pl+xX}AJWAXU$^-|+?-B(u5r!y@^20u92O(H@{^>KIqH9+u-laKQyeES^_k(!Q};5b$!j>S1!O5d`xD?kn+pe+W97bHXkEDW!C@EK4TNRexCk4xD-UI736D@yPxs?ERaz z+1$)D)->LA*Y^<(fPh>7yt`ud4m|A;crQRoHD*3JJaTon*X~`Ce_nuGIBV9vlkVK? z9q;+@CqL3Ud+M*2^HC9b5#bE(36TP15M-rW-U$97cUz7dIVCdUX7*gS(>qtv0stW6 zmT|W?R^9fUW`=5T(by9Wm8fK#U~bXfn(kRGCoCJ_xEtUz?)(L~uzZ&d&}(<-w&$q2 zovQ&fL`0)#ESjRBi96;Aw~XaPPBoVEg-YEWU@!3Of66~Ez|hDzoz_{6W#e@kA|aLx z3@u}*tm$Q?({)lZvKf|Z+%Ad(9pIP1SAq6|0p9)TA7D8ViegM8TpwbA#*!k!T{k_# zisdJnI<}mb8^i2Bu==TkCtmx!LbRM(?*0Ps6!1r&1zw+p?}=0$I8`H+!+4Mh77!(&L?X9M*Oz@>ZVN(Xf!jA#U*(in0#dWs{z)1^jn}8 z$#Sjv~)KtCp7gak9YA=$g=_dPR=vhYV8_8HJE82#Qqa3RP6uR z*ZymlV}Vom-=qRqgL8wsuhkIWD#BZUHQ)`igqxAGGcx`PYph2M79KL5enCTV}E z5#lYj9%Zz+JyHCqh9e6D__&6!UNoG$Jr3^uYTdhzw{T8_zu@LiSWZ7}G{Qf3JhqjM z;V?SxSqA*+=C+#d&IUSY3+sTYzON`s5GAD=H^)6c4e}`XA@CD!Hl1@i-5k8CQ|FB1 z)ZLo$_QdRG2FO!^`tbs?K)E1&VhC|fQ8sV{%bD8hUkH3wL!9z+<8(kZQ1$v=a^T;t z(^Wt0EKKoL05Oilq9CV?S)OvUucJEUR^c9**!|`IOJKgx5Mv|80&~MG?^$)jtp{<( zO%`3e4-g_6B9`;CnLYZC!%qTS@@ZJ?4pgdwnLSf=JI}fsu6aqs`v4l|`i5h_8C$Wk zQ;(D!{2$hNr6XzxXTeL$_J?k#O<7e-Cf)~7JqdKGs`s}TRlR{{mKfk)n=j78 z{RBZ&0000bbVXQnWMOn=I%9HWVRU5xGB7bWEio`HF*Q^&F*-6fIxsjbFgH3dFqYE| z@c;k-C3HntbYx+4WjbwdWNBu305UK!H!U$REipAzGBG+bHaajkEigAaFfiwiwM_s3 y02y>eSaefwW^{L9a%BK_cXuvnZfkR6VQ^(GZ*pgw?mQX*0000 Date: Sun, 26 Nov 2017 17:33:11 -0500 Subject: [PATCH 056/244] Finish Bluebird scraper --- assets/images/docs-2.png | Bin 14773 -> 15136 bytes assets/images/docs-2@2x.png | Bin 35391 -> 36428 bytes assets/javascripts/news.json | 3 ++ .../templates/pages/about_tmpl.coffee | 5 +++ assets/stylesheets/global/_icons.scss | 1 + lib/docs/filters/bluebird/clean_html.rb | 29 +++++++++++++-- lib/docs/filters/bluebird/entries.rb | 34 +++++------------- lib/docs/scrapers/bluebird.rb | 13 +++---- public/icons/docs/bluebird/16.png | Bin 1133 -> 448 bytes public/icons/docs/bluebird/16@2x.png | Bin 1652 -> 1018 bytes 10 files changed, 51 insertions(+), 34 deletions(-) diff --git a/assets/images/docs-2.png b/assets/images/docs-2.png index 0aa1a1051970958a5ec97cca842cd9acae7e4445..6ef8e80905adcb39067aa3e9e6b129da56a68de1 100644 GIT binary patch delta 5337 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 diff --git a/assets/images/docs-2@2x.png b/assets/images/docs-2@2x.png index e6e018aaa7e9dcf535eb566b8232d1c41fe260a4..e79cbd6862075a10848d4435d0e144555197299d 100644 GIT binary patch delta 14628 zcmcI~Q*-8D&~2P2wmsoYY}-yIHYc|Ii>*l}_QbYrPi)(^-~W5Qz^QX_cJ)Rrp(6B_vwGpVX1JUmiUsP<_yApmcc z&8yzuSn@>kSQJ*gHi}3bjm{+I8&iFECnGDDs`BX5{8Z=S*9PxVw)3U7{UC{VPUlps zBf&Vf3WyF};~!Qe?S9qxaVt|fz(9ezuSW9Rlyd{Jz;?9zDH0hZTL#L{9t7eY4$%K z;_p7Sb?_`s+v~xU*eP%7aluP$JjigJNB@=^oQm07-ZX-F1?NMd@*ZQ`cj|2wx8R8P zAh_V{8Lcer0JELS4{xs&W?vR@$5-&l#;8Bu$RFL_?TIw4i3ULnJbo;qHcr}Ap+0w0 zVB-_1#a(;Pv<0U8rx_P-Mbz>Hl9ZN_Q6sqTUQh@d z6El|V3cko@cfK?V^Y$l~u5yxN_N$bnd87oSK8y*06K2 zabL<1kefyAx=nC_R?BLkI9qk${qJI<_HN}fOUIxJtuSftv3ZR9eO`tSGcS|0B{qfj zVUv&+Yq(7vJA6r1UrvV_2~HU7m8kN5xUx#`12p)nKvGEJmjcxOF#6+ zroQXXfPsCSQz{VzuAv3$1!ZGQZ%P{sNkLZ}HeM-bSZ5KF=W`rtvEq7pSlcxpQ;YUi z5}V|ebYtb8ZCNHfEs=taB23uuqAFPFu#BDAOYjOwvAjFXrVnj;+O*7#48`^`64ql$ zyk+&ec8VMW=q@nPO%Xe$Grl8|c=r9P%iFAx?A@HwkBKjT2VFmvjz_;<$(M^r5rw1T z&{5BoTnae?Q&4-urch&N$@-KtF!79j{1!g8?fF!M%hX;r&|vdIWi58NXG@Pu3yZsW zS6WK z$c(JMj$6aX6amh8^MKzVmV5hc;`(z>XgB-v>J^sb`} zIw#4>O`vKI9=QW2KZReXMs|aP`;AE{DoY)7Qd&9@Ynuh&872ji4ySVeJFZ(DV_kc6ax>lp{Uocz)336m9NO#V zk2VBCJFrXvy&l3p|KY8k{nA(})PoMZvoto^c5C!p%A;noSESgDRG=A2TMu{sxJ`w7 zLJcj{XU&^m!@l%d>$Sboa?r9sFkd(8!K*;vyWmKKi|NK@F=%2ykdqbW0j@q%Qq1SY1VD*wX zCgr0R6{_g!#=25<5n8iHcD|0PZAS&_{9(j9R-n5!=@I=`FaY&UV3zDTuVEcEb6F$m zx1|A$zmEy8SLg@vDM-G3K@+SI7vW3(Kk}XX7QE9N+FqQLrIygl&y@p#q`yLL+PhJ4 zaU&ZI3SExBLpFHc5gJ`>imFnNWFk8s$QV6%ZP%Mmr8$H5_o4Sp*a#y%lNln+%&A&$ z=Sv|8$5#wiYxDB_ zTzMy9pJ~lfkTW|R*X04s_4!C&CV&ES>eO#o>}HP`al9##Cbo+YS8fNy$MxbihSR(1 z4(zxYFQ7^(>-FaJ8C?D`>_pD$+im|!b_|Y)gMj!p9@KPEx$jNYt$CKN_YE<+bBHkD z;15ZAdP+*|G?_PAIk9sNq!8-81jr5f2Vj4^5MUTRpSIAkm@)%w+1w);zW-R4cvl$V zhuC@W0!s}@0KWE!t@hgeXt^x5I}}n7`R!=7o6YT>qb_e%vbH4k+%vl$vO+&G7c-im zkR3VB@-D2LM2Dfl53S%45%mt7m@CCfv}j(9*D#@s3z6qw!KM2gUE(g71_nzI=B6es zpar~h2TAw~9^Zg}--16g0?qt2S%Z6UiD?9)Ec2yNDHKu99tu3@)G04Fjo^SqVH7ZGr-Hd>N-{?X3VvNuz&+uvRI`%d$G>s3rR^SjKg~YG#So0XE7z z&^b@84Zo|<)8%-y*V(5LM~|2VyJJC*Vt_;L84G|AB)OJy}0E!>AZ;PEWo<(|WkC%#DFO2Ma?6u$P$?7MJIS|p`dbzbfRx46JP zl)-^p5FRLAXmWz%ZPFE<&}R@zvOK*l#<9xvcEHU7@7BC@S(HByVco* z!=p&Q`Jgx)&Ii8Ig+IFnv44fqj++zHR@QSxIa}a{GC;>zhJm6|K$z_Q<l*s^&Ou*8{KDKrI}Rybu1nx zRcB3yBhFm){vbBs>H5^`U9ts?4z4n<`RR4OoVg&oo0*ZCR+?9JF<_zAS&67IdaNHT zXI2$LVOIYQ{iLThnRXOe-f@19@dc&2OaUbY->>ot1_706L{w{Hu(2I6k-4SjFEoA* zoO#w;m|6uTN3pJnX@@3Eev#6&6`#XYTG{b~pH}^I`lcYEKq{}WdjFwWLN<+<7eVxT z{j9q+pW+E5XT7?hqn3iODJSW;A=Kw%AAPef7R;2^U&9`6LmNn-$Tl5EBV#(xIABUq zbNGF9+$@1;tyvr! ze6#z*iRbr*K+DrcJ^01t(m_Pzw4wwxYih4FJ}QgLw1x4bif(A7 zX`^;bJ2QdGRk>&t@b-^^jF>< zydGsP{#BRrpN)(60$fv9MCT-TM0He*E@QW;M+vP{o0Q~MwX*8bSBJ|4V>`}+TIIML zjIrw-uX){{+XhQ85j?Pjyeqa(Skf1>$#!HoS8lfoz|^yAT6Y-V z`bFq#!oqq{Kf8X#B(uWw0lr?(nF3pdrCT!&oO->w|+WmPZ^WZ}9z zQCpsGP{kOC%oGYkXOtaX73dqRw%|dqI*KI0zLpczpl%r3y`k`bdAyvAaVU4I3C`i( z*MygJHwavqdBa^d>}U19z>i0idBu{;t@lmQv-a$Cn1bXBo@wk&ff9uh63v{8D^6cY zBSFYmnt}MeuAob;oR*W9q6UsbYGh{YLOB+Uf_XUV;g(-M_5+I976TY(r|nelBd<0& zmBa*GAxj$Li;}tQbJlC91T##F!=^U;ZnBEbRk0R)?wuo<^>e;_0JSt*cH)WMKWX8M z-YsC)H5e!B;SnxFVC_LLl(3hTyoxvecr%{%o%0NXjXyXG&46!CDjq$mEyPQ%+xm(1 zFlzE<#aC2#%(jDy0Dd4UdVS9Czo}1!78wnFs*f)^zg)LwM1}r)oLsDZIPHJcobc_K zV@xxcmlxQ1K$o$4(~_N9Wz8WUnH3#H8skI8~v zWEy=hrCJ(V;5{aY^s*}|<13XE8ffahX#NJ+>&apJ7V@s8*w=7L74grVnRQFsL28l& z{ic@GC+fSR47eatJ+a#vd1^FmHuDuR+b1Q|hZdUoK!QDBFm*x|SwI;qzUr$Bc@=RL}jt;F&St$))6vfaL zalIY%+(c-G)TaUIm`QsAn=>1}eD2@%&9|?_FArlyI*R`OIE`jL!t~JMc{27D3BBGs z;RXGW4vqZ=D5|1Eio?1KE>fEg_3i)0UF;&w?JP8Hq2fw@SlP57r=vS0UT&_wp8otu zINoTdoN0HH{wpFv@w>M-A-qzDawmgRw(tFe64u9u0=A=rB9E9jK`BqEE@vv`+}Szt z+}ZK>xvNvc`GEt4Hz6TK``5E*o%f!^Xw}0RCGS!N@H@Cdn{uVrIK=d=?pMM^6t=Vv zHeE|8tIxB~;#a^!+IdNt^^vp5ejq)QVVzEL8ReTn1Yz6vZ|pUcFlwH~!0U)yT-NL?9aE7+ZAl@` z8G-gV;LQmZS-4O3^S0nI6FNA#3}@4H1GloSVNSOK$HyoD7!oP-2w zoa8=rF8Ymt_#Kk}qa03R zt+4{8^f8T1Xp+j|p<+<+)@>5_(`@~=*P%yEoVDzFG!v0Ebawvd+`G70qmrO*(JCW54M^O75saRvEH{bcWgp#|^Ree{;P@q*W?* zU26Xd)ZZy6b9`^AKv_QiBGFySuo_WZiRfV^6*8iF5(Kf3K&@avtn!|6|5)}Y0e!|&hjSSvA;}ph8AUu!ISSo!49J6nHI@ZLj?n+^~&h$2&{QmXJ*; zdAhinuFIQKE3++~&abA3PTxNDoJJqz;g~Gy5 z8v7%i6NOW3O=Au@8D~SW0#yDC)l48(QIy7J}EbXzF38z<;CTvj;QSXE41x-?)u(7k)RHE+>n`qv0 zV%SWisH(iS zsQJZ&)u?nT`C+N6snbZ61CHAY0IeQ7BH@O$q>?oLcQeWk4BrqL#Ke0-Eci&Nsqo>A zO}1xuG--O?oZp^$N5O!R)fRB{nT)7G$J)xSz=mcsnleYn`X}{pC5zJeE z)#!cA_U8=hyVzl@^Gwhl2ed!#slp(~@afiJ?3|U?AKk70$RS>DuTc(OmIBgF#_u#- zbdaav+Lssdrq+wNE96dXwfGkSIS+qKQ~`s?+S(L~41q^3DGWdaUZar5I&l2*MQZ&U zBN2Nk;u}kFrxD#D8oZ7cm;vDeYPlmPf|^U)B7CBOlzh@+gPklq4s#76QN=YpPnZSg z7j$Ixzr3Kp%wfVRQq0Smhnt1=@a9FBCKOnLhWc z&<09bQ>cnHoT>i1NR8|L7Zs1!CDyjZg?j4i=MxjYqZ{x)>mA@JDhZ^ngHGWCH&9*S zi+58XsDJDUof`dF`XpMqGJ!!$1f~<0k%izt%vdElk0JBo|qs!B>uTV z>N_T~I$uUb>7w^8*g_cM`|DHS%;`q2BXG#o66HW%vVmzIa25fslvYm7(PsVz}8 zFZXDh>PP!mqB;FN9hl^2zEhlsJfk0FvW_2&==}#s70op@@u;L=3B~Fzk8GZvP)smZ z?$x@1f9GD5Tn^dv6`7~5Fm?UC0r$wVfM--AXDYMS@{+2F&QeR$J z1xZgK<9Nt(jLKk>JRdGRDhO$P(E6lEHA-iX_sUux6u9(~4oEt1?>k|lyAnvb>x>LN ziDU;kjZ8N^@vz99Mpf<#s0vNYr%B!pcJ(n>(!+5v@W4GT|M4cgmT$R=)k%+5#DJZv|b|Oe<%@ zruhhUC;v7gmI=XmBBAN7>ocq;x@e%+BBFzJ*}w7Xv$KlPMwJUJAXXX?5eVvEEi*UK z)CnivhU^d!<(K3a-so>CFQJ=fKm;_5|C(}n#oGJQee@FX;(`sSLtevy#|NxP8`w)7 zuRGKoE!Yvq?BoUd4k+bu-_0!YUekLTeoT^$=K|Q7cY^9@Mgr?*!1g7L7U|!&TC@x2KL3wx0{nMVkxvb_07Ar3Shc1f0 zp4DVc63)O^;rd>cVw#%2hZRTu#JQif*|#-U&fuHOng?lvdT$=UQHNvDqmMonjA}*# z+mkzlF-b8sX#8ciRc_gajikKfzzc7V^Y9)|A?hDs`&TppMF)L5NP3+nFj`t#CcIL} zmz};cC7gh;Y?8jX8`ScSo(WP97awX&!kYlgJ&B%3EZWqs<;uy>-W3bQ|AV5cX#D16 z0s#a=;I^1Fk~l$M4SVQ-cWIW0Ho4?XUr`15OcPftY)k$jHqVoS+|OXz^+z)l#s+ce z*r|fQs=!Ph!RUK=$-79c!&;>(N_hs}w*_lyJLhWZo1LGTytf=&gD@d@Szf6mb)Jhj_AT`dCLb+We1zA&9-D(5lpOl z0Kfkc+C8C8^PX+1@jmS%&MI`Fr|P>s@Yz(hiU$0!nrR7r3hZ04z%&a42lD4rA9`rs z<)@4fb}o&Q1RTVwEKbY+QVCm7ZSzHaTYb2gE_fK)Hk6VCBQ^%}D8l!TL-Q}@fED^% z#ZVyEQ1QcdW+{w|$d+q89~Of}GWVZx-TvqtH54!OvsL)&cN>N-U9j(aLn5ne1X8_q zX%s-_)bLoDG+2Qv|NZ$RV(ow3zV;Zd5aTwR!KPNM!+9Zy3RypLOlO`zwp>aQ=dir% z-#0tO9P@@OCH*G^`z*51C!ER>arTJ%&uFbA9N}C*O=k_8VL!0bdELpS#*E+^|9pDU z$79^B&h3X&S(U_z;wI(wh&9q;lznnfMgupWeztFnJ!DLF>s-$l&0GG>Ry=$oE5f;= zarUeO9@Qa19as*;MxzyI#vnQg`)cthY!91vKKyYSfsug2g4Povc(CM|b}grV(_#ET zjHC`G=~&l)f_M(W!zD3Q{oHmN8JVBMD)HqadOOMoZui8tB}5oMtO*DV($5x(l>j;( zANBxP9Aw^nji^lrHdqE?$AGBkHy6a_%vFWpdg=R)=+%>#6-{ayu2TpN^!4pf&3Nt1 zgPWmrF`kYdO;UxQFsWF9_U4O7T)wgpo=aE#O%2vez0{C73pck`m!CqFaQx7tI5OKd zzo7=8p9~*9-&ffKTVd>OF3Qiex`6jvVeyL;yQF}iS$w$m^#Iesp7O-8v?tQdUI29K?Z+5Z-h;~x*GPdl{Og`f&fCR96|l$ z$8f|FjMvkK^5MPbmwwm?RRzW0MUEuEX(XnYvHG|6Z!{S#Y@jxiljR|DFXgH^R^2{} zndd`{5JY-h7Kp<)%t6D6uR{CCzRPt}5Qi1|N&F*2&PzfBy#n{oO;&PFE5RXCFl8kD z3{1hw;Se%^DwI5|?Ux~%s{jd@l}y(5-(4(M%;%44N(XkTG7W@z9CRu(^~XzRt$uO; z3^$vpJ?QHL>Y4Sgz27+4KlAz99#G;9Z};R1cZ${+VD!nO^Jx*t-(-~wbNeRrZ5 zyGocDEZfOF7_!DD9AXqM}6Og%a3&@k2D~u$sCe0r7gOb6QG^Fs*k9AH;FxO1qTQW2bd%Q&l!%`x+$c8ua6u;iy5#>U~hwl;) zh)?uJbSp4`RQcV4513*LoG|&ya(IRW?@w zZBx?@5v#x$maA71UdO5XYUu?&XHq@kJdt4 z&b|>6WBjFMOguWJ2KpYEve3YF;J6$>f0Y1k_`jC3fWiA0OS#Uz_(I47YcQ@a)54=-%st7{hi!~ZD#LL621jHnW{6&s54z{avuZF=ie*}D zWcS(T0M5P{F9!n{9}@?8d(EY-@AaJ7DhPe~{P6+$#{0+l8bf$k+p|68e0n31Rx1&JaYxOe98ON!EQ%1v&L`=rd zQn+Qjh(&91K?UpeOup904@N>B*U$7Vn(t7D8ofwK5W>6T+gCVX{SOjMdp5Qg+m9D( zsF{vI+u9^xqg|qLbm}K48Y;~g91s1xotSU{wim2d=G(QkYxfM~#Oh`7v^t*OJpnkj zc$xtO4umbVSCHeMotPmpsf8B(57g*5kV`6km%r9t&#Hsiv;3gr&8@>L_&<~WvR`lS zkfi1xUL&c$U2psWjN{{zCdq#4AG4$7i<= zXci4!p_zqH%79VO2>41%$Ct+&31)~G-hMg=m`LFY5Oxg3rLe0%{^cGQ6*pJ!G1Ysc z*9iTG)c4RuIxWmN?GnM58F!9Yr;4o_+~^;fPoLd+ZCg6{su}Zm&7nR`SBL2v6oH1o z0}fcr?t}FhA1j>*VQJ^i z<3qgg+2%2G(}*RI&MhYk%FeQS&*mv$q_EixHh~oCn1idLd}YlxN;UN4<}Y?9~@Hr>jsy+@&SWl=B*h*Djh@eJQ#99^GdFe*N7x zqJS$$qe#+6x1yzv_F*5@Jg&pFRqG(mpB>)1T)PQ=JMpZUy!-dpR&_!_T~ievpZB}5 zId(;@)?26uOM3FVQI1*H+yRYT{gA9DeNpZ#d_!y?A$^vKHAlio5TN=P@Vz0|PTgv;Roe|7R$Pm(6G| z5f9TSlMMp7V(hBr21%qovIf>_UtHfao!WzBMHWxBel&VvJxDH^)dl&kV?gE<72-OEhdt>6uQuRyt%a5Bq&ixt_tZLd&Y2K zMW)wb5>lgGu@-}$ay{iRq#G)D6EWv( zG%PvVWex$_ zM3T%JooviBrFH{P;p_EcYDoP*haToQ=H86nK10>gyx8!G!Ry~@Q5mSOZ^3hWQGaJ| z2wpCIxU~&O5`6Ci*r4(->xZu?7<&*dLz=3Pgy2o+nNJ+wUm>{&2@uTkCk^*OzM5Sw zc!W~C2#1>|^TqmLKifqI@IWh_C=wa5WwdKk_?(` zlQmsv(t{fPJJx9$sO5FW*tz z)5w`K3>|r(0zZu1-x1X9VQYI$$g4ioGqtKlgn>;4>gI(ky8Zz>R^O?)7`UPb{2@V1 zJLxy|WHidyBDBYmk9KC}y<__6;MVV~C_hC%3R*|iFX1K+8| z9=!;;kg|bo|5#W6Q~9LaXOgn_{<^bN&x%V9HvDj+e6%9t>`U04_&v3#HS%YZ*zCH! zX7f08?tkA}Dj=}GAUthiOuZXRdeSb>5CR^Eo(CiK$R!A8CcMC1ZQV6m>dJAzIu=%? z9ovQh<6B%uU&g#r6HsWJ0?hqy!aFSuKW3WN-B*VG)4O*oN@4ZO@i2@f88UKKf^YdI zWK?%_l~-!i{1#bEN2`z(tmXcVunKD4{(Bv>MzXWw;So6fdHs^x=LaG(MM@kkwWz6J zg|QCllus~k`Aw+HU7xSk@Z3P3H<9Xc^Ohg5)`iA}zs)5WOoK)Lh0(wMwS5&(!rwql zljCi4;Rs?p()5Jb7b0l9Ey?lLpzfeSEV{+59r?0=6$UJg{tsXN*gI2GZ+M@aGnMe{R}jVX8j5ES8pJj8rBLXj<}w;Zy+p z5~+ws7%?qp*NY_d-&Bt9OsUUEPuGepwlGX!;(y*Px&&gF2S0xge=lknSz~cpT18xv zGiR_t_K+zjoe>&Snl7Cw71-bAqec)Y8^1w(pqe@G(EOwUTR!ab|wtwH5J!nKOR18K4OouXfk$;mUy2kb$d$Ek` zKYZ?C!=5FZK_{WLl(cwa^;K|e-?zE>m!|vnz=V(%JoNDRex`J?#+B76>^<`qb1P(V zPi7uk#F)s-Cm&i^45P}^Lz}8$ph^n=?456rgQ9ik5Z!mGMu=>0^)Fh`Y&ig&7)jr# zl4&e*(=6793gsz}Hn;e;Ql1J^&e&1!5qIynkGQYAw_>`VvyWc*$E$aH;K=}T_xy*m z`$iLd);*NG>N+!=uq_6(*ZN!3;I&|=D_(6CKB^7MiB{RL{zTrCRu55??!5o@7ZfCZ zrpLQ3`5E%xWw*<0n8P~SS4aSW3_{%ufiuJAsv<5nGHFQV8u!3^m11mu-x#g-F4e@u!fEt5rzO(mg!!sjfw5)xS{%7MAy6MU3mOpj792I|?@*m^ytHKXU)ut4+%B>lxMF?- zKFUnqMO+4cB3h6Ylk3SB%M7;`@N)Vdnw79zhwLkmY`?FGPS+$;X}Ev>{*8Q-xYg=% z@|P}mn4-=Iyln#$?Sq6G+=6KZsQHJy; z=mfKtb=xDR3OM4@24(?fCHEd?CcmP+k<>-bm-V8eE11U8#(H0v9Xj}2+W`iG9cI0) z!p|WcelCkM+W*Oh+FD(-cFmLY&-4eH9js{rkId8#NWVKS83xzb9Xl7*#j9I z8?QV^^o>Gsn1U*DX%`=>kVjRtb79DB+=-^8se02#>5eN%BsOMnSzQ<-_V!; zj(}cL1@HK|*)|n7b9?9JUX6ux&2nm^z7OcZqluBRrZE83=D7^fix7GSh>=$k7@1#- zu*h=O&}VL`PsMOS=F4!2TXksNw78y%flVHz_5*uO*?FCAT=1pCmf58NPc$3<34#mT zlBhkHv}@ttE-2#Hr#Wk#Fpe%~x6#WPY$-Al_lxym0>?D$V7~wr>vp!?tcE3J91yr_ zU0=I$-z<=dl=x?-gtl>M#zgKcMD(o_M|S7uU5kEg?OY?{VmOJcI;V9D1P2Sgv6Ns= zrn5xFR7t!zZTjNbtpyU(!w7dRM<+x!aYq}EV^D64+}JFBFjBVO25YqnmFMWEQ!V*d zg%l&}p3Vs2INn}Eot3rFPq)VLNsN4wZ`HPGF7AK_h|GnYsuwZetBVC**+8Q@Pc;;s zoIP@>I2|8dLq$hdr!>N5=0uDk0$r@?RO~xk?)nNDHFMdNY61;$7}Gb=Xl;QuH*H-u zjsCOzhb~%>_led$)EC{q{loC}Qv1k2E!NR|iu^0=c+ErFQ0H}83bF}OVR;9)CLU-? zT@S!hB;i=lsL8Rt+FdkscHv}6Wi=bSzfK_x%|@aJs;zBTEV3~wT)KO+!u2_+(<9>3aoRuQY3Het z1BSGWEu6yk6g4)@dK|PZBv)@#de>@{3tylD@^1;=(>38n+;b%qoc7T*os7Y}wTI+~ zKqXT8LEotvse-*n&EdXTxAkyhj!iNc74FB#S-Z`1hn$bZH!P{V%k+lofv^{YC_L4k zj`V*B3I>=aNw+v8+Iw&AGn^Dw3%f!m&AYkAo>*VPEm3qV!AjU&{F3DZJ~EMX>%M?4 zuA=IA7Flh(%;2X9&cO5_-qN}qwh$Z{VZv*!8B6XbGMJzgX zBHQ*8P2gr}Xm9#84jfV`9>wsmjCR7Jd@vYMA1Ug$MZhY*OsFY&viD{9|?EXe&A z`1|Kk&c0jotzPN348C^0GPnuA90uT%sZ)A!zr44sS-n%@Deg{@uny-jHy@YXOV)MH z7J>eUp+WY}zvOFbQ@*t`&2YRzY4m!a5fG(cc>;128;zt=>3~^kgeZybj9iGML8nT$ zr<;Z^>8M%;GZ!$pLpcS#SSB2eqp~eXA@css7sYPxopS$sr_iE)g~xdM$_3QTIqb~` z6o4an18_Q+y^;OtB#}uM4^So@NwN)}-?GK+nIv|2hmW&67M|wen0>b*yfv#Bqo*}y z@$;*yh^nBslN@U1a-SP!;RtTUt)!DiXgH&0%V>>P0-QX8oM?Rfp=1^OX~-%f1`v0{ zzgd9DPhp;X9rY)u6lap4Pysj;AB5~Z|K*@>9(q+Y+}>K)W1{n9=#qg_cQCZDC-Tj! zgvCT-I>#Q=O-nYiyUnfN8I89Cl&ttHDbz7TdO6`plNzChttNBnE?#a~ zZuS_L&=y6O?eK#ry?tFe{x)=}vCnGED?Cmi>MiC0c!WG(bdYOV=@4)f{7rYTZa6Z$ZE=1AmFm8lz zfCg&+F}74)^by}10kpW)`A@A=`9MpGVtE4McNgjB*gXC=O&I>A8F)wQ5xzD7>lj48 z#`BKvh01wwa4V8Bsdl>b6gjD;=9+V4_%lY`Kzhw{sCD#ac%a2nc<`nN zOb`~S+v(fCnJAuJE%Yh$dyGB8Z{Hii;wzluI0xffw3JsNYPB1VT2dR(9{lQ3h1a)l zj4l*>;hjhw+^%{Xh+b&sPVIA_8k9JTf~ax?<@e>d#xS}1%KB^OFMf2_ zRPN_G`VSw0R{Lri#Sgj1x;wcbLyj3<6D8~Ccl z8f8c(%DA@eN3gMvP^cBxvA$4n7z8)%WiN+Xz8IVmcnACU%UtHvS=}m6PJ+WnjPK>{ zab;+o?KuRO|9Q7t<9SXlTiI(t`cB7g?OWpVBoX@ZdPabAG{dMHB!zAms#R3cfl=x2 z8|YK-#=fGr>&;0!rnwuTAGAq*{MX)KB^WFjJi4aOlH%-ksYehpx3H~*19c{Yr+f;(}LehGy3l19$IMe zNGI#4T5vG(hG2N>xpSVD+;K8TN8yk>QENh{$^keh?(jT7E~V<~4!j3IcDr~wZ@5-p zV^Rn|KHQ+#c1FYw1%5N1fNaRxuJH1GE`mJGD)59?Lf5@bu6U7T#s5yefP{#IOW{I>qsMg!uSFM*Brm*EbG~O2S||z9pQj z&c((C*r^D%9AkB|`Z2K)Ka(v+mmXXOkCAcJGp!O+s5Ym3RLFZ@Ffb3~ zr$ot)td5K%He?lg&Si2hWSIS{*nGZhKSbKuIef^=J9JekPG3?;GuCIdOz?bozBydz z?LAa88A?wK44j~afS90_h-G6WVeZR3zOq-izhk9-eN9h!c}`71BC^syy|C5aJ+ah3 zztp$IWh?Qjt*_@ET6p*)TCMK{F-8u!I2XEmjKwj=GT$eq8uX5MMRx^ytiY%JeBxZ% z#=rofph6Ltk{X$iBO{z(hArtUR> z$D1h01v8hy+#mNELTfdARJ^e45w3o)`U^y?Mb=qA8Z@T6{xDQUQT8M!<<%{`xrKan zUCB!k0TayhIP=o^Md;~$HeU;9#?+jZ+~xmFQP)rj?y~^prcWp>y~T_DF79g(sVS~@ zKi`pr!IR_X+nw`ScR9hZpq)ISaJn05&rl4+k>H3JaB9i;x9lALZyp=s2Qxh}dJpbZ zO=Uer(Qjfh5&iq8SMiHpHk`U@t2pMjq^zybajhM7L=oM2MB{y|BJnwZ87+fK8qqm! z2e0WDS5mKsG-5x~6G4@I1@NEOC=aCIh8q3<495Rk^+VviHvsH^PyClPc}XH!1bZS= z1T^xG|Ccn%kBeS1@c(M~=YCah7{VrkN75vsMxtV8gV|;Yl8PrvLjCUz(&7qYRU(Fg F{{#1CTj~G+ delta 13580 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 JN^#@B{{!$Z?xO$z diff --git a/assets/javascripts/news.json b/assets/javascripts/news.json index dd82e94b..17376fc0 100644 --- a/assets/javascripts/news.json +++ b/assets/javascripts/news.json @@ -1,5 +1,8 @@ [ [ + "2017-11-26", + "New documentation: Bluebird" + ], [ "2017-11-18", "Added print & PDF stylesheet.\nFeedback welcome on Twitter and GitHub." ], [ diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index 40b96136..85cc62ea 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -112,6 +112,11 @@ credits = [ '2010-2016 Jeremy Ashkenas, DocumentCloud', 'MIT', 'https://raw.githubusercontent.com/jashkenas/backbone/master/LICENSE' + ], [ + 'Bluebird', + '2013-2017 Petka Antonov', + 'MIT', + 'https://raw.githubusercontent.com/petkaantonov/bluebird/master/LICENSE' ], [ 'Bootstrap', '2011-2017 Twitter, Inc.
2011-2017 The Bootstrap Authors', diff --git a/assets/stylesheets/global/_icons.scss b/assets/stylesheets/global/_icons.scss index fffc7e25..0f8c2aed 100644 --- a/assets/stylesheets/global/_icons.scss +++ b/assets/stylesheets/global/_icons.scss @@ -164,3 +164,4 @@ ._icon-nim:before { background-position: -5rem -2rem; @extend %doc-icon-2; @extend %darkIconFix !optional; } ._icon-vulkan:before { background-position: -6rem -2rem; @extend %doc-icon-2; @extend %darkIconFix !optional; } ._icon-d:before { background-position: -7rem -2rem; @extend %doc-icon-2; } +._icon-bluebird:before { background-position: -8rem -2rem; @extend %doc-icon-2; } diff --git a/lib/docs/filters/bluebird/clean_html.rb b/lib/docs/filters/bluebird/clean_html.rb index 92f10b41..6580a6aa 100644 --- a/lib/docs/filters/bluebird/clean_html.rb +++ b/lib/docs/filters/bluebird/clean_html.rb @@ -2,8 +2,33 @@ module Docs class Bluebird class CleanHtmlFilter < Filter def call - css('.post-content > p:first').remove - css('pre').attr('data-language', 'javascript') + @doc = at_css('.post') + + css('hr').remove + + css('.api-code-section').each do |node| + node.previous_element.remove + end + + css('.post-header', '.post-content', '.api-reference-menu', '.api-code-section', 'markdown', '.highlight', 'code code').each do |node| + node.before(node.children).remove + end + + at_css('> h2:first-child').name = 'h1' unless at_css('h1') + + css('.header-anchor[name]').each do |node| + node.parent['id'] = node['name'] + end + + css('pre').each do |node| + node.content = node.content + node['data-language'] = 'javascript' + end + + css('.info-box').each do |node| + node.name = 'blockquote' + end + doc end end diff --git a/lib/docs/filters/bluebird/entries.rb b/lib/docs/filters/bluebird/entries.rb index bebae289..522e4db4 100644 --- a/lib/docs/filters/bluebird/entries.rb +++ b/lib/docs/filters/bluebird/entries.rb @@ -26,41 +26,23 @@ module Docs done promise.config suppressunhandledrejections promise.onpossiblyunhandledrejection promise.bind promise.onunhandledrejectionhandled), - 'Progression migration': %(), - 'Deferred migration': %(), - 'Environment variables': %(), - "Beginner's Guide": %w(), - 'Error management configuration': %w(), - 'Anti-patterns': %w(), - 'Deprecated APIs': %w() } def get_name - name = at_css('h1.post-title') - if name.nil? - name = at_css('.post-content h2') - end - name.text + name = at_css('h1').content.strip + name << '()' if doc.to_html.include?("#{name}(") + name end def get_type - type = nil - TYPE_MAP.each do |k,v| - if k.to_s.casecmp(name.strip) == 0 - type = k - break - else - slug_end = slug.sub(%r(^docs/api/), '') - if v.include?(slug_end.downcase) - type = k - break - end + if slug.start_with?('api') + TYPE_MAP.each do |key, value| + return key.to_s if value.include?(slug.remove('api/')) end + else + 'Guides' end - - type.to_s end - end end end diff --git a/lib/docs/scrapers/bluebird.rb b/lib/docs/scrapers/bluebird.rb index bfa96a03..e5cd6b59 100644 --- a/lib/docs/scrapers/bluebird.rb +++ b/lib/docs/scrapers/bluebird.rb @@ -1,9 +1,10 @@ module Docs class Bluebird < UrlScraper - self.type = 'bluebird' - self.base_url = 'http://bluebirdjs.com' - self.root_path = '/docs/api-reference.html' - self.release = '3.5.0' + self.type = 'simple' + self.release = '3.5.1' + self.base_url = 'http://bluebirdjs.com/docs/' + self.root_path = 'api-reference.html' + self.force_gzip = true self.links = { home: 'http://bluebirdjs.com/', code: 'https://github.com/petkaantonov/bluebird/' @@ -11,10 +12,10 @@ module Docs html_filters.push 'bluebird/clean_html', 'bluebird/entries' - options[:container] = 'body .post' + options[:skip] = %w(support.html download-api-reference.html contribute.html) options[:attribution] = <<-HTML - © Petka Antonov
+ © 2013–2017 Petka Antonov
Licensed under the MIT License. HTML end diff --git a/public/icons/docs/bluebird/16.png b/public/icons/docs/bluebird/16.png index 5bbe4d72b24ebc5745b82be47884763c3d3e3133..cdbe752bfe0ff81ff6fc6bac6785803bb6295ace 100644 GIT binary patch delta 433 zcmV;i0Z#ty2*3l78Gi-<001BJ|6u?C0f$LMK~#7FV;~3ErA;%pO`ST~DshrC$(n7F zC+j(+Pd{yyI5CA}&6<9-96$rsS|?4~ui;zGO|k)|(cLN5NfUoq#`hKARAiYriP<)7 zMwnI7lq9Q^=^nP}vz@I|W(1hU^-ng5?s{(?+x^`%y2~D?0e@z(z3dhV6ZcrBO#g3} zIsd11`uy(}iBtZYM0fu;if9MnLqIHw+XYEerL0qD-SjM)^MCIA$p15Eh5QQ2tJ`Q8 z(KQpOu@Z>YFfEcQecqpdlD_|sc1isIzn$U3-!)A7IBf)) zXl5MQxzseK_kWf};^Z$t7yLI*nEc;6yXEk!Jpz@#)-lifF`d;EU&tOYjqUvpG~fp? zpw5`Z_N_II>1i~K=v4yAe_zbT`h5}`2TlX5lc#*ON}BZDII1%n=nX!D&?aV*;?^l^ z&VTEashc!>s@Ta&*KYX>f7qr?k7pnkcor==>ySBHlPYWjyi1m~yX4O2qr?Rk?gfij b$kh)3vUHeqzJ5b+00000NkvXXu0mjf6<*Zm literal 1133 zcmZ`(drVtp6hDmimVrDJH)i+8%#tBE9&PFKUdm&m(2jwOXQ4xS`xFsMN=d`!3}eX3 zd(hH$ZCP~=L!z6`Y);9HiY!5yiDszT{AbST7GiKFkalFt_1uw|><_=3?>mq0ch33F zxhHq9s$U0nfiBpsl) zA7BGbz4rmS1pq600MZYT))|^Rln)TISaq;gg#eNEBye*}ZQ%loS81Li>B+pNL8Zx^ zZ*&(~eIz}hYM++W4T|es;s#e<^$=-LSNIRIZ<(OumBFFl7zPX%8Cl_GubGUj^+^7^Wz5Kw}S0hZ|1^YO6cm z5^C8{n@p&+O`fiIWq-T9V4zV%F%W9-h{4(19x{&353kpCZeQ^;!^lpG$F({79` z)4R*t`d6-|Y+Q(q`nc;M-X;dClQfSa3`@YaV0A+6=)$L2k@twmBoPS_l+i;P*p^~m zL0zAMb|a?E{zf#!jZ6@c0I~0N?ATPs!6SK1LzodeiIJtc{!-h!N{g?kH7IIyY3%1v zKvk%9l{?-qX%8#SUNn| z6z#+_w%(xLU*-NgQpjHLt}+iJ7-)VQs{#Ke!)#nU-GhS!9KOu^h+!V&KDm+3+*)Ip zZ+gy1P+ef6*Uul{4cs_bkF+JRlZlJ@g!hC;TL8Y#1UQ)lat_3se#AFHjG?@&#P?^% z&W}*p+No~r0^n|8cg)wX$!Rq59GVIh@3;8mB!1i#r^Jn>Ynqbc+8sBH`rg>mbj$X7 zDJOh<`h6{zPD|sjyg&Zyt0?9X$>-G@+-NvT`h$K!SsIh&h1k_eEh(*ID6l( zB?dl=_Ai{f>sh|EHgY}d)Zk6U=RFU(Z>z5DnMt|lnQEx5ulr^B=bvOn9DXpMYx?yT zbvtSGua#B0i1^~z0Uq@+NeEs&7{f%it@KTkQd+f1#Np8t2aH+C6+0q_Ewp~hx$IBB~X hoK9y>Ye!p`k?u6-*zDHeYCa!9pixzpT-c}Y`xiP@kv0GT diff --git a/public/icons/docs/bluebird/16@2x.png b/public/icons/docs/bluebird/16@2x.png index cad3315b93f4678bcd10c5373f120ee522f73752..9ffae075b3af0473e9d5861b8d015d419bb482b1 100644 GIT binary patch delta 997 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 icXuvnZfkR6VQ^(GZ*pgw?mQX*0000 Date: Sun, 26 Nov 2017 17:39:40 -0500 Subject: [PATCH 057/244] Update PHP documentation (7.1.12) Closes #686. Closes #673. --- lib/docs/scrapers/php.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/docs/scrapers/php.rb b/lib/docs/scrapers/php.rb index 44b8c24d..78736a0e 100644 --- a/lib/docs/scrapers/php.rb +++ b/lib/docs/scrapers/php.rb @@ -4,7 +4,7 @@ module Docs self.name = 'PHP' self.type = 'php' - self.release = 'up to 7.1.5' + self.release = '7.1.12' self.base_url = 'https://secure.php.net/manual/en/' self.root_path = 'index.html' self.initial_paths = %w( @@ -20,7 +20,7 @@ module Docs self.links = { home: 'https://secure.php.net/', - code: 'https://github.com/php/php-src' + code: 'https://git.php.net/?p=php-src.git;a=summary' } # Downloaded from php.net/download-docs.php @@ -45,7 +45,7 @@ module Docs BOOKS = %w(apache apc apcu array bc bzip2 calendar csprng classobj ctype curl datetime dba dir dom ds eio errorfunc ev event exec exif fileinfo filesystem filter - ftp funchand gearman geoip gettext gmagick gmp hash iconv iisfunc image + ftp funchand gearman geoip gettext gmagick gmp hash ibase iconv iisfunc image imagick imap info inotify intl json judy ldap libevent libxml lua mail mailparse math mbstring mcrypt memcached misc mysqli network oauth openssl outcontrol password pcntl pcre pdo pgsql phar posix proctitle pthreads quickhash regex runkit From 28aeb115c03d6066ac7252a54f97a7caa8f505a1 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 26 Nov 2017 17:44:10 -0500 Subject: [PATCH 058/244] Improve Flow scraper entry classification Closes #680. --- lib/docs/filters/flow/entries.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/docs/filters/flow/entries.rb b/lib/docs/filters/flow/entries.rb index 6cbdf0f4..88bf68a8 100644 --- a/lib/docs/filters/flow/entries.rb +++ b/lib/docs/filters/flow/entries.rb @@ -6,6 +6,7 @@ module Docs end def get_type + return 'React' if slug.start_with?('react') type = at_css('.guide-nav .nav-item').content.strip type.remove! %r{ \(.*} type From df0f586d07a65f7bbbdeb1aa2ec5216693d6ee48 Mon Sep 17 00:00:00 2001 From: Kyan Date: Sat, 25 Nov 2017 09:55:04 +0800 Subject: [PATCH 059/244] fix misspelled "occured" to "occurred" Reference: http://www.gingersoftware.com/english-online/spelling-book/misspelling/occurred-occured-ocurred --- assets/javascripts/templates/error_tmpl.coffee | 4 ++-- assets/javascripts/templates/notif_tmpl.coffee | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/javascripts/templates/error_tmpl.coffee b/assets/javascripts/templates/error_tmpl.coffee index 9dc311d9..9c19c0a6 100644 --- a/assets/javascripts/templates/error_tmpl.coffee +++ b/assets/javascripts/templates/error_tmpl.coffee @@ -37,10 +37,10 @@ app.templates.offlineError = (reason, exception) -> """ Your browser appears to be running in private mode.
This prevents DevDocs from caching documentations for offline access.""" when 'exception' - """ An error occured when trying to open the IndexedDB database:
+ """ An error occurred when trying to open the IndexedDB database:
#{exception.name}: #{exception.message} """ when 'cant_open' - """ An error occured when trying to open the IndexedDB database:
+ """ An error occurred when trying to open the IndexedDB database:
#{exception.name}: #{exception.message}
This could be because you're browsing in private mode or have disallowed offline storage on the domain. """ when 'version' diff --git a/assets/javascripts/templates/notif_tmpl.coffee b/assets/javascripts/templates/notif_tmpl.coffee index 0cd8531c..1cc17ff6 100644 --- a/assets/javascripts/templates/notif_tmpl.coffee +++ b/assets/javascripts/templates/notif_tmpl.coffee @@ -13,7 +13,7 @@ app.templates.notifUpdateReady = -> """Reload the page to use the new version.""" app.templates.notifError = -> - textNotif """ Oops, an error occured. """, + textNotif """ Oops, an error occurred. """, """ Try reloading, and if the problem persists, resetting the app.
You can also report this issue on GitHub. """ @@ -31,7 +31,7 @@ app.templates.notifInvalidLocation = -> """ Otherwise things are likely to break. """ app.templates.notifImportInvalid = -> - textNotif """ Oops, an error occured. """, + textNotif """ Oops, an error occurred. """, """ The file you selected is invalid. """ app.templates.notifNews = (news) -> From 0379d4910a9fdaa00b513d7d745270e0e4fb76f5 Mon Sep 17 00:00:00 2001 From: firewalker06 Date: Wed, 22 Nov 2017 14:21:01 +0700 Subject: [PATCH 060/244] Remove trailing slash on bootstrap example URL --- lib/docs/filters/bootstrap/clean_html_v3.rb | 2 +- lib/docs/filters/bootstrap/clean_html_v4.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/docs/filters/bootstrap/clean_html_v3.rb b/lib/docs/filters/bootstrap/clean_html_v3.rb index a96102c9..ddd7990a 100644 --- a/lib/docs/filters/bootstrap/clean_html_v3.rb +++ b/lib/docs/filters/bootstrap/clean_html_v3.rb @@ -27,7 +27,7 @@ module Docs node.remove_attribute('data-example-id') prev = node.previous_element prev = prev.previous_element until prev['id'] - node.inner_html = %(Open example on getbootstrap.com) + node.inner_html = %(Open example on getbootstrap.com) end end diff --git a/lib/docs/filters/bootstrap/clean_html_v4.rb b/lib/docs/filters/bootstrap/clean_html_v4.rb index b841410a..0974556e 100644 --- a/lib/docs/filters/bootstrap/clean_html_v4.rb +++ b/lib/docs/filters/bootstrap/clean_html_v4.rb @@ -26,7 +26,7 @@ module Docs node.remove_attribute('data-example-id') prev = node.previous_element prev = prev.previous_element until prev['id'] - node.inner_html = %(Open example on getbootstrap.com) + node.inner_html = %(Open example on getbootstrap.com) end end From 9fdaf078bdbae2074f6935b6321c5e1132155058 Mon Sep 17 00:00:00 2001 From: Cyril Lakech <1169286+clakech@users.noreply.github.com> Date: Mon, 23 Oct 2017 23:03:37 +0200 Subject: [PATCH 061/244] add eslint doc (4.9.0) --- lib/docs/filters/eslint/clean_html.rb | 10 ++++++++++ lib/docs/filters/eslint/entries.rb | 25 +++++++++++++++++++++++++ lib/docs/scrapers/eslint.rb | 25 +++++++++++++++++++++++++ public/icons/docs/eslint/16.png | Bin 0 -> 505 bytes public/icons/docs/eslint/16@2x.png | Bin 0 -> 1088 bytes public/icons/docs/eslint/SOURCE. | 17 +++++++++++++++++ 6 files changed, 77 insertions(+) create mode 100644 lib/docs/filters/eslint/clean_html.rb create mode 100644 lib/docs/filters/eslint/entries.rb create mode 100644 lib/docs/scrapers/eslint.rb create mode 100644 public/icons/docs/eslint/16.png create mode 100644 public/icons/docs/eslint/16@2x.png create mode 100644 public/icons/docs/eslint/SOURCE. diff --git a/lib/docs/filters/eslint/clean_html.rb b/lib/docs/filters/eslint/clean_html.rb new file mode 100644 index 00000000..b5225038 --- /dev/null +++ b/lib/docs/filters/eslint/clean_html.rb @@ -0,0 +1,10 @@ +module Docs + class Eslint + class CleanHtmlFilter < Filter + def call + @doc = at_css('.doc') if at_css('.doc') + doc + end + end + end +end diff --git a/lib/docs/filters/eslint/entries.rb b/lib/docs/filters/eslint/entries.rb new file mode 100644 index 00000000..c8451bf2 --- /dev/null +++ b/lib/docs/filters/eslint/entries.rb @@ -0,0 +1,25 @@ +module Docs + class Eslint + class EntriesFilter < Docs::EntriesFilter + def get_name + at_css('h1').content + end + + def get_type + if subpath.start_with?('docs/developer-guide/') + type = 'Developer Guide' + elsif subpath.start_with?('docs/user-guide/') + type = 'User Guide' + elsif subpath.start_with?('docs/rules') + type = 'Rules' + elsif subpath.start_with?('docs/about') + type = 'User Guide' + else + type = nil + end + type + end + + end + end +end diff --git a/lib/docs/scrapers/eslint.rb b/lib/docs/scrapers/eslint.rb new file mode 100644 index 00000000..d0a3f636 --- /dev/null +++ b/lib/docs/scrapers/eslint.rb @@ -0,0 +1,25 @@ +module Docs + class Eslint < UrlScraper + self.name = 'ESLint' + self.type = 'eslint' + self.release = '4.9.0' + self.base_url = 'https://eslint.org/' + self.root_path = 'docs/user-guide/getting-started' + + self.links = { + home: 'https://eslint.org/', + code: 'https://github.com/eslint/eslint' + } + + html_filters.push 'eslint/entries', 'eslint/clean_html' + + options[:container] = 'body' + + options[:skip_patterns] = [/\Ablog/, /\Ademo/, /\Aparser/, /formatters\//] + + options[:attribution] = <<-HTML + © Copyright JS Foundation and other contributors, https://js.foundation/
+ Licensed under the MIT License. + HTML + end +end diff --git a/public/icons/docs/eslint/16.png b/public/icons/docs/eslint/16.png new file mode 100644 index 0000000000000000000000000000000000000000..10e1edb099ce97816e834be20429fbecc2b312ae GIT binary patch literal 505 zcmVeCgh3d`fBWt#vNo;`TqGr}-lC)tTP|L0YEx3aN)A5mio=u(H!UeCp`5j9 zt}d?wZB2<1HV3(JTKS5#F0(Z@TzG1l`Tw8inUClB5B$*rHt<}(7C0~FEqe!|N{j0P z;S>dI0cAj`85!Wh!eL;;PH?Q#yMRsuUw~1iMU&E^85l7fK+JRf*mpPBGIKKbmJ2H_ zwx!GtNtqp0TI}TBa^*nM#H@d*f#>?uzzWc-v`|uJ8-ZOQYT{0TK`A3=p6mAj3Ybz_ ztOY#R4*^d=2@q?EM=ycfABtF)-an}U4uEH%$^n*5a=}8sbS-GD%YY>ZsQiNrDji^= zh|K?zVEaCR8AoaH1k4q#C}rdZNC5X%@I8=_GIC{!Y+h;c5U_M`XWlidv{(g@GP?i- z8`>-82D$@z&-EvPMc@&rR$Aok4dOt`zzi^^v^X@rc3=~zH~v1QMe4i1a169s)Sl6Q vzr`IXE!uu+*)Wg>UJdTBYJh3?IR9y%x#e}`xO^X500000NkvXXu0mjf{*2OE literal 0 HcmV?d00001 diff --git a/public/icons/docs/eslint/16@2x.png b/public/icons/docs/eslint/16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..463fc6109b85eab498275b2fd5d9fea12e899780 GIT binary patch literal 1088 zcmV-G1i$-;(V-1IU=%8NzD9-{EVdWBGApf?l3h^%hPDN61= z6QqnoqwY#c$HFTM(uav)1h0tVd{~syA1g0(;z*}wQfnLM?dCUlI-U1DXJ^p*T^*j^ zbH2at@Av%vy)e(BDqRTt$eROxY^;uJCJ^{hJCFxf1JkoKo&hcby~gUFXH6jRqeZ}8 zV9y+*{2p-7SUp}&nHJs^KzCYrB`Q<$J4s##)+Q;v1n(D%@ic;0fmeVo;QN$&O+Z)R zN3B&6kfeJG=uGhXHgEt~XRPiwRv!mCfDjl>AkhUpQ&kQGezX)gDI{DO2hITdjMYCT zL~ezU+XyTy!T%cAVXXc&kwD-_8DKl`iF5oHa0S?JtTr=;VOXdKT7Y_BBn+FT9h?n7 z4)8@kBRha&#_Fjg0`0(M;8CCm+yFj8@u9h_ivT_Q?UWA)X45eWRKL0ET-@d)TNR*yPfXXU*Ql*#O2;9cPCpW_n~@8?@$ z!EFQjf%P*mK;BsWpfm}W1G}8C56u`4!$Msc7FNmA3?`J-8p)lb3l}x4$>jgjQ@B%+lz_Y;S z6wnrFt<_4S{3l7a1AgE~%9BR%K?T5KErY0nejm{00WZn0`LE?U;AszNo5yva)sqsr zH4nyr0Zw|r9jV_rEiN_urw17IjMcG<)c|lQbFxv9g_e(J@+$8sZL-)9LJyMa?O(f z8`qx8#KrhAiR4?r!zIn9&shCO+CtI_oC6*&QT+rQ0tSuMBMA#h8?XU*2Y9kX{T;B` zSbfbstS^J}yF{SB%#wN-7!3UAW8i|ZdQ1#A%X93MZK#~&f$LS(ssMfgypRAkA&E60 z3Ak0ZoovGWQ^0G+>YLRPP{8xD1J + + + + + + + + From 66d3228f766718fc7622dd3b784ce3e4306ee905 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 26 Nov 2017 18:31:40 -0500 Subject: [PATCH 062/244] Finish ESLint scraper --- assets/images/docs-2.png | Bin 15136 -> 15491 bytes assets/images/docs-2@2x.png | Bin 36428 -> 37437 bytes assets/javascripts/news.json | 2 +- .../templates/pages/about_tmpl.coffee | 5 ++++ assets/stylesheets/global/_icons.scss | 1 + lib/docs/filters/eslint/clean_html.rb | 18 ++++++++++++++ lib/docs/filters/eslint/entries.rb | 22 ++++++++---------- lib/docs/scrapers/eslint.rb | 16 ++++++------- public/icons/docs/eslint/16.png | Bin 505 -> 330 bytes public/icons/docs/eslint/16@2x.png | Bin 1088 -> 747 bytes public/icons/docs/eslint/SOURCE | 1 + public/icons/docs/eslint/SOURCE. | 17 -------------- 12 files changed, 43 insertions(+), 39 deletions(-) create mode 100644 public/icons/docs/eslint/SOURCE delete mode 100644 public/icons/docs/eslint/SOURCE. diff --git a/assets/images/docs-2.png b/assets/images/docs-2.png index 6ef8e80905adcb39067aa3e9e6b129da56a68de1..f60694b4c7113fe45a6210810207b2799681c91e 100644 GIT binary patch delta 5691 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

`|@eSwrGe+#|tF=@nocu zh`cl1ql=DEp7`l+jj@f$S{8n|0@h_$LPG8ph|RhTejAElL2?Pi;Ctlp3Rs;{rZeMO z{Jbt3g=3?#ssJnKjz@%vs8P(T8KocFe}(jq2Y*7&T+x8(hcOLjkfNlwkrneBWXuVI z%Jj5nXh7|Qh6gQV`-QyMqw4O}wqR6jDG>>^MRR7ioItal2wu=q^lflU$&$q_+uhu> z1{6SsYVpH#j$rXF>RVX&NPPQhaKtIm7JbCqUTbT#)bXS_8QS_k!zx{I}i>vOWmvqtk(v=<*k^W0u?4lMK~$86-d zjigwtioX`QiVR6{LbhmdT^NFWw~6_%APHptAV>rx<|0+EF7k0BJ|+8s*cOjP%6fag zJQ6pgueL|PH^4Y)_QVMifAw`oRRK6E^U!n}m>O3EPP)B8HB4DwsH=$CD%{1#F%u-& zH^+#NbGo?>?~95>Z9&EBwS~0l``+j+oVex77wlfJpe_Tygr4r@bthxeq?$dxzBPNM z`PJ;55m>Wt-rSl!_)PclsY!KpsoCk|bZ4i7!|jv_)4a02;7Z<-xOO{$R-V z3rWG_g|aX7M{&3C1jLv51F?%ZJ{UKaqa9^ARV-I4{{2YUUK2@&WS(aJ0}2)Th{*R^{C#dj45+-(`r#=vCLTdXN(i+;Z88 zQSUlAio^GGQgFnPHQ!r;tobng-qokt0Ol>hmZ*C>NYsvaKKz4&EGr(3mw>lmcn%mP z9h7;WF#pHE2spwP?=LcwK{}&8g+lq?_TYd70000$(Er!%2vh(7000000000000000 h0000000000#scTu#6d}oOiBO%002ovPDHLkV1kncDct}7 delta 5336 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 delta 14625 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" + "New documentations: Bluebird and ESLint" ], [ "2017-11-18", "Added print & PDF stylesheet.\nFeedback welcome on Twitter and GitHub." diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index 85cc62ea..9156cb82 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -247,6 +247,11 @@ credits = [ '2010-2017 Ericsson AB', 'Apache', 'https://raw.githubusercontent.com/erlang/otp/maint/LICENSE.txt' + ], [ + 'ESLint', + 'JS Foundation and other contributors', + 'MIT', + 'https://raw.githubusercontent.com/eslint/eslint/master/LICENSE' ], [ 'Express', '2017 StrongLoop, IBM, and other expressjs.com contributors.', diff --git a/assets/stylesheets/global/_icons.scss b/assets/stylesheets/global/_icons.scss index 0f8c2aed..26ed1cab 100644 --- a/assets/stylesheets/global/_icons.scss +++ b/assets/stylesheets/global/_icons.scss @@ -165,3 +165,4 @@ ._icon-vulkan:before { background-position: -6rem -2rem; @extend %doc-icon-2; @extend %darkIconFix !optional; } ._icon-d:before { background-position: -7rem -2rem; @extend %doc-icon-2; } ._icon-bluebird:before { background-position: -8rem -2rem; @extend %doc-icon-2; } +._icon-eslint:before { background-position: -9rem -2rem; @extend %doc-icon-2; } diff --git a/lib/docs/filters/eslint/clean_html.rb b/lib/docs/filters/eslint/clean_html.rb index b5225038..c87e1ab7 100644 --- a/lib/docs/filters/eslint/clean_html.rb +++ b/lib/docs/filters/eslint/clean_html.rb @@ -3,6 +3,24 @@ module Docs class CleanHtmlFilter < Filter def call @doc = at_css('.doc') if at_css('.doc') + + css('.glyphicon').remove + css('hr', 'colgroup', 'td:empty').remove + + css('.container').each do |node| + node.before(node.children).remove + end + + css('div.highlighter-rouge').each do |node| + lang = node['class'][/language-(\w+)/, 1] + node['data-language'] = lang if lang + node.content = node.content.strip + node.name = 'pre' + node.remove_attribute('class') + end + + css('code', 'p').remove_attr('class') + doc end end diff --git a/lib/docs/filters/eslint/entries.rb b/lib/docs/filters/eslint/entries.rb index c8451bf2..d231829c 100644 --- a/lib/docs/filters/eslint/entries.rb +++ b/lib/docs/filters/eslint/entries.rb @@ -2,24 +2,22 @@ module Docs class Eslint class EntriesFilter < Docs::EntriesFilter def get_name - at_css('h1').content + name = at_css('h1').content.strip + + if subpath.start_with?('rules/') && subpath != 'rules/' + name = name[/\(([\w\-]+?)\)\z/, 1] || name[/\A([\w\-]+?):/, 1] + end + + name end def get_type - if subpath.start_with?('docs/developer-guide/') - type = 'Developer Guide' - elsif subpath.start_with?('docs/user-guide/') - type = 'User Guide' - elsif subpath.start_with?('docs/rules') + if subpath.include?('guide') + type = 'Guide' + elsif subpath.start_with?('rules') type = 'Rules' - elsif subpath.start_with?('docs/about') - type = 'User Guide' - else - type = nil end - type end - end end end diff --git a/lib/docs/scrapers/eslint.rb b/lib/docs/scrapers/eslint.rb index d0a3f636..fffedc35 100644 --- a/lib/docs/scrapers/eslint.rb +++ b/lib/docs/scrapers/eslint.rb @@ -1,11 +1,10 @@ module Docs class Eslint < UrlScraper self.name = 'ESLint' - self.type = 'eslint' - self.release = '4.9.0' - self.base_url = 'https://eslint.org/' - self.root_path = 'docs/user-guide/getting-started' - + self.type = 'simple' + self.release = '4.12.0' + self.base_url = 'https://eslint.org/docs/' + self.root_path = 'user-guide/getting-started' self.links = { home: 'https://eslint.org/', code: 'https://github.com/eslint/eslint' @@ -13,12 +12,11 @@ module Docs html_filters.push 'eslint/entries', 'eslint/clean_html' - options[:container] = 'body' - - options[:skip_patterns] = [/\Ablog/, /\Ademo/, /\Aparser/, /formatters\//] + options[:skip_patterns] = [/developer-guide/, /maintainer-guide/] + options[:skip] = %w(about about/ rules) options[:attribution] = <<-HTML - © Copyright JS Foundation and other contributors, https://js.foundation/
+ © JS Foundation and other contributors
Licensed under the MIT License. HTML end diff --git a/public/icons/docs/eslint/16.png b/public/icons/docs/eslint/16.png index 10e1edb099ce97816e834be20429fbecc2b312ae..97d48c754889c29dbfc1aab1c4b82d75e1a3521d 100644 GIT binary patch delta 304 zcmV-00nh&V1IhxBBYy!ANklk%7Ug*hfAt-#c|Z>pqyTp{0e*7Fs)Gj%84%FN1MK7i+|&g43ITuMC>@77 zDyGswEQT9l@rKuEHkoE?<&53>*vn z0##Sz4luzCOex6Kw$$AV{_qSpeCgh3d`fBWt#vNo;`TqGr}-lC)t zTP|L0YEx3aN)A5mio=u(H!UeCp`5j9t}d?wZB2<1HV3(JT7UV9wJx(YHe7gWn)&~q z=b4Y^`49Zj0ygkmzZN(z<}G^%qDqVF0^t+|Yyo9JsTmpI!op!-!%lFl)4PC917Cnq zrA3p{q8S)596-!-{n&Rm*fMi6_m&GQEw-i14oR6ERa)%i-g4zY(!{KPse$ME)4&SQ ztF%y3W*dQBAb)D&PJuxwBWIrL_W%l*Qd+D9Jl78aPe2I}Yl%lMf!iO7SeM>EsR0gv zXQ0XfmQ8ZOLceq^XsyeDB?qYdgA6JiV4{f3|B_()K7biVY4HTi6|N{{bt*i476I*p3#55#T_Xv+J0);Fpvgb4eqdNfNA$Q|7oAO W<#pw_d>>l?0000e+FhugBwU@dQ|kE4bjMtC)uro)(XQVGu73Lj+F( zWP<}@!ijJA3Ma(G8x(Q3cvLKbSU8V{sDrZ*3$qd1os+JVMSrg!V;~|Z+eAb^Jb{>~ z>}r5mI116c#d4&w*fu4W-~*fx#SSF3D;@$ZAd1g8fpY4){rkTSj<`sO;95JSaRlEW zislGmciBCKz=1pHR4&`T{{zON8ApZIxyitJka6<4Aqm{zJkP!kJKx?0c(edyP1h|fP0ViQI zn*h~+!AV#z@UB=s%l=T>{a+7I8V-nyzM+~DV5}BkJEG}Nz#>|Ju}Xl5Xpc+y3^DNq z7tkJ2l=jCc0URib|BN0)3n2J{#fYfgiW6Wm9%y^SiTjv}#QIGR3-KL-8HjB5JV=Fi z5PZX8k!QqG(%jAZR4N`E;(V-1IU= z%8NzD9-{EVdWBGApf?l3h^%hPDN61=6QqnoqwY#c$HFTM(tn4EU<9v-;(SrSpJz=V@S{b*USQ80qx>Fl&{#cQPMH?o6+m}dcqJ-R@;gah z2i7Jjy#((Ui+}Mnf>(i8fG*(slzUA;SKvpjRS}S+dkW}G@cK4z09a?N?l)E+2ReWd z7)>D21w2z#4g`L*6gVj)Tp0(>0Q-#9KPE(Og^=3_EG)tQ8rWg1{xy+6;71u?JMf8f z{1Zv3G?Z9Q=QJ@Ii06s$T zp}DM!06qKfE9I#rz*Y&n60eUHi}6@*Z*$Rc<_+LYV3|DkHQ;4q_0@k72>hr)Sa*x@ z2jgjQ@B%+lz_Y;S6wnrFt<_4S{3l7a1AgE~%9BR%K?T5K zErY0nejm{00WZn0`LE?U;AszNo5yva)sqsrHGdDre*sQoq>SlZGJMKm6@i1m z-O^T^0geLO1n5iPRbzF*X~peAbQ93(bkZ0Y0loqbg<;cm2e%RUR2o#Bbkp6&>U-se z(SJ(mcv%VK37`+S;;vL-SkU6-Iw5f$$cJImHx5=7SS15#6VM>}w%%AhoHPv=$PSn* zdH+6OKzZu7Q$rn-06jhTGfJsWU_l(mpXYMTlK>mnp3B6=_%Vs(TfoC5&8N>;{YTnD z(h8gd9xqY-1RMeejnyLw3rQQW0eA;^vVTPV9kAJ0ea$_rFN5>DM4-RSl6n{z4E*S0 z;DWJwObj>6bL^CDsGQ`1>s8gN0Db|ykN`Fzi8UYzxK*~DY{LChz-z|po7ECf!1J;L z)}@r)Z6UKP<<11K#a-truI2JMbqP39q2Vm8U>x8x;6kmRW-FxvvNeok4;YhWb|rXD mJwEWGB{dLG#_Bu#-{o%@q&+t}MFGPA0000 - - - - - - - - From 438fa8e6d04486fde5901ddb916ea09074d38e78 Mon Sep 17 00:00:00 2001 From: Cyril Lakech <1169286+clakech@users.noreply.github.com> Date: Tue, 24 Oct 2017 23:05:46 +0200 Subject: [PATCH 063/244] add brew doc (1.3.6) --- lib/docs/filters/brew/clean_html.rb | 9 +++++++++ lib/docs/filters/brew/entries.rb | 14 ++++++++++++++ lib/docs/scrapers/brew.rb | 22 ++++++++++++++++++++++ public/icons/docs/brew/16.png | Bin 0 -> 672 bytes public/icons/docs/brew/16@2x.png | Bin 0 -> 1462 bytes public/icons/docs/brew/SOURCE | Bin 0 -> 23281 bytes 6 files changed, 45 insertions(+) create mode 100644 lib/docs/filters/brew/clean_html.rb create mode 100644 lib/docs/filters/brew/entries.rb create mode 100644 lib/docs/scrapers/brew.rb create mode 100644 public/icons/docs/brew/16.png create mode 100644 public/icons/docs/brew/16@2x.png create mode 100644 public/icons/docs/brew/SOURCE diff --git a/lib/docs/filters/brew/clean_html.rb b/lib/docs/filters/brew/clean_html.rb new file mode 100644 index 00000000..59b893d7 --- /dev/null +++ b/lib/docs/filters/brew/clean_html.rb @@ -0,0 +1,9 @@ +module Docs + class Brew + class CleanHtmlFilter < Filter + def call + doc + end + end + end +end diff --git a/lib/docs/filters/brew/entries.rb b/lib/docs/filters/brew/entries.rb new file mode 100644 index 00000000..fdfdfd2b --- /dev/null +++ b/lib/docs/filters/brew/entries.rb @@ -0,0 +1,14 @@ +module Docs + class Brew + class EntriesFilter < Docs::EntriesFilter + def get_name + at_css('h1').content + end + + def get_type + name + end + + end + end +end diff --git a/lib/docs/scrapers/brew.rb b/lib/docs/scrapers/brew.rb new file mode 100644 index 00000000..ac3cc3e5 --- /dev/null +++ b/lib/docs/scrapers/brew.rb @@ -0,0 +1,22 @@ +module Docs + class Brew < UrlScraper + self.name = 'Homebrew' + self.type = 'brew' + self.release = '1.3.6' + self.base_url = 'https://docs.brew.sh' + self.root_path = '/' + self.links = { + home: 'https://brew.sh', + code: 'https://github.com/Homebrew/brew' + } + + options[:container] = ->(filter) { filter.root_page? ? '#home' : '#page' } + + html_filters.push 'brew/entries', 'brew/clean_html' + + options[:attribution] = <<-HTML + Homebrew was created by Max Howell.
+ Licensed under the BSD 2-Clause License. + HTML + end +end diff --git a/public/icons/docs/brew/16.png b/public/icons/docs/brew/16.png new file mode 100644 index 0000000000000000000000000000000000000000..0f58b0a1fd2f19ab265ffe7ffe325e09fef3820b GIT binary patch literal 672 zcmV;R0$=@!P)7({0xd~I zK~y-)ol?zfl5rgWJUXAJId^ELRuG%m!9%7*jmW{;B!bq1!`WOewJh6w<@x#TG?}J@`kcORpAX+RpffC!_okNionSDC ze}!t{rt^u!2KXZaK!m{ZG6X?DHk-?)(_7+Ut(yaZ z01**+yj;do&0`v^ zAs2pXUWLU!BYHmCZEse<#PEihr@9h0A%d~^}3`ZRsl&BG#bFhP8}CVuK}g+*i3Cj zTrSrvW6Zc;-_tIj-~}xjH9)EW90!Y`ALsawpr2MKc>PHL2|*BaT?Kl3l>=ZUK;oOR zM!f;l3Xm9`01z)0i_P3$BPjb+0IL8}wKY-AV{m9l>+yKzjYcB?C_4&hb;m)wUx2;s z)`u-;pw}B@N~Kb8I-M>6l_JM5Kf zp-`|aQ=6qvdwN9*!#$s?rdoKrKOGFG{C4~8CycSxgM>dLNdTc@k4hE*0000N4E7TRwQZ4sveRpL%^AMUx| zJ?HnGKi@qUf|HHF86cAXNj_?7`9b8bDGdUjOcDwxz;Qo99 zBoq}D|M}VRhBleZ8N~2SE0q)%xz`)>gJ`*@As|7_-@o(P-qxjTT z^oI{0el$nf*-y2hQmI0pCj|u+6&1p4HjA0WVzE4?tE;Q?u3x`i0L!1Z4fCq2tDF1# zdTBcDv4&(46BAKKM?QS(X|N->rcaIk>v7(9?C6;lC!4Nl^Y~IA_l_Fya{H%!&P&+k0qiY!u1K$s#T; z4j}}!wYB#;J3EsBcd!5&jYb158(ufa#=V5f+$_;AoLbOS1&2OZN?dd(=DpDX6c!dr zMx&9wzCQBu@+d7W)n{gAZUSoOT!aAttyT-JVF*!zECeQ94-H6g)YQ-D;ty%DECiVs zyc1l!c#*WUv?KZX`D?ds-RjK9$N)$VstW=D3WWkDMnJv*gaD6|=>$LDk@)1uLB^En z5UK#zAO?d0;1{6LVzG1vK4?J$C=?0}fN&4{007~67y++GaAJp+_X`$qu<#GO4+J=E z=yW;&9YA+?_g#R@%*>Ra0SpF%8UVKgLVN&B0{~bQCgbzn>AaE><}>LY3IJ#U91h1F zfTX0P;8PG2=r6Y&Nv;G*f=TCN>x2k2whUZ0{GZ|&zxM9HzyMmU)(|v+TCMh#wcB5W zLV(9T!^t8;xO^=i6&0oPYkMpfOCTyzPyi7T5i!0R7y-Ewyb~ZiGoNjKfcW_MKm_`F zdwYqEjpe@+^sE5k;o)IZ5s)c;EjZhxZ0AgShQT za+SXYX9ftQpt7=ZNli^n&%nUI-s0k7Y&ILfcrYhnq(-Ch@5+u40%_v@oFh6rT`|#5ce)4gaFwruQ`1H2M!$I*s)_ffZu`EpyvTV6X-%o zU*Idgz=fC|bns5Xq<0)#F? z3QL6OEKo*IZ{a}I4?gQal9`^KetqA*eWIyrkEKaBMI`A#fH5bGG0s!%sP7yKI QG5`Po07*qoM6N<$f*jqImH+?% literal 0 HcmV?d00001 diff --git a/public/icons/docs/brew/SOURCE b/public/icons/docs/brew/SOURCE new file mode 100644 index 0000000000000000000000000000000000000000..85aa2a146f3bb41964859d17084e45a01a903742 GIT binary patch literal 23281 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 Ef9jnt`Tzg` literal 0 HcmV?d00001 From b8c8a42f868fa261b26d24bd25fd48af29139a33 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 26 Nov 2017 18:55:05 -0500 Subject: [PATCH 064/244] Finish Homebrew scraper --- assets/images/docs-2.png | Bin 15491 -> 15956 bytes assets/images/docs-2@2x.png | Bin 37437 -> 38686 bytes assets/javascripts/news.json | 2 +- .../templates/pages/about_tmpl.coffee | 5 +++ assets/stylesheets/global/_icons.scss | 1 + lib/docs/filters/brew/clean_html.rb | 9 ----- lib/docs/filters/brew/entries.rb | 14 -------- lib/docs/filters/homebrew/clean_html.rb | 19 +++++++++++ lib/docs/filters/homebrew/entries.rb | 32 ++++++++++++++++++ lib/docs/scrapers/brew.rb | 22 ------------ lib/docs/scrapers/homebrew.rb | 24 +++++++++++++ public/icons/docs/brew/16.png | Bin 672 -> 0 bytes public/icons/docs/brew/16@2x.png | Bin 1462 -> 0 bytes public/icons/docs/brew/SOURCE | Bin 23281 -> 0 bytes public/icons/docs/homebrew/16.png | Bin 0 -> 551 bytes public/icons/docs/homebrew/16@2x.png | Bin 0 -> 1349 bytes public/icons/docs/homebrew/SOURCE | 1 + 17 files changed, 83 insertions(+), 46 deletions(-) delete mode 100644 lib/docs/filters/brew/clean_html.rb delete mode 100644 lib/docs/filters/brew/entries.rb create mode 100644 lib/docs/filters/homebrew/clean_html.rb create mode 100644 lib/docs/filters/homebrew/entries.rb delete mode 100644 lib/docs/scrapers/brew.rb create mode 100644 lib/docs/scrapers/homebrew.rb delete mode 100644 public/icons/docs/brew/16.png delete mode 100644 public/icons/docs/brew/16@2x.png delete mode 100644 public/icons/docs/brew/SOURCE create mode 100644 public/icons/docs/homebrew/16.png create mode 100644 public/icons/docs/homebrew/16@2x.png create mode 100644 public/icons/docs/homebrew/SOURCE diff --git a/assets/images/docs-2.png b/assets/images/docs-2.png index f60694b4c7113fe45a6210810207b2799681c91e..cee86d69e5be1ed6b6864df58803e1306d805595 100644 GIT binary patch delta 6188 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 delta 5119 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 E0D0~2mH+?% diff --git a/assets/javascripts/news.json b/assets/javascripts/news.json index b99986f7..c93f8ed9 100644 --- a/assets/javascripts/news.json +++ b/assets/javascripts/news.json @@ -1,7 +1,7 @@ [ [ "2017-11-26", - "New documentations: Bluebird and ESLint" + "New documentations: Bluebird, ESLint and Homebrew" ], [ "2017-11-18", "Added print & PDF stylesheet.\nFeedback welcome on Twitter and GitHub." diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index 9156cb82..8dfd77ef 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -302,6 +302,11 @@ credits = [ '2005-2016 Haxe Foundation', 'MIT', 'http://haxe.org/foundation/open-source.html' + ], [ + 'Homebrew', + '2009-present Homebrew contributors', + 'BSD', + 'https://raw.githubusercontent.com/Homebrew/brew/master/LICENSE.txt' ], [ 'Immutable.js', '2014-2016 Facebook, Inc.', diff --git a/assets/stylesheets/global/_icons.scss b/assets/stylesheets/global/_icons.scss index 26ed1cab..b4b433f1 100644 --- a/assets/stylesheets/global/_icons.scss +++ b/assets/stylesheets/global/_icons.scss @@ -166,3 +166,4 @@ ._icon-d:before { background-position: -7rem -2rem; @extend %doc-icon-2; } ._icon-bluebird:before { background-position: -8rem -2rem; @extend %doc-icon-2; } ._icon-eslint:before { background-position: -9rem -2rem; @extend %doc-icon-2; } +._icon-homebrew:before { background-position: 0 -3rem; @extend %doc-icon-2; } diff --git a/lib/docs/filters/brew/clean_html.rb b/lib/docs/filters/brew/clean_html.rb deleted file mode 100644 index 59b893d7..00000000 --- a/lib/docs/filters/brew/clean_html.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Docs - class Brew - class CleanHtmlFilter < Filter - def call - doc - end - end - end -end diff --git a/lib/docs/filters/brew/entries.rb b/lib/docs/filters/brew/entries.rb deleted file mode 100644 index fdfdfd2b..00000000 --- a/lib/docs/filters/brew/entries.rb +++ /dev/null @@ -1,14 +0,0 @@ -module Docs - class Brew - class EntriesFilter < Docs::EntriesFilter - def get_name - at_css('h1').content - end - - def get_type - name - end - - end - end -end diff --git a/lib/docs/filters/homebrew/clean_html.rb b/lib/docs/filters/homebrew/clean_html.rb new file mode 100644 index 00000000..5bf6aa29 --- /dev/null +++ b/lib/docs/filters/homebrew/clean_html.rb @@ -0,0 +1,19 @@ +module Docs + class Homebrew + class CleanHtmlFilter < Filter + def call + css('hr') + + css('div.highlighter-rouge').each do |node| + lang = node['class'][/language-(\w+)/, 1] + node['data-language'] = lang if lang + node.content = node.content.strip + node.name = 'pre' + node.remove_attribute('class') + end + + doc + end + end + end +end diff --git a/lib/docs/filters/homebrew/entries.rb b/lib/docs/filters/homebrew/entries.rb new file mode 100644 index 00000000..03650ad9 --- /dev/null +++ b/lib/docs/filters/homebrew/entries.rb @@ -0,0 +1,32 @@ +module Docs + class Homebrew + class EntriesFilter < Docs::EntriesFilter + def get_name + name = at_css('h1').content.strip + name.remove! %r{\(.*} + name + end + + CONTRIBUTOR_SLUGS = %w( + How-To-Open-a-Homebrew-Pull-Request + Formula-Cookbook + Acceptable-Formulae + Versions + Node-for-Formula-Authors + Python-for-Formula-Authors + Migrating-A-Formula-To-A-Tap + Rename-A-Formula + How-to-Create-and-Maintain-a-Tap + Brew-Test-Bot + Prose-Style-Guidelines) + + def get_type + if CONTRIBUTOR_SLUGS.include?(slug) + 'Contributors' + else + 'Users' + end + end + end + end +end diff --git a/lib/docs/scrapers/brew.rb b/lib/docs/scrapers/brew.rb deleted file mode 100644 index ac3cc3e5..00000000 --- a/lib/docs/scrapers/brew.rb +++ /dev/null @@ -1,22 +0,0 @@ -module Docs - class Brew < UrlScraper - self.name = 'Homebrew' - self.type = 'brew' - self.release = '1.3.6' - self.base_url = 'https://docs.brew.sh' - self.root_path = '/' - self.links = { - home: 'https://brew.sh', - code: 'https://github.com/Homebrew/brew' - } - - options[:container] = ->(filter) { filter.root_page? ? '#home' : '#page' } - - html_filters.push 'brew/entries', 'brew/clean_html' - - options[:attribution] = <<-HTML - Homebrew was created by Max Howell.
- Licensed under the BSD 2-Clause License. - HTML - end -end diff --git a/lib/docs/scrapers/homebrew.rb b/lib/docs/scrapers/homebrew.rb new file mode 100644 index 00000000..0298dd9b --- /dev/null +++ b/lib/docs/scrapers/homebrew.rb @@ -0,0 +1,24 @@ +module Docs + class Homebrew < UrlScraper + self.name = 'Homebrew' + self.type = 'simple' + self.release = '1.3.6' + self.base_url = 'https://docs.brew.sh/' + self.links = { + home: 'https://brew.sh', + code: 'https://github.com/Homebrew/brew' + } + + html_filters.push 'homebrew/entries', 'homebrew/clean_html' + + options[:container] = ->(filter) { filter.root_page? ? '#home' : '#page' } + + options[:skip_patterns] = [/maintainer/i, /core\-contributor/i] + options[:skip] = %w(Kickstarter-Supporters.html) + + options[:attribution] = <<-HTML + © 2009–present Homebrew contributors
+ Licensed under the BSD 2-Clause License. + HTML + end +end diff --git a/public/icons/docs/brew/16.png b/public/icons/docs/brew/16.png deleted file mode 100644 index 0f58b0a1fd2f19ab265ffe7ffe325e09fef3820b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 672 zcmV;R0$=@!P)7({0xd~I zK~y-)ol?zfl5rgWJUXAJId^ELRuG%m!9%7*jmW{;B!bq1!`WOewJh6w<@x#TG?}J@`kcORpAX+RpffC!_okNionSDC ze}!t{rt^u!2KXZaK!m{ZG6X?DHk-?)(_7+Ut(yaZ z01**+yj;do&0`v^ zAs2pXUWLU!BYHmCZEse<#PEihr@9h0A%d~^}3`ZRsl&BG#bFhP8}CVuK}g+*i3Cj zTrSrvW6Zc;-_tIj-~}xjH9)EW90!Y`ALsawpr2MKc>PHL2|*BaT?Kl3l>=ZUK;oOR zM!f;l3Xm9`01z)0i_P3$BPjb+0IL8}wKY-AV{m9l>+yKzjYcB?C_4&hb;m)wUx2;s z)`u-;pw}B@N~Kb8I-M>6l_JM5Kf zp-`|aQ=6qvdwN9*!#$s?rdoKrKOGFG{C4~8CycSxgM>dLNdTc@k4hE*0000N4E7TRwQZ4sveRpL%^AMUx| zJ?HnGKi@qUf|HHF86cAXNj_?7`9b8bDGdUjOcDwxz;Qo99 zBoq}D|M}VRhBleZ8N~2SE0q)%xz`)>gJ`*@As|7_-@o(P-qxjTT z^oI{0el$nf*-y2hQmI0pCj|u+6&1p4HjA0WVzE4?tE;Q?u3x`i0L!1Z4fCq2tDF1# zdTBcDv4&(46BAKKM?QS(X|N->rcaIk>v7(9?C6;lC!4Nl^Y~IA_l_Fya{H%!&P&+k0qiY!u1K$s#T; z4j}}!wYB#;J3EsBcd!5&jYb158(ufa#=V5f+$_;AoLbOS1&2OZN?dd(=DpDX6c!dr zMx&9wzCQBu@+d7W)n{gAZUSoOT!aAttyT-JVF*!zECeQ94-H6g)YQ-D;ty%DECiVs zyc1l!c#*WUv?KZX`D?ds-RjK9$N)$VstW=D3WWkDMnJv*gaD6|=>$LDk@)1uLB^En z5UK#zAO?d0;1{6LVzG1vK4?J$C=?0}fN&4{007~67y++GaAJp+_X`$qu<#GO4+J=E z=yW;&9YA+?_g#R@%*>Ra0SpF%8UVKgLVN&B0{~bQCgbzn>AaE><}>LY3IJ#U91h1F zfTX0P;8PG2=r6Y&Nv;G*f=TCN>x2k2whUZ0{GZ|&zxM9HzyMmU)(|v+TCMh#wcB5W zLV(9T!^t8;xO^=i6&0oPYkMpfOCTyzPyi7T5i!0R7y-Ewyb~ZiGoNjKfcW_MKm_`F zdwYqEjpe@+^sE5k;o)IZ5s)c;EjZhxZ0AgShQT za+SXYX9ftQpt7=ZNli^n&%nUI-s0k7Y&ILfcrYhnq(-Ch@5+u40%_v@oFh6rT`|#5ce)4gaFwruQ`1H2M!$I*s)_ffZu`EpyvTV6X-%o zU*Idgz=fC|bns5Xq<0)#F? z3QL6OEKo*IZ{a}I4?gQal9`^KetqA*eWIyrkEKaBMI`A#fH5bGG0s!%sP7yKI QG5`Po07*qoM6N<$f*jqImH+?% diff --git a/public/icons/docs/brew/SOURCE b/public/icons/docs/brew/SOURCE deleted file mode 100644 index 85aa2a146f3bb41964859d17084e45a01a903742..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23281 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 Ef9jnt`Tzg` diff --git a/public/icons/docs/homebrew/16.png b/public/icons/docs/homebrew/16.png new file mode 100644 index 0000000000000000000000000000000000000000..833e457cd249561a0546453902967bd833364de5 GIT binary patch literal 551 zcmV+?0@(eDP)P^uG#I{wSON9pz(l#gD#C5KLPZ8%j79j_tIzWe*OCA55(NaU^3(8?K`;t@GmTiry$Rz%Q$xIIARzU?b>x%;y1cRqk*go7cSu9 z#fz9Zb0%axeE1NesASR7tGh^%B3-RkD}LAg`}cpo=j7y|K!E~neWtK_&Dtnt_izYj zmLUG{1f1Nx1hUqzU4Kz2`LtMt;|y?digCX);(@n3-1afQ}i4%@iOxHQK2?%+N=r-3(I7A@nLdW)|cee p%+Jv=?44uBj&Vhc79IV!;VU~!TR5=2{dNEV002ovPDHLkV1ibs4ix|Z literal 0 HcmV?d00001 diff --git a/public/icons/docs/homebrew/16@2x.png b/public/icons/docs/homebrew/16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3128178e748e050eef3eb96ed7662ca2a2be5afd GIT binary patch literal 1349 zcmV-L1-kl)P)eaTHT-Ua3+qP}nwh`54np-<J|Z5#+MsZ1^- zV~M}SkX?KBp-|x>pyiw-ljxIwgl0>YF2{j`;mDuA02dK4dyX6rlO|32jugJ=)xkuB zB1MW~ztIG(&cFrSY1F7O|7RC}kV-Xb*2KxvXHm3RaYT$1X)!5?m}F$}8%aaGaH2)a zR_M^NlgyhpA5>};X#38P(9p~6J9I$v7A+AgR;+!rEt>enBrjRA6l@nS;nbP4U@bN~ z&YUyj^rz*|+s~c90F_Gpm=vDq(Lo6kCOmAXaPtKVhq(2?K@<1PF!75>*rsheRIXA5 z6)ILlzX1bq-eUbO@buYpFohq&n6cxqbN3!t?GEI~k@FHM-0AiJqFCzGsi7ze7>!1Q zzWw^cXbQ*N`3qpCE}uGmIvO=<1f$W2?%lhi|A2w0QL`2+-05;BkvMJIw3e+~x8hqe zsZ{7llTNGEqC|-jC||xjzNK^L&S=%D74qcC^F+`n3tvf+B*}jKgq}Tn;#- z3L-8UNBBXtlP6CCFRlWHbinPIc)hniEHg47d`ub~9-9UQa);p7t=qU@v7uOw6kxV* z-!40K>V(mwM`P5eQ3wnSyumLo;RCI%U%w7KJOyPf6>xDnpqL-eTj%jT|_FELy8ptydsuxxes%Nnoz(p{&meT$%~Fqtw>|HiV%@!9-xnmM#Ho zQ3Ee;f`^TVPY~I%WjpezfQ7C)Fp@vZ#hQtG~AAmquxkh{w99DriT!eKvG7X)0;Y{MhdD6>(mEGR?AWn2q#(*1IB)qv*pR54QqN_2h}>x`17k!90EX6b^?2 zdcB?}ABXo4UXpIkoH<~Wbs0F=ee2mx1;BLd*pWkP%=~xPaUqoC$JmCjrj~zRP?|5PXuC9l)%z->N@uRi{z|Eb&>jyu6 zsBi&+!VlD$GG#i^yLWGxOeT23y?gh-6OW!BkNHIwHEPrdq;MwxxRr=PRwhTKNRh%& zq)3tD^nAENA1C+f)~$Q5YSpS2=>s%8a^%QM`NkpD!bAQA;diCMfPkd?00000NkvXX Hu0mjf`%8&F literal 0 HcmV?d00001 diff --git a/public/icons/docs/homebrew/SOURCE b/public/icons/docs/homebrew/SOURCE new file mode 100644 index 00000000..f7c36907 --- /dev/null +++ b/public/icons/docs/homebrew/SOURCE @@ -0,0 +1 @@ +https://github.com/Homebrew/brew/tree/master/docs/img \ No newline at end of file From 87a88be921dfc779969bd7e6e666dea103c7c504 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:07:02 -0500 Subject: [PATCH 065/244] Update gems --- Gemfile.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e07de2b2..298217cd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,7 +6,7 @@ GEM i18n (~> 0.7) minitest (~> 5.1) tzinfo (~> 1.1) - backports (3.10.3) + backports (3.11.0) better_errors (2.4.0) coderay (>= 1.0.0) erubi (>= 1.0.0) @@ -18,13 +18,13 @@ GEM execjs coffee-script-source (1.12.2) concurrent-ruby (1.0.5) - daemons (1.2.5) + daemons (1.2.6) erubi (1.7.0) ethon (0.11.0) ffi (>= 1.3.0) eventmachine (1.2.5) execjs (2.7.0) - exifr (1.3.2) + exifr (1.3.3) ffi (1.9.18) fspath (3.1.0) highline (1.7.10) @@ -33,20 +33,20 @@ GEM nokogiri (>= 1.4) i18n (0.9.1) concurrent-ruby (~> 1.0) - image_optim (0.26.0) + image_optim (0.26.1) exifr (~> 1.2, >= 1.2.2) fspath (~> 3.0) image_size (~> 1.5) in_threads (~> 1.3) progress (~> 3.0, >= 3.0.1) - image_optim_pack (0.5.0.20171101) + image_optim_pack (0.5.0.20180103) fspath (>= 2.1, < 4) image_optim (~> 0.19) image_size (1.5.0) in_threads (1.5.0) method_source (0.9.0) mini_portile2 (2.3.0) - minitest (5.10.3) + minitest (5.11.1) multi_json (1.12.2) mustermann (1.0.1) nokogiri (1.8.1) @@ -69,7 +69,7 @@ GEM rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) rr (1.2.1) - sass (3.5.3) + sass (3.5.5) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) @@ -102,13 +102,13 @@ GEM tty-screen (~> 0.6.0) tty-which (~> 0.3.0) verse (~> 0.5.0) - tty-screen (0.6.3) + tty-screen (0.6.4) tty-which (0.3.0) typhoeus (1.3.0) ethon (>= 0.9.0) tzinfo (1.2.4) thread_safe (~> 0.1) - uglifier (3.2.0) + uglifier (4.1.3) execjs (>= 0.3.0, < 3) unicode-display_width (1.1.3) unicode_utils (1.4.0) From 46a2981aef6636f9fd42041a6c3b218a716ba75c Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:08:06 -0500 Subject: [PATCH 066/244] 2018 --- COPYRIGHT | 2 +- README.md | 2 +- assets/javascripts/lib/license.coffee | 2 +- assets/javascripts/templates/pages/about_tmpl.coffee | 2 +- assets/stylesheets/application-dark.css.scss | 2 +- assets/stylesheets/application.css.scss | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/COPYRIGHT b/COPYRIGHT index e194cf37..719895e9 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,4 +1,4 @@ -Copyright 2013-2017 Thibaut Courouble and other contributors +Copyright 2013-2018 Thibaut Courouble and other contributors This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/README.md b/README.md index f6859b90..4bb41868 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ DevDocs's own documentation is available on the [wiki](https://github.com/Thibau ## Copyright / License -Copyright 2013-2017 Thibaut Courouble and [other contributors](https://github.com/Thibaut/devdocs/graphs/contributors) +Copyright 2013-2018 Thibaut Courouble and [other contributors](https://github.com/Thibaut/devdocs/graphs/contributors) This software is licensed under the terms of the Mozilla Public License v2.0. See the [COPYRIGHT](https://github.com/Thibaut/devdocs/blob/master/COPYRIGHT) and [LICENSE](https://github.com/Thibaut/devdocs/blob/master/LICENSE) files. diff --git a/assets/javascripts/lib/license.coffee b/assets/javascripts/lib/license.coffee index 484d865c..8ff7c6e2 100644 --- a/assets/javascripts/lib/license.coffee +++ b/assets/javascripts/lib/license.coffee @@ -1,5 +1,5 @@ ### - * Copyright 2013-2017 Thibaut Courouble and other contributors + * Copyright 2013-2018 Thibaut Courouble and other contributors * * This source code is licensed under the terms of the Mozilla * Public License, v. 2.0, a copy of which may be obtained at: diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index 8dfd77ef..963edf38 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -28,7 +28,7 @@ app.templates.aboutPage = -> """

- Copyright 2013–2017 Thibaut Courouble and other contributors
+ Copyright 2013–2018 Thibaut Courouble and other contributors
This software is licensed under the terms of the Mozilla Public License v2.0.
You may obtain a copy of the source code at github.com/Thibaut/devdocs.
For more information, see the COPYRIGHT diff --git a/assets/stylesheets/application-dark.css.scss b/assets/stylesheets/application-dark.css.scss index c88ada20..96d5e445 100644 --- a/assets/stylesheets/application-dark.css.scss +++ b/assets/stylesheets/application-dark.css.scss @@ -4,7 +4,7 @@ //= depend_on docs-2@2x.png /*! - * Copyright 2013-2017 Thibaut Courouble and other contributors + * Copyright 2013-2018 Thibaut Courouble and other contributors * * This source code is licensed under the terms of the Mozilla * Public License, v. 2.0, a copy of which may be obtained at: diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss index f8b8a3c0..e4314a0f 100644 --- a/assets/stylesheets/application.css.scss +++ b/assets/stylesheets/application.css.scss @@ -4,7 +4,7 @@ //= depend_on docs-2@2x.png /*! - * Copyright 2013-2017 Thibaut Courouble and other contributors + * Copyright 2013-2018 Thibaut Courouble and other contributors * * This source code is licensed under the terms of the Mozilla * Public License, v. 2.0, a copy of which may be obtained at: From 118d85fd895f0dc2ee385f469c77e9aaf678c5c0 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:11:05 -0500 Subject: [PATCH 067/244] Remove Gratipay --- README.md | 2 -- assets/javascripts/templates/pages/about_tmpl.coffee | 2 -- assets/javascripts/templates/pages/root_tmpl.coffee.erb | 2 -- 3 files changed, 6 deletions(-) diff --git a/README.md b/README.md index 4bb41868..03786ac5 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,6 @@ Keep track of development news: * Follow [@DevDocs](https://twitter.com/DevDocs) on Twitter * Join the [mailing list](https://groups.google.com/d/forum/devdocs) -DevDocs is free and open source. If you like it, please consider supporting my work on [Gratipay](https://gratipay.com/devdocs/). Thanks! - **Table of Contents:** [Quick Start](#quick-start) · [Vision](#vision) · [App](#app) · [Scraper](#scraper) · [Commands](#available-commands) · [Contributing](#contributing) · [License](#copyright--license) · [Questions?](#questions) ## Quick Start diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index 963edf38..13e6310b 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -23,8 +23,6 @@ app.templates.aboutPage = -> """

  • Watch the repository on GitHub
  • Join the mailing list -

    If you like DevDocs, please spread the word and consider supporting my work on - Gratipay. Thanks!

    diff --git a/assets/javascripts/templates/pages/root_tmpl.coffee.erb b/assets/javascripts/templates/pages/root_tmpl.coffee.erb index bfb3f3d6..44dbf4fb 100644 --- a/assets/javascripts/templates/pages/root_tmpl.coffee.erb +++ b/assets/javascripts/templates/pages/root_tmpl.coffee.erb @@ -19,7 +19,6 @@ app.templates.intro = """

  • DevDocs is licensed under the terms of the Mozilla Public License v2.0. For more information, see the COPYRIGHT and LICENSE files. -
  • If you like the app, please consider supporting the project on Gratipay. Thanks!

    Happy coding! @@ -41,7 +40,6 @@ app.templates.intro = """

  • For the latest news, follow @DevDocs.
  • DevDocs is free and open source. -
  • If you like the app, please consider supporting the project on Gratipay. Thanks!
  • And if you're new to coding, check out freeCodeCamp's open source curriculum.

    Happy coding! From 704709ba9b3ec6a5c98a2ed2b8e6c708567fe39c Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:11:13 -0500 Subject: [PATCH 068/244] Update Angular documentation (5.1.3) --- assets/javascripts/templates/pages/about_tmpl.coffee | 2 +- lib/docs/scrapers/angular.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index 13e6310b..c2a251c2 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -87,7 +87,7 @@ app.templates.aboutPage = -> """ credits = [ [ 'Angular
    Angular.js', - '2010-2017 Google, Inc.', + '2010-2018 Google, Inc.', 'CC BY', 'https://creativecommons.org/licenses/by/4.0/' ], [ diff --git a/lib/docs/scrapers/angular.rb b/lib/docs/scrapers/angular.rb index 17fd32dc..a3daaf22 100644 --- a/lib/docs/scrapers/angular.rb +++ b/lib/docs/scrapers/angular.rb @@ -11,7 +11,7 @@ module Docs options[:max_image_size] = 256_000 options[:attribution] = <<-HTML - © 2010–2017 Google, Inc.
    + © 2010–2018 Google, Inc.
    Licensed under the Creative Commons Attribution License 4.0. HTML @@ -59,7 +59,7 @@ module Docs end version do - self.release = '5.0.1' + self.release = '5.1.3' self.base_url = 'https://angular.io/' self.root_path = 'docs' From 6b33e3c9d62cdac90c3b149f6b2b0e8ece171305 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:16:39 -0500 Subject: [PATCH 069/244] Update Clojure documentation (1.9) --- lib/docs/scrapers/clojure.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/docs/scrapers/clojure.rb b/lib/docs/scrapers/clojure.rb index f5148f4e..c6bdcdea 100644 --- a/lib/docs/scrapers/clojure.rb +++ b/lib/docs/scrapers/clojure.rb @@ -13,9 +13,14 @@ module Docs Licensed under the Eclipse Public License 1.0. HTML + version '1.9' do + self.release = '1.9' + self.base_url = 'https://clojure.github.io/clojure/' + end + version '1.8' do self.release = '1.8' - self.base_url = 'https://clojure.github.io/clojure/' + self.base_url = 'https://clojure.github.io/clojure/branch-clojure-1.8.0/' end version '1.7' do From ee2ac4eb8bb1a27dbbd5e764088fc2946e09a627 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:18:40 -0500 Subject: [PATCH 070/244] Update CMake documentation (3.10.1) --- lib/docs/scrapers/cmake.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/docs/scrapers/cmake.rb b/lib/docs/scrapers/cmake.rb index 45628461..1cb00dd1 100644 --- a/lib/docs/scrapers/cmake.rb +++ b/lib/docs/scrapers/cmake.rb @@ -20,8 +20,13 @@ module Docs Licensed under the BSD 3-clause License. HTML + version '3.10' do + self.release = '3.10.1' + self.base_url = 'https://cmake.org/cmake/help/v3.10/' + end + version '3.9' do - self.release = '3.9.0' + self.release = '3.9.6' self.base_url = 'https://cmake.org/cmake/help/v3.9/' end From 01bd4c5ebe95a5e127825a86c2ede20490d058cb Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:20:02 -0500 Subject: [PATCH 071/244] Update CodeceptJS documentation (1.1.1) --- lib/docs/scrapers/codeceptjs.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/codeceptjs.rb b/lib/docs/scrapers/codeceptjs.rb index 6f6db93e..0f73e0d8 100644 --- a/lib/docs/scrapers/codeceptjs.rb +++ b/lib/docs/scrapers/codeceptjs.rb @@ -3,7 +3,7 @@ module Docs self.name = 'CodeceptJS' self.type = 'codeceptjs' self.root_path = 'index.html' - self.release = '1.0.1' + self.release = '1.1.1' self.base_url = 'http://codecept.io/' self.links = { home: 'http://codecept.io/', From e8c0857279adba89a462fc3bacb0139049f6c3a6 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:20:39 -0500 Subject: [PATCH 072/244] Update CoffeeScript documentation (2.1.1) --- lib/docs/scrapers/coffeescript.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/coffeescript.rb b/lib/docs/scrapers/coffeescript.rb index 0b75ae34..0ebf5e10 100644 --- a/lib/docs/scrapers/coffeescript.rb +++ b/lib/docs/scrapers/coffeescript.rb @@ -16,7 +16,7 @@ module Docs HTML version '2' do - self.release = '2.0.2' + self.release = '2.1.1' self.base_url = 'http://coffeescript.org/' html_filters.push 'coffeescript/entries', 'coffeescript/clean_html', 'title' From 5bf6916ffa6c763a4d3bf2d87b87744dbe710ca9 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:27:33 -0500 Subject: [PATCH 073/244] Update Crystal documentation (0.24.1) --- lib/docs/scrapers/crystal.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/crystal.rb b/lib/docs/scrapers/crystal.rb index aa7ce99b..1e95e540 100644 --- a/lib/docs/scrapers/crystal.rb +++ b/lib/docs/scrapers/crystal.rb @@ -1,7 +1,7 @@ module Docs class Crystal < UrlScraper self.type = 'crystal' - self.release = '0.23.0' + self.release = '0.24.1' self.base_url = 'https://crystal-lang.org/' self.root_path = "api/#{release}/index.html" self.initial_paths = %w(docs/index.html) From 2def74758615bb1485cc938e58763c805bdbcee0 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:27:51 -0500 Subject: [PATCH 074/244] Update Bootstrap documentation (4.0.0-beta.3) --- lib/docs/scrapers/bootstrap.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/bootstrap.rb b/lib/docs/scrapers/bootstrap.rb index 7858e40e..3653bb2d 100644 --- a/lib/docs/scrapers/bootstrap.rb +++ b/lib/docs/scrapers/bootstrap.rb @@ -16,7 +16,7 @@ module Docs HTML version '4' do - self.release = '4.0.0-beta.2' + self.release = '4.0.0-beta.3' self.base_url = 'https://getbootstrap.com/docs/4.0/' self.root_path = 'getting-started/introduction/' From 404884919ea5ac892ea1adb43661739d470aa152 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:29:19 -0500 Subject: [PATCH 075/244] Update D3.js documentation (4.12.2) --- lib/docs/scrapers/d3.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/d3.rb b/lib/docs/scrapers/d3.rb index 9497d572..d222d64f 100644 --- a/lib/docs/scrapers/d3.rb +++ b/lib/docs/scrapers/d3.rb @@ -17,7 +17,7 @@ module Docs HTML version '4' do - self.release = '4.11.0' + self.release = '4.12.2' self.base_url = 'https://github.com/d3/' self.root_path = 'd3/blob/master/API.md' From c97453aa84cc9f964064bec60bdb33a394093403 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:30:27 -0500 Subject: [PATCH 076/244] Update ESLint documentation (4.15.0) --- lib/docs/filters/eslint/entries.rb | 8 +++++--- lib/docs/scrapers/eslint.rb | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/docs/filters/eslint/entries.rb b/lib/docs/filters/eslint/entries.rb index d231829c..42b66f36 100644 --- a/lib/docs/filters/eslint/entries.rb +++ b/lib/docs/filters/eslint/entries.rb @@ -12,10 +12,12 @@ module Docs end def get_type - if subpath.include?('guide') - type = 'Guide' + if subpath.include?('developer-guide') + 'Developer Guide' + elsif subpath.include?('guide') + 'Guide' elsif subpath.start_with?('rules') - type = 'Rules' + 'Rules' end end end diff --git a/lib/docs/scrapers/eslint.rb b/lib/docs/scrapers/eslint.rb index fffedc35..b45025ba 100644 --- a/lib/docs/scrapers/eslint.rb +++ b/lib/docs/scrapers/eslint.rb @@ -2,7 +2,7 @@ module Docs class Eslint < UrlScraper self.name = 'ESLint' self.type = 'simple' - self.release = '4.12.0' + self.release = '4.15.0' self.base_url = 'https://eslint.org/docs/' self.root_path = 'user-guide/getting-started' self.links = { @@ -12,7 +12,7 @@ module Docs html_filters.push 'eslint/entries', 'eslint/clean_html' - options[:skip_patterns] = [/developer-guide/, /maintainer-guide/] + options[:skip_patterns] = [/maintainer-guide/] options[:skip] = %w(about about/ rules) options[:attribution] = <<-HTML From 6700c5e30c9f4a6c026dd63395bba1494736b181 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:30:51 -0500 Subject: [PATCH 077/244] Update Fish documentation (2.7.1) --- lib/docs/scrapers/fish.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/docs/scrapers/fish.rb b/lib/docs/scrapers/fish.rb index c54cea4a..ac098d45 100644 --- a/lib/docs/scrapers/fish.rb +++ b/lib/docs/scrapers/fish.rb @@ -17,6 +17,11 @@ module Docs Licensed under the GNU General Public License, version 2. HTML + version '2.7' do + self.release = '2.7.1' + self.base_url = "https://fishshell.com/docs/#{version}/" + end + version '2.6' do self.release = '2.6.0' self.base_url = "https://fishshell.com/docs/#{version}/" From 3c7e7ff1d7d82f53ed38a9a4b3aac87c33e8f791 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:31:33 -0500 Subject: [PATCH 078/244] Update Flow documentation (0.63.0) --- lib/docs/scrapers/flow.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/flow.rb b/lib/docs/scrapers/flow.rb index e184a591..edc04f97 100644 --- a/lib/docs/scrapers/flow.rb +++ b/lib/docs/scrapers/flow.rb @@ -1,7 +1,7 @@ module Docs class Flow < UrlScraper self.type = 'flow' - self.release = '0.59.0' + self.release = '0.63.0' self.base_url = 'https://flow.org/en/docs/' self.links = { home: 'https://flow.org/', From 01d0f1cda4b503b8b7727d6f9f54e38e5fff54a0 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:32:26 -0500 Subject: [PATCH 079/244] Update Git documentation (2.15.1) --- lib/docs/scrapers/git.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/git.rb b/lib/docs/scrapers/git.rb index 223b48c2..3c48ab50 100644 --- a/lib/docs/scrapers/git.rb +++ b/lib/docs/scrapers/git.rb @@ -1,7 +1,7 @@ module Docs class Git < UrlScraper self.type = 'git' - self.release = '2.14.3' + self.release = '2.15.1' self.base_url = 'https://git-scm.com/docs' self.initial_paths = %w(/git.html) self.links = { From 4d7d2b7d0acce1d31d070dcf0263368cc9d25a72 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:32:50 -0500 Subject: [PATCH 080/244] Update Homebrew documentation (1.4.2) --- lib/docs/scrapers/homebrew.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/homebrew.rb b/lib/docs/scrapers/homebrew.rb index 0298dd9b..1e1c1633 100644 --- a/lib/docs/scrapers/homebrew.rb +++ b/lib/docs/scrapers/homebrew.rb @@ -2,7 +2,7 @@ module Docs class Homebrew < UrlScraper self.name = 'Homebrew' self.type = 'simple' - self.release = '1.3.6' + self.release = '1.4.2' self.base_url = 'https://docs.brew.sh/' self.links = { home: 'https://brew.sh', From eb1450edeed6d3cb1cf7b0ede7e4db1e40df76ac Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:34:55 -0500 Subject: [PATCH 081/244] Update Jest documentation (22.0.4) --- lib/docs/filters/jest/clean_html.rb | 2 +- lib/docs/scrapers/jest.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/docs/filters/jest/clean_html.rb b/lib/docs/filters/jest/clean_html.rb index 9d88383f..394316b6 100644 --- a/lib/docs/filters/jest/clean_html.rb +++ b/lib/docs/filters/jest/clean_html.rb @@ -18,7 +18,7 @@ module Docs end css('pre').each do |node| - node['data-language'] = node['class'][/language-(\w+)/, 1] + node['data-language'] = node['class'][/language-(\w+)/, 1] if node['class'] node.content = node.content end diff --git a/lib/docs/scrapers/jest.rb b/lib/docs/scrapers/jest.rb index 8112f69e..88712474 100644 --- a/lib/docs/scrapers/jest.rb +++ b/lib/docs/scrapers/jest.rb @@ -1,7 +1,7 @@ module Docs class Jest < UrlScraper self.type = 'jest' - self.release = '21.2.1' + self.release = '22.0.4' self.base_url = 'https://facebook.github.io/jest/docs/en/' self.root_path = 'getting-started.html' self.links = { From 922ab804893287a91ee4485befafba8c9704ab55 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:35:53 -0500 Subject: [PATCH 082/244] Update Julia documentation (0.6.2) --- lib/docs/scrapers/julia.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/julia.rb b/lib/docs/scrapers/julia.rb index d1c798f8..6a411b70 100644 --- a/lib/docs/scrapers/julia.rb +++ b/lib/docs/scrapers/julia.rb @@ -13,7 +13,7 @@ module Docs HTML version '0.6' do - self.release = '0.6.0' + self.release = '0.6.2' self.base_url = 'https://docs.julialang.org/en/release-0.6/' self.type = 'julia' From 30ac44746d7fb843a55e44eb6d64b33229e9ee0c Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:37:45 -0500 Subject: [PATCH 083/244] Update Laravel documentation (5.5.28) --- lib/docs/scrapers/laravel.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/laravel.rb b/lib/docs/scrapers/laravel.rb index 69cba641..c5dc9fef 100644 --- a/lib/docs/scrapers/laravel.rb +++ b/lib/docs/scrapers/laravel.rb @@ -30,7 +30,7 @@ module Docs HTML version '5.5' do - self.release = '5.5.0' + self.release = '5.5.28' self.root_path = '/api/5.5/index.html' self.initial_paths = %w(/docs/5.5/installation /api/5.5/classes.html) From a82c4711161d1ed97cd395c471b490f528cb0647 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:38:46 -0500 Subject: [PATCH 084/244] Update Mocha documentation (4.1.0) --- lib/docs/scrapers/mocha.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/mocha.rb b/lib/docs/scrapers/mocha.rb index 1f6d870b..0dc4ac7b 100644 --- a/lib/docs/scrapers/mocha.rb +++ b/lib/docs/scrapers/mocha.rb @@ -1,7 +1,7 @@ module Docs class Mocha < UrlScraper self.type = 'mocha' - self.release = '4.0.1' + self.release = '4.1.0' self.base_url = 'https://mochajs.org/' self.links = { home: 'https://mochajs.org/', From 6b1b270fea630f647670e336dd4ff819384fc264 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:39:10 -0500 Subject: [PATCH 085/244] Update nginx documentation (1.13.8) --- lib/docs/scrapers/nginx.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/nginx.rb b/lib/docs/scrapers/nginx.rb index a4e8897c..c65935ee 100644 --- a/lib/docs/scrapers/nginx.rb +++ b/lib/docs/scrapers/nginx.rb @@ -2,7 +2,7 @@ module Docs class Nginx < UrlScraper self.name = 'nginx' self.type = 'nginx' - self.release = '1.13.6' + self.release = '1.13.8' self.base_url = 'https://nginx.org/en/docs/' self.links = { home: 'https://nginx.org/', From 55c23bbc787e56836f0327432edb278ecc34f7fb Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:40:41 -0500 Subject: [PATCH 086/244] Update Node.js documentation (9.3.0) --- lib/docs/scrapers/node.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/docs/scrapers/node.rb b/lib/docs/scrapers/node.rb index fc725779..bc09d197 100644 --- a/lib/docs/scrapers/node.rb +++ b/lib/docs/scrapers/node.rb @@ -23,22 +23,22 @@ module Docs HTML version do - self.release = '9.1.0' + self.release = '9.3.0' self.base_url = 'https://nodejs.org/dist/latest-v9.x/docs/api/' end version '8 LTS' do - self.release = '8.9.1' + self.release = '8.9.4' self.base_url = 'https://nodejs.org/dist/latest-v8.x/docs/api/' end version '6 LTS' do - self.release = '6.12.0' + self.release = '6.12.3' self.base_url = 'https://nodejs.org/dist/latest-v6.x/docs/api/' end version '4 LTS' do - self.release = '4.8.6' + self.release = '4.8.7' self.base_url = 'https://nodejs.org/dist/latest-v4.x/docs/api/' end end From 495a4e9c05a7e202e097c729d40f6a87e6ec5805 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:41:55 -0500 Subject: [PATCH 087/244] Update npm documentation (5.6.0) --- lib/docs/scrapers/npm.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/npm.rb b/lib/docs/scrapers/npm.rb index f5211df7..6c07df9b 100644 --- a/lib/docs/scrapers/npm.rb +++ b/lib/docs/scrapers/npm.rb @@ -2,7 +2,7 @@ module Docs class Npm < UrlScraper self.name = 'npm' self.type = 'npm' - self.release = '5.5.1' + self.release = '5.6.0' self.base_url = 'https://docs.npmjs.com/' self.force_gzip = true self.links = { From a90f0a3f565e62cb1ca28d8512b034bb89ea970f Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:44:23 -0500 Subject: [PATCH 088/244] Update pandas documentation (0.22.0) --- lib/docs/scrapers/pandas.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/docs/scrapers/pandas.rb b/lib/docs/scrapers/pandas.rb index 1ab3692d..4879c8c1 100644 --- a/lib/docs/scrapers/pandas.rb +++ b/lib/docs/scrapers/pandas.rb @@ -20,6 +20,11 @@ module Docs Licensed under the 3-clause BSD License. HTML + version '0.22' do + self.release = '0.22.0' + self.base_url = "http://pandas.pydata.org/pandas-docs/version/#{self.release}/" + end + version '0.21' do self.release = '0.21.0' self.base_url = "http://pandas.pydata.org/pandas-docs/version/#{self.release}/" From 967a5d691d8e005d5490956628a74a42edd95801 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:44:39 -0500 Subject: [PATCH 089/244] Update PHPUnit documentation (6.5) --- lib/docs/scrapers/phpunit.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/phpunit.rb b/lib/docs/scrapers/phpunit.rb index aba16947..665ca4c7 100644 --- a/lib/docs/scrapers/phpunit.rb +++ b/lib/docs/scrapers/phpunit.rb @@ -24,7 +24,7 @@ module Docs HTML version '6' do - self.release = '6.4' + self.release = '6.5' self.base_url = "https://phpunit.de/manual/#{release}/en/" end From 15872cfa4c1f48d269ae54f71f647702b40492b1 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:44:52 -0500 Subject: [PATCH 090/244] Update Pug documentation (2.0.0-rc.4) --- lib/docs/scrapers/pug.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/pug.rb b/lib/docs/scrapers/pug.rb index e7a3a21c..4802aa23 100644 --- a/lib/docs/scrapers/pug.rb +++ b/lib/docs/scrapers/pug.rb @@ -3,7 +3,7 @@ module Docs self.type = 'pug' self.base_url = 'https://pugjs.org/' self.root_path = 'api/getting-started.html' - self.release = '2.0.0-rc.2' + self.release = '2.0.0-rc.4' self.links = { home: 'https://pugjs.org/', code: 'https://github.com/pugjs/pug' From d9033ef65e5bdaf7b4b53a983d5fe97a123fef92 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:48:01 -0500 Subject: [PATCH 091/244] Update Python documentation (3.6.4) --- assets/javascripts/templates/pages/about_tmpl.coffee | 2 +- lib/docs/scrapers/python.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index c2a251c2..1d8694b1 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -522,7 +522,7 @@ credits = [ 'https://www.postgresql.org/about/licence/' ], [ 'Python', - '2001-2017 Python Software Foundation
    Python is a trademark of the Python Software Foundation.', + '2001-2018 Python Software Foundation
    Python is a trademark of the Python Software Foundation.', 'PSFL', 'https://docs.python.org/3/license.html' ], [ diff --git a/lib/docs/scrapers/python.rb b/lib/docs/scrapers/python.rb index baad2ddb..8b0289d5 100644 --- a/lib/docs/scrapers/python.rb +++ b/lib/docs/scrapers/python.rb @@ -19,12 +19,12 @@ module Docs library/sunau.html) options[:attribution] = <<-HTML - © 2001–2017 Python Software Foundation
    + © 2001–2018 Python Software Foundation
    Licensed under the PSF License. HTML version '3.6' do - self.release = '3.6.1' + self.release = '3.6.4' self.dir = '/Users/Thibaut/DevDocs/Docs/Python36' # docs.python.org/3.6/download.html self.base_url = 'https://docs.python.org/3.6/' From 3c84eadba19c865f2abc35a784a8ae4983ec4719 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:51:23 -0500 Subject: [PATCH 092/244] Update React documentation (16.2.0) --- assets/javascripts/templates/pages/about_tmpl.coffee | 4 ++-- lib/docs/scrapers/react.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index 1d8694b1..ce0d5c37 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -537,9 +537,9 @@ credits = [ 'https://raw.githubusercontent.com/ramda/ramda/master/LICENSE.txt' ], [ 'React, React Native, Flow, Relay', - '2013-2017 Facebook Inc.', + '2013-present Facebook Inc.', 'CC BY', - 'https://raw.githubusercontent.com/facebook/react/master/LICENSE-docs' + 'https://raw.githubusercontent.com/reactjs/reactjs.org/master/LICENSE-DOCS.md' ], [ 'Redis', '2009-2017 Salvatore Sanfilippo', diff --git a/lib/docs/scrapers/react.rb b/lib/docs/scrapers/react.rb index 11872e5e..6bf26299 100644 --- a/lib/docs/scrapers/react.rb +++ b/lib/docs/scrapers/react.rb @@ -2,7 +2,7 @@ module Docs class React < UrlScraper self.name = 'React' self.type = 'simple' - self.release = '16.1.0' + self.release = '16.2.0' self.base_url = 'https://reactjs.org/docs/' self.root_path = 'hello-world.html' self.links = { @@ -27,7 +27,7 @@ module Docs } options[:attribution] = <<-HTML - © 2013–2017 Facebook Inc.
    + © 2013–present Facebook Inc.
    Licensed under the Creative Commons Attribution 4.0 International Public License. HTML end From 1a776d5b75e4075bcf381a08438c81585e94caac Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:54:36 -0500 Subject: [PATCH 093/244] Update Redis documentation (4.0.6) --- lib/docs/scrapers/redis.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/redis.rb b/lib/docs/scrapers/redis.rb index 3dc4aae1..714facb9 100644 --- a/lib/docs/scrapers/redis.rb +++ b/lib/docs/scrapers/redis.rb @@ -1,7 +1,7 @@ module Docs class Redis < UrlScraper self.type = 'redis' - self.release = '4.0.2' + self.release = '4.0.6' self.base_url = 'https://redis.io/commands' self.links = { home: 'https://redis.io/', From 4792f559cbb4f10b7a751dc61f937d6ae99584b4 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 18:58:29 -0500 Subject: [PATCH 094/244] Update Rust documentation (1.23.0) --- lib/docs/scrapers/rust.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/rust.rb b/lib/docs/scrapers/rust.rb index b4e89b66..27c873dd 100644 --- a/lib/docs/scrapers/rust.rb +++ b/lib/docs/scrapers/rust.rb @@ -1,7 +1,7 @@ module Docs class Rust < UrlScraper self.type = 'rust' - self.release = '1.21.0' + self.release = '1.23.0' self.base_url = 'https://doc.rust-lang.org/' self.root_path = 'book/first-edition/index.html' self.initial_paths = %w( From d41a9346ae658e521744738bd02ce9c0c437c63a Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 19:05:03 -0500 Subject: [PATCH 095/244] Update webpack documentation (3.10.0) --- lib/docs/scrapers/webpack.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/webpack.rb b/lib/docs/scrapers/webpack.rb index 02f1e599..1120d403 100644 --- a/lib/docs/scrapers/webpack.rb +++ b/lib/docs/scrapers/webpack.rb @@ -4,7 +4,7 @@ module Docs self.type = 'webpack' version do - self.release = '3.8.1' + self.release = '3.10.0' self.base_url = 'https://webpack.js.org/' self.root_path = 'guides/' self.initial_paths = %w( From 9590c529efebd58bae1ff8477d1504bb1d0c6c58 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 19:05:28 -0500 Subject: [PATCH 096/244] Update Symfony documentation (4.0.3) --- lib/docs/scrapers/symfony.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/docs/scrapers/symfony.rb b/lib/docs/scrapers/symfony.rb index fed9a45a..c50b7041 100644 --- a/lib/docs/scrapers/symfony.rb +++ b/lib/docs/scrapers/symfony.rb @@ -26,8 +26,18 @@ module Docs Licensed under the MIT License. HTML + version '4.0' do + self.release = '4.0.3' + self.base_url = "http://api.symfony.com/#{version}/" + end + + version '3.4' do + self.release = '3.4.3' + self.base_url = "http://api.symfony.com/#{version}/" + end + version '3.3' do - self.release = '3.3.10' + self.release = '3.3.15' self.base_url = "http://api.symfony.com/#{version}/" end From 49e2c4b0f22ee85b6daaf385b6008b1d44520049 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 7 Jan 2018 19:05:30 -0500 Subject: [PATCH 097/244] Update Vue.js documentation (2.5.13) --- lib/docs/scrapers/vue.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/vue.rb b/lib/docs/scrapers/vue.rb index 8e947049..e8e29406 100644 --- a/lib/docs/scrapers/vue.rb +++ b/lib/docs/scrapers/vue.rb @@ -20,7 +20,7 @@ module Docs HTML version '2' do - self.release = '2.5.2' + self.release = '2.5.13' self.base_url = 'https://vuejs.org/v2/' self.root_path = 'guide/index.html' self.initial_paths = %w(api/) From 7c3a761c63499791a8097b986fc28f0079f54cf8 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 14 Jan 2018 13:20:29 -0500 Subject: [PATCH 098/244] Update Ruby documentation (2.5.0) --- lib/docs/scrapers/rdoc/ruby.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/docs/scrapers/rdoc/ruby.rb b/lib/docs/scrapers/rdoc/ruby.rb index d8f3b798..35f34462 100644 --- a/lib/docs/scrapers/rdoc/ruby.rb +++ b/lib/docs/scrapers/rdoc/ruby.rb @@ -76,18 +76,23 @@ module Docs Licensed under their own licenses. HTML + version '2.5' do + self.release = '2.5.0' + self.dir = '/Users/Thibaut/DevDocs/Docs/RDoc/Ruby25' + end + version '2.4' do - self.release = '2.4.1' + self.release = '2.4.3' self.dir = '/Users/Thibaut/DevDocs/Docs/RDoc/Ruby24' end version '2.3' do - self.release = '2.3.4' + self.release = '2.3.6' self.dir = '/Users/Thibaut/DevDocs/Docs/RDoc/Ruby23' end version '2.2' do - self.release = '2.2.7' + self.release = '2.2.9' self.dir = '/Users/Thibaut/DevDocs/Docs/RDoc/Ruby22' end end From c85e4398a79f464cfc0da7eb9fa61aa9ae038268 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 14 Jan 2018 13:23:29 -0500 Subject: [PATCH 099/244] Update Django documentation (2.0.1) --- lib/docs/scrapers/django.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/docs/scrapers/django.rb b/lib/docs/scrapers/django.rb index 5bb7469b..f32aa7d8 100644 --- a/lib/docs/scrapers/django.rb +++ b/lib/docs/scrapers/django.rb @@ -34,8 +34,14 @@ module Docs Licensed under the BSD License. HTML + version '2.0' do + self.release = '2.0.1' + self.dir = '/Users/Thibaut/DevDocs/Docs/Django20' + self.base_url = 'https://docs.djangoproject.com/en/2.0/' + end + version '1.11' do - self.release = '1.11.5' + self.release = '1.11.9' self.dir = '/Users/Thibaut/DevDocs/Docs/Django111' self.base_url = 'https://docs.djangoproject.com/en/1.11/' end From 914100a6573ae9f423ffd1627caac89cb4241664 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 14 Jan 2018 16:14:43 -0500 Subject: [PATCH 100/244] Improve error message on failed requests --- lib/docs/core/scrapers/url_scraper.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/docs/core/scrapers/url_scraper.rb b/lib/docs/core/scrapers/url_scraper.rb index 8633f1b7..043365e9 100644 --- a/lib/docs/core/scrapers/url_scraper.rb +++ b/lib/docs/core/scrapers/url_scraper.rb @@ -35,7 +35,11 @@ module Docs def process_response?(response) if response.error? - raise "Error status code (#{response.code}): #{response.return_message}\n#{response.url}" + raise <<~ERROR + Error status code (#{response.code}): #{response.return_message} + #{response.url} + #{JSON.pretty_generate(response.headers).slice(2..-3)} + ERROR elsif response.blank? raise "Empty response body: #{response.url}" end From ad9276e9013e2bd0fef7b485fe4bde9448113021 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 14 Jan 2018 16:18:34 -0500 Subject: [PATCH 101/244] Add rate limiter --- lib/docs/core/scrapers/url_scraper.rb | 41 +++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/lib/docs/core/scrapers/url_scraper.rb b/lib/docs/core/scrapers/url_scraper.rb index 043365e9..1daa1c05 100644 --- a/lib/docs/core/scrapers/url_scraper.rb +++ b/lib/docs/core/scrapers/url_scraper.rb @@ -13,6 +13,8 @@ module Docs end end + @@rate_limiter = nil + self.params = {} self.headers = { 'User-Agent' => 'DevDocs' } self.force_gzip = false @@ -24,6 +26,15 @@ module Docs end def request_all(urls, &block) + if options[:rate_limit] + if @@rate_limiter + @@rate_limiter.limit = options[:rate_limit] + else + @@rate_limiter = RateLimiter.new(options[:rate_limit]) + Typhoeus.before(&@@rate_limiter.to_proc) + end + end + Requester.run urls, request_options: request_options, &block end @@ -165,5 +176,35 @@ module Docs super.merge! redirections: self.class.redirections end end + + class RateLimiter + attr_accessor :limit + + def initialize(limit) + @limit = limit + @minute = nil + @counter = 0 + end + + def call(*) + if @minute != Time.now.min + @minute = Time.now.min + @counter = 0 + end + + @counter += 1 + + if @counter >= @limit + wait = Time.now.end_of_minute.to_i - Time.now.to_i + 1 + sleep wait + end + + true + end + + def to_proc + method(:call).to_proc + end + end end end From 6ba23292dc2d488dcf5ffc5a8084598c1bcaa96d Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 14 Jan 2018 21:41:59 -0500 Subject: [PATCH 102/244] Update MDN docs Fixes #719. --- lib/docs/filters/css/entries.rb | 15 +++++++++------ lib/docs/filters/dom/entries.rb | 6 ++++++ lib/docs/filters/javascript/entries.rb | 2 +- lib/docs/scrapers/http.rb | 1 + lib/docs/scrapers/mdn/dom_events.rb | 2 ++ lib/docs/scrapers/mdn/mdn.rb | 3 ++- 6 files changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/docs/filters/css/entries.rb b/lib/docs/filters/css/entries.rb index f83746b8..00816cea 100644 --- a/lib/docs/filters/css/entries.rb +++ b/lib/docs/filters/css/entries.rb @@ -7,8 +7,8 @@ module Docs 'CSS_Columns' => 'Multi-column Layout', 'CSS_Flexible_Box_Layout' => 'Flexible Box Layout', 'CSS_Grid_Layout' => 'Grid Layout', - 'CSS_Images' => 'Image Values', - 'CSS_Lists_and_Counters' => 'Lists & Counters', + 'CSS_Images' => 'Images', + 'CSS_Lists_and_Counters' => 'Lists', 'CSS_Transforms' => 'Transforms', 'Media_Queries' => 'Media Queries', 'transform-function' => 'Transforms', @@ -34,7 +34,7 @@ module Docs "#{super}()" elsif slug =~ /\A[a-z]+_/i slug.to_s.gsub('_', ' ').gsub('/', ': ') - elsif slug.start_with?('transform-function') + elsif slug.start_with?('transform-function') || slug.start_with?('filter-function') slug.split('/').last + '()' else super @@ -74,9 +74,10 @@ module Docs 'spec-Living' => 0, 'spec-REC' => 1, 'spec-CR' => 2, - 'spec-LC' => 3, - 'spec-WD' => 4, - 'spec-ED' => 5 + 'spec-PR' => 3, + 'spec-LC' => 4, + 'spec-WD' => 5, + 'spec-ED' => 6 } PRIORITY_STATUSES = %w(spec-REC spec-CR) @@ -89,6 +90,8 @@ module Docs specs.map! { |node| [node.at_css('> td:nth-child(1) > a'), node.at_css('> td:nth-child(2) > span')] } # ignore non-CSS specs specs.select! { |pair| pair.first && pair.first['href'] =~ /css|fxtf|fullscreen|svg/i && !pair.first['href'].include?('compat.spec') } + # ignore specs with no status + specs.select! { |pair| pair.second } # ["Spec", "spec-REC"] specs.map! { |pair| [pair.first.child.content, pair.second['class']] } # sort by status diff --git a/lib/docs/filters/dom/entries.rb b/lib/docs/filters/dom/entries.rb index ddfa3751..988897c6 100644 --- a/lib/docs/filters/dom/entries.rb +++ b/lib/docs/filters/dom/entries.rb @@ -10,6 +10,7 @@ module Docs 'Audio' => 'Audio', 'Battery Status' => 'Battery Status', 'Canvas ' => 'Canvas', + 'Clipboard' => 'Clipboard', 'Cooperative Scheduling' => 'Scheduling', 'CSS Font Loading' => 'CSS', 'CSS Object Model' => 'CSS', @@ -45,6 +46,7 @@ module Docs 'Stream API' => 'Media Streams', 'Streams' => 'Media Streams', 'Touch Events' => 'Touch Events', + 'Visual Viewport' => 'Visual Viewport', 'Web Animations' => 'Animation', 'Web App Manifest' => 'Web App Manifest', 'Budget' => 'Budget', @@ -54,6 +56,8 @@ module Docs 'WebVR' => 'WebVR' } TYPE_BY_NAME_STARTS_WITH = { + 'AbortController' => 'Fetch', + 'AbortSignal' => 'Fetch', 'Ambient' => 'Ambient Light', 'Attr' => 'Nodes', 'Audio' => 'Audio', @@ -61,6 +65,7 @@ module Docs 'Broadcast' => 'Broadcast Channel', 'Budget' => 'Budget', 'Canvas' => 'Canvas', + 'Clipboard' => 'Clipboard', 'CSS' => 'CSS', 'CharacterData' => 'Nodes', 'ChildNode' => 'Nodes', @@ -105,6 +110,7 @@ module Docs 'screen' => 'Screen', 'Selection' => 'Selection', 'Shadow' => 'Shadow DOM', + 'Streams' => 'Media Streams', 'StyleSheet' => 'CSS', 'Stylesheet' => 'CSS', 'SVG' => 'SVG', diff --git a/lib/docs/filters/javascript/entries.rb b/lib/docs/filters/javascript/entries.rb index 39b7a0b8..40654087 100644 --- a/lib/docs/filters/javascript/entries.rb +++ b/lib/docs/filters/javascript/entries.rb @@ -2,7 +2,7 @@ module Docs class Javascript class EntriesFilter < Docs::EntriesFilter TYPES = %w(Array ArrayBuffer Atomics Boolean DataView Date Function - Generator Intl JSON Map Math Number Object Promise Reflect RegExp + Generator Intl JSON Map Math Number Object PluralRules Promise Reflect RegExp Set SharedArrayBuffer SIMD String Symbol TypedArray WeakMap WeakSet) INTL_OBJECTS = %w(Collator DateTimeFormat NumberFormat) diff --git a/lib/docs/scrapers/http.rb b/lib/docs/scrapers/http.rb index 881c0545..60f15f75 100644 --- a/lib/docs/scrapers/http.rb +++ b/lib/docs/scrapers/http.rb @@ -11,6 +11,7 @@ module Docs options[:title] = ->(filter) { filter.current_url.host == 'tools.ietf.org' ? false : filter.default_title } options[:container] = ->(filter) { filter.current_url.host == 'tools.ietf.org' ? '.content' : nil } options[:skip_links] = ->(filter) { filter.current_url.host == 'tools.ietf.org' ? true : false } + options[:replace_paths] = { '/Access_control_CORS' => '/CORS' } options[:fix_urls] = ->(url) do url.sub! %r{(Status/\d\d\d)_[A-Z].+}, '\1' url diff --git a/lib/docs/scrapers/mdn/dom_events.rb b/lib/docs/scrapers/mdn/dom_events.rb index fa6cf33d..fcbdc08f 100644 --- a/lib/docs/scrapers/mdn/dom_events.rb +++ b/lib/docs/scrapers/mdn/dom_events.rb @@ -1,5 +1,7 @@ module Docs class DomEvents < Mdn + prepend FixInternalUrlsBehavior + self.name = 'DOM Events' self.slug = 'dom_events' self.base_url = 'https://developer.mozilla.org/en-US/docs/Web/Events' diff --git a/lib/docs/scrapers/mdn/mdn.rb b/lib/docs/scrapers/mdn/mdn.rb index 1c01ccd7..15a33291 100644 --- a/lib/docs/scrapers/mdn/mdn.rb +++ b/lib/docs/scrapers/mdn/mdn.rb @@ -9,6 +9,7 @@ module Docs html_filters.push 'mdn/clean_html' text_filters.insert_before 'attribution', 'mdn/contribute_link' + options[:rate_limit] = 400 options[:trailing_slash] = false options[:skip_link] = ->(link) { @@ -16,7 +17,7 @@ module Docs } options[:attribution] = <<-HTML - © 2005–2017 Mozilla Developer Network and individual contributors.
    + © 2005–2018 Mozilla Developer Network and individual contributors.
    Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later. HTML From e7e4d13681256f36aaa8d95825da73bc4f9f954e Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 28 Jan 2018 18:40:57 -0500 Subject: [PATCH 103/244] Update Bootstrap documentation (4.0.0) --- assets/javascripts/templates/pages/about_tmpl.coffee | 2 +- lib/docs/filters/bootstrap/clean_html_v4.rb | 2 ++ lib/docs/scrapers/bootstrap.rb | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index ce0d5c37..efa00877 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -117,7 +117,7 @@ credits = [ 'https://raw.githubusercontent.com/petkaantonov/bluebird/master/LICENSE' ], [ 'Bootstrap', - '2011-2017 Twitter, Inc.
    2011-2017 The Bootstrap Authors', + '2011-2018 Twitter, Inc.
    2011-2018 The Bootstrap Authors', 'CC BY', 'https://creativecommons.org/licenses/by/3.0/' ], [ diff --git a/lib/docs/filters/bootstrap/clean_html_v4.rb b/lib/docs/filters/bootstrap/clean_html_v4.rb index 0974556e..c7354f13 100644 --- a/lib/docs/filters/bootstrap/clean_html_v4.rb +++ b/lib/docs/filters/bootstrap/clean_html_v4.rb @@ -17,6 +17,8 @@ module Docs end css('.bd-example', '.responsive-utilities-test').each do |node| + next unless node.previous_element + if node.previous_element['class'].try(:include?, 'bd-example') node.remove else diff --git a/lib/docs/scrapers/bootstrap.rb b/lib/docs/scrapers/bootstrap.rb index 3653bb2d..859998a9 100644 --- a/lib/docs/scrapers/bootstrap.rb +++ b/lib/docs/scrapers/bootstrap.rb @@ -9,14 +9,14 @@ module Docs options[:trailing_slash] = true options[:attribution] = <<-HTML - © 2011–2017 Twitter, Inc.
    - © 2011–2017 The Bootstrap Authors
    + © 2011–2018 Twitter, Inc.
    + © 2011–2018 The Bootstrap Authors
    Code licensed under the MIT License.
    Documentation licensed under the Creative Commons Attribution License v3.0. HTML version '4' do - self.release = '4.0.0-beta.3' + self.release = '4.0.0' self.base_url = 'https://getbootstrap.com/docs/4.0/' self.root_path = 'getting-started/introduction/' From cc5105c07a2b8d0799052b795e8e22d00212c483 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 28 Jan 2018 18:43:50 -0500 Subject: [PATCH 104/244] Update Elixir documentation (1.6.0) --- .../templates/pages/about_tmpl.coffee | 2 +- lib/docs/scrapers/elixir.rb | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index efa00877..db97532f 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -232,7 +232,7 @@ credits = [ 'https://raw.githubusercontent.com/electron/electron/master/LICENSE' ], [ 'Elixir', - '2012-2017 Plataformatec', + '2012 Plataformatec', 'Apache', 'https://raw.githubusercontent.com/elixir-lang/elixir/master/LICENSE' ], [ diff --git a/lib/docs/scrapers/elixir.rb b/lib/docs/scrapers/elixir.rb index 023966b3..3aa8ff7a 100644 --- a/lib/docs/scrapers/elixir.rb +++ b/lib/docs/scrapers/elixir.rb @@ -19,7 +19,7 @@ module Docs options[:root_title] = 'Elixir' options[:attribution] = <<-HTML - © 2012–2017 Plataformatec
    + © 2012 Plataformatec
    Licensed under the Apache License, Version 2.0. HTML @@ -33,8 +33,21 @@ module Docs "https://elixir-lang.org/getting-started/introduction.html" ] end + version '1.6' do + self.release = '1.6.0' + self.base_urls = [ + "https://hexdocs.pm/elixir/#{release}/", + "https://hexdocs.pm/eex/#{release}/", + "https://hexdocs.pm/ex_unit/#{release}/", + "https://hexdocs.pm/iex/#{release}/", + "https://hexdocs.pm/logger/#{release}/", + "https://hexdocs.pm/mix/#{release}/", + 'https://elixir-lang.org/getting-started/' + ] + end + version '1.5' do - self.release = '1.5.2' + self.release = '1.5.3' self.base_urls = [ "https://hexdocs.pm/elixir/#{release}/", "https://hexdocs.pm/eex/#{release}/", From 54133da85e19b71d868cba05090b5b1cd54f6f00 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 28 Jan 2018 18:45:45 -0500 Subject: [PATCH 105/244] Update Sinon.JS documentation (4.2.2) --- assets/javascripts/templates/pages/about_tmpl.coffee | 2 +- lib/docs/scrapers/sinon.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index db97532f..0e2e4912 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -592,7 +592,7 @@ credits = [ 'https://raw.githubusercontent.com/scikit-learn/scikit-learn/master/COPYING' ], [ 'Sinon', - '2010-2017 Christian Johansen', + '2010-2018 Christian Johansen', 'BSD', 'https://raw.githubusercontent.com/sinonjs/sinon/master/LICENSE' ], [ diff --git a/lib/docs/scrapers/sinon.rb b/lib/docs/scrapers/sinon.rb index 9822a00f..c96bbef1 100644 --- a/lib/docs/scrapers/sinon.rb +++ b/lib/docs/scrapers/sinon.rb @@ -14,12 +14,12 @@ module Docs options[:container] = '.content .container' options[:attribution] = <<-HTML - © 2010–2017 Christian Johansen
    + © 2010–2018 Christian Johansen
    Licensed under the BSD License. HTML version '4' do - self.release = '4.1.2' + self.release = '4.2.2' self.base_url = "http://sinonjs.org/releases/v#{release}/" end From a0a730ce9f443631b175b669627d1ea06dc30377 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 28 Jan 2018 18:46:01 -0500 Subject: [PATCH 106/244] Update Angular documentation (5.2.2) --- lib/docs/scrapers/angular.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/angular.rb b/lib/docs/scrapers/angular.rb index a3daaf22..c9d53ec5 100644 --- a/lib/docs/scrapers/angular.rb +++ b/lib/docs/scrapers/angular.rb @@ -59,7 +59,7 @@ module Docs end version do - self.release = '5.1.3' + self.release = '5.2.2' self.base_url = 'https://angular.io/' self.root_path = 'docs' From 003e754f2fb7a9007064c559a790ac75337a3060 Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 28 Jan 2018 18:50:19 -0500 Subject: [PATCH 107/244] Update jQuery documentation (up to 3.3.1) --- lib/docs/scrapers/jquery/jquery_core.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/docs/scrapers/jquery/jquery_core.rb b/lib/docs/scrapers/jquery/jquery_core.rb index 4688df53..dd5ed601 100644 --- a/lib/docs/scrapers/jquery/jquery_core.rb +++ b/lib/docs/scrapers/jquery/jquery_core.rb @@ -1,7 +1,7 @@ module Docs class JqueryCore < Jquery self.name = 'jQuery' - self.release = 'up to 3.2.1' + self.release = 'up to 3.3.1' self.base_url = 'https://api.jquery.com/' self.initial_paths = %w(/index/index) From 6baa21ee0bb759956ffb8612602fef86645d1a03 Mon Sep 17 00:00:00 2001 From: metarmask Date: Fri, 29 Dec 2017 16:27:52 +0100 Subject: [PATCH 108/244] Update OpenSearch instructions for Firefox --- assets/javascripts/templates/pages/help_tmpl.coffee | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/assets/javascripts/templates/pages/help_tmpl.coffee b/assets/javascripts/templates/pages/help_tmpl.coffee index 3f09a9ce..f8cb19a5 100644 --- a/assets/javascripts/templates/pages/help_tmpl.coffee +++ b/assets/javascripts/templates/pages/help_tmpl.coffee @@ -57,9 +57,7 @@ app.templates.helpPage = ->

    • On Chrome, the setup is done automatically. Simply press tab when devdocs.io is autocompleted in the omnibox (to set a custom keyword, click Manage search engines\u2026 in Chrome's settings). -
    • On Firefox, open the search engine list (icon in the search bar) and click Add "DevDocs Search". - DevDocs is now available in the search bar. You can also search from the location bar by following - these instructions. +
    • On Firefox, right-click the DevDocs search field and select Add a Keyword for this Search…. Then, type the added keyword followed by a query in the address bar to search DevDocs.

      Note: the above search features only work for documentations that are enabled. From 884f21e1a986ff022d405ed0a4119f4232fff31c Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Tue, 30 Jan 2018 21:38:51 -0500 Subject: [PATCH 109/244] Encode utf8 character in print stylesheet Fixes #742. --- assets/stylesheets/global/_print.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/stylesheets/global/_print.scss b/assets/stylesheets/global/_print.scss index 30fa64c1..5044631e 100644 --- a/assets/stylesheets/global/_print.scss +++ b/assets/stylesheets/global/_print.scss @@ -29,7 +29,7 @@ } ._attribution:last-child:after { - content: 'Exported from DevDocs — https://devdocs.io'; + content: 'Exported from DevDocs \2014 https://devdocs.io'; display: block; margin-top: 1rem; font-weight: $bolderFontWeight; From abbd43b85e4a84b140b81f45a8c61389a0b7ae88 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Fri, 27 Oct 2017 18:38:55 -0400 Subject: [PATCH 110/244] Add JSDoc --- assets/stylesheets/application.css.scss | 1 + assets/stylesheets/pages/_jsdoc.scss | 25 ++++++++++++++ lib/docs/filters/jsdoc/clean_html.rb | 43 ++++++++++++++++++++++++ lib/docs/filters/jsdoc/entries.rb | 25 ++++++++++++++ lib/docs/scrapers/jsdoc.rb | 30 +++++++++++++++++ public/icons/docs/jsdoc/16.png | Bin 0 -> 246 bytes public/icons/docs/jsdoc/16@2x.png | Bin 0 -> 529 bytes public/icons/docs/jsdoc/SOURCE | 1 + 8 files changed, 125 insertions(+) create mode 100644 assets/stylesheets/pages/_jsdoc.scss create mode 100644 lib/docs/filters/jsdoc/clean_html.rb create mode 100644 lib/docs/filters/jsdoc/entries.rb create mode 100644 lib/docs/scrapers/jsdoc.rb create mode 100644 public/icons/docs/jsdoc/16.png create mode 100644 public/icons/docs/jsdoc/16@2x.png create mode 100644 public/icons/docs/jsdoc/SOURCE diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss index e4314a0f..fb0c08cd 100644 --- a/assets/stylesheets/application.css.scss +++ b/assets/stylesheets/application.css.scss @@ -56,6 +56,7 @@ 'pages/go', 'pages/haskell', 'pages/jquery', + 'pages/jsdoc', 'pages/julia', 'pages/knockout', 'pages/kotlin', diff --git a/assets/stylesheets/pages/_jsdoc.scss b/assets/stylesheets/pages/_jsdoc.scss new file mode 100644 index 00000000..05e83f1d --- /dev/null +++ b/assets/stylesheets/pages/_jsdoc.scss @@ -0,0 +1,25 @@ +._jsdoc { + > h2 { @extend %block-heading; } + + > h3 { + @extend %lined-heading; + font-size: 1.1em; + } + + figure { + margin-left: 0; + font-size: inherit; + + pre { + margin-bottom: 0.5em; + } + + figcaption { + font-style: italic; + } + } + + pre { + font-size: inherit; + } +} diff --git a/lib/docs/filters/jsdoc/clean_html.rb b/lib/docs/filters/jsdoc/clean_html.rb new file mode 100644 index 00000000..f61593e2 --- /dev/null +++ b/lib/docs/filters/jsdoc/clean_html.rb @@ -0,0 +1,43 @@ +module Docs + class Jsdoc + class CleanHtmlFilter < Filter + def call + css('h2').each do |node| + next unless node.content.strip == 'Table of Contents' + toc_ul = node.next_element + toc_block = node.add_next_sibling('

      ').first + + node.name = 'h3' + node['class'] = '_toc-title' + node.remove + toc_block.add_child(node) + + toc_ul.remove + toc_ul['class'] = '_toc-list' + toc_ul.css('ul').each do |child_list| + child_list.remove + end + toc_block.add_child(toc_ul) + end + + css('.prettyprint').each do |node| + match = /lang-(\w+)/.match(node['class']) + next unless match + + lang = match[1] + node.remove_attribute('class') + node['data-language'] = lang + end + + css('figure').each do |node| + caption = node.at_css 'figcaption' + next unless caption + + node.children.last.add_next_sibling(caption) + end + + doc + end + end + end +end diff --git a/lib/docs/filters/jsdoc/entries.rb b/lib/docs/filters/jsdoc/entries.rb new file mode 100644 index 00000000..62170151 --- /dev/null +++ b/lib/docs/filters/jsdoc/entries.rb @@ -0,0 +1,25 @@ +module Docs + class Jsdoc + class EntriesFilter < Docs::EntriesFilter + def get_name + at_css('h1').content + end + def get_type + case slug + when /^about-/ + 'Getting Started' + when /^plugins-/ + 'Plugins' + when /^howto-/ + 'Examples' + when /^tags-inline-/ + 'Inline Tags' + when /^tags-/ + 'Tags' + else + 'Other' # Only shown if a new category gets added in the upstream docs + end + end + end + end +end diff --git a/lib/docs/scrapers/jsdoc.rb b/lib/docs/scrapers/jsdoc.rb new file mode 100644 index 00000000..de43eb4e --- /dev/null +++ b/lib/docs/scrapers/jsdoc.rb @@ -0,0 +1,30 @@ +module Docs + class Jsdoc < UrlScraper + self.name = 'JSDoc' + self.type = 'jsdoc' + self.release = '3.5.5' + self.base_url = 'http://usejsdoc.org/' + self.links = { + home: 'http://usejsdoc.org/', + code: 'https://github.com/jsdoc3/jsdoc' + } + + html_filters.push 'jsdoc/clean_html', 'jsdoc/entries' + + options[:trailing_slash] = false + options[:container] = 'article' + options[:skip] = [ + 'about-license-jsdoc3.html' + ] + options[:attribution] = <<-HTML + © 2011–2017 + + JSDoc 3 contributors +
      + Licensed under + + CC BY-SA 3.0 + + HTML + end +end diff --git a/public/icons/docs/jsdoc/16.png b/public/icons/docs/jsdoc/16.png new file mode 100644 index 0000000000000000000000000000000000000000..6f1ad033fc675878a26f555b3d5ed3e2bb20c5df GIT binary patch literal 246 zcmVFFHBu!2_DY>{fO7sT4hR@Oq1T~0gErQ_a-d&UygIdmA zoVvK=S-!&={+#bS91gxpp*_^GMH_2;{snM^2TX8`3!LJ-$QF%%k-n<#Aj0{b=O*c^%Vip!t7AA$%7z?ta5k;(QSecTQ&6NBBn(op$Uk&@~y$c!49hn!_jY7{}3tZ@8JUX((kphkIz?CHCgq3_gdQ_gH8)1Et*VJVvAY zjx*R0hZZ7NTHyfP2m@_HH962hTd;PCybD|KrJ&o6!Bj^NhOjjive-NJU?Zkiab_8Z zup3iF2Tq_5+maWrqaVZ=uHy|hqZeOsHWl&#BeB09yILyhSL7b7OVypiCG?gG4m5BW z`!in-jr52KJdbV~*KirbVR15jhocF>E&N=DS~!rK z?!dFGzkp+SkaZ2b!@kwz$!Yw~d^Vf@NNDclmi2_B9_nYqz5|7!YAH=ZQ6|3@FFVm;;xx>_imYlQ>FG8{<8 z4iz3I Date: Sun, 4 Feb 2018 10:43:11 -0500 Subject: [PATCH 111/244] Finish JSDoc scraper --- assets/javascripts/news.json | 3 ++ .../templates/pages/about_tmpl.coffee | 5 +++ assets/stylesheets/application.css.scss | 1 - assets/stylesheets/components/_content.scss | 2 + assets/stylesheets/global/_icons.scss | 1 + assets/stylesheets/pages/_jsdoc.scss | 25 ------------- lib/docs/filters/jsdoc/clean_html.rb | 35 +++++------------- lib/docs/filters/jsdoc/entries.rb | 7 +++- lib/docs/scrapers/jsdoc.rb | 13 ++----- public/icons/docs/jsdoc/16.png | Bin 246 -> 0 bytes public/icons/docs/jsdoc/16@2x.png | Bin 529 -> 0 bytes public/icons/docs/jsdoc/SOURCE | 1 - 12 files changed, 29 insertions(+), 64 deletions(-) delete mode 100644 assets/stylesheets/pages/_jsdoc.scss delete mode 100644 public/icons/docs/jsdoc/16.png delete mode 100644 public/icons/docs/jsdoc/16@2x.png delete mode 100644 public/icons/docs/jsdoc/SOURCE diff --git a/assets/javascripts/news.json b/assets/javascripts/news.json index c93f8ed9..e998c941 100644 --- a/assets/javascripts/news.json +++ b/assets/javascripts/news.json @@ -1,5 +1,8 @@ [ [ + "2018-2-4", + "New documentation: JSDoc" + ], [ "2017-11-26", "New documentations: Bluebird, ESLint and Homebrew" ], [ diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index 0e2e4912..adabe626 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -345,6 +345,11 @@ credits = [ '2009-2016 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors', 'MIT', 'https://raw.githubusercontent.com/JuliaLang/julia/master/LICENSE.md' + ], [ + 'JSDoc', + '2011-2017 the contributors to the JSDoc 3 documentation project', + 'CC BY-SA', + 'https://raw.githubusercontent.com/jsdoc3/jsdoc3.github.com/master/LICENSE' ], [ 'Knockout.js', 'Steven Sanderson, the Knockout.js team, and other contributors', diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss index fb0c08cd..e4314a0f 100644 --- a/assets/stylesheets/application.css.scss +++ b/assets/stylesheets/application.css.scss @@ -56,7 +56,6 @@ 'pages/go', 'pages/haskell', 'pages/jquery', - 'pages/jsdoc', 'pages/julia', 'pages/knockout', 'pages/kotlin', diff --git a/assets/stylesheets/components/_content.scss b/assets/stylesheets/components/_content.scss index 9b8e299a..18f2e51d 100644 --- a/assets/stylesheets/components/_content.scss +++ b/assets/stylesheets/components/_content.scss @@ -382,6 +382,8 @@ ._table { width: 100%; } ._mobile ._table { overflow-x: auto; } +._pre-heading { @extend %pre-heading; } + ._pre-clip { display: none; position: absolute; diff --git a/assets/stylesheets/global/_icons.scss b/assets/stylesheets/global/_icons.scss index b4b433f1..08dcc4dd 100644 --- a/assets/stylesheets/global/_icons.scss +++ b/assets/stylesheets/global/_icons.scss @@ -92,6 +92,7 @@ ._icon-nginx_lua_module:before { background-position: -4rem -5rem; } ._icon-svg:before { background-position: -5rem -5rem; } ._icon-marionette:before { background-position: -6rem -5rem; } +._icon-jsdoc:before, ._icon-mongoose:before { background-position: -7rem -5rem; } ._icon-phpunit:before { background-position: -8rem -5rem; } ._icon-nokogiri:before { background-position: -9rem -5rem; @extend %darkIconFix !optional; } diff --git a/assets/stylesheets/pages/_jsdoc.scss b/assets/stylesheets/pages/_jsdoc.scss deleted file mode 100644 index 05e83f1d..00000000 --- a/assets/stylesheets/pages/_jsdoc.scss +++ /dev/null @@ -1,25 +0,0 @@ -._jsdoc { - > h2 { @extend %block-heading; } - - > h3 { - @extend %lined-heading; - font-size: 1.1em; - } - - figure { - margin-left: 0; - font-size: inherit; - - pre { - margin-bottom: 0.5em; - } - - figcaption { - font-style: italic; - } - } - - pre { - font-size: inherit; - } -} diff --git a/lib/docs/filters/jsdoc/clean_html.rb b/lib/docs/filters/jsdoc/clean_html.rb index f61593e2..ce44598b 100644 --- a/lib/docs/filters/jsdoc/clean_html.rb +++ b/lib/docs/filters/jsdoc/clean_html.rb @@ -2,38 +2,21 @@ module Docs class Jsdoc class CleanHtmlFilter < Filter def call - css('h2').each do |node| - next unless node.content.strip == 'Table of Contents' - toc_ul = node.next_element - toc_block = node.add_next_sibling('').first - - node.name = 'h3' - node['class'] = '_toc-title' - node.remove - toc_block.add_child(node) - - toc_ul.remove - toc_ul['class'] = '_toc-list' - toc_ul.css('ul').each do |child_list| - child_list.remove - end - toc_block.add_child(toc_ul) - end + at_css('h1').content = 'JSDoc' if root_page? css('.prettyprint').each do |node| - match = /lang-(\w+)/.match(node['class']) - next unless match - - lang = match[1] + node.content = node.content + node['data-language'] = node['class'][/lang-(\w+)/, 1] node.remove_attribute('class') - node['data-language'] = lang end - css('figure').each do |node| - caption = node.at_css 'figcaption' - next unless caption + css('figcaption').each do |node| + node.name = 'div' + node['class'] = '_pre-heading' + end - node.children.last.add_next_sibling(caption) + css('figure').each do |node| + node.before(node.children).remove end doc diff --git a/lib/docs/filters/jsdoc/entries.rb b/lib/docs/filters/jsdoc/entries.rb index 62170151..ea6fa84c 100644 --- a/lib/docs/filters/jsdoc/entries.rb +++ b/lib/docs/filters/jsdoc/entries.rb @@ -2,8 +2,11 @@ module Docs class Jsdoc class EntriesFilter < Docs::EntriesFilter def get_name - at_css('h1').content + name = at_css('h1').content + name.prepend 'JSDoc: ' if !name.include?('@') && !name.include?('JSDoc') + name end + def get_type case slug when /^about-/ @@ -17,7 +20,7 @@ module Docs when /^tags-/ 'Tags' else - 'Other' # Only shown if a new category gets added in the upstream docs + 'Miscellaneous' # Only shown if a new category gets added in the upstream docs end end end diff --git a/lib/docs/scrapers/jsdoc.rb b/lib/docs/scrapers/jsdoc.rb index de43eb4e..bb3781ca 100644 --- a/lib/docs/scrapers/jsdoc.rb +++ b/lib/docs/scrapers/jsdoc.rb @@ -1,9 +1,10 @@ module Docs class Jsdoc < UrlScraper self.name = 'JSDoc' - self.type = 'jsdoc' + self.type = 'simple' self.release = '3.5.5' self.base_url = 'http://usejsdoc.org/' + self.root_path = 'index.html' self.links = { home: 'http://usejsdoc.org/', code: 'https://github.com/jsdoc3/jsdoc' @@ -17,14 +18,8 @@ module Docs 'about-license-jsdoc3.html' ] options[:attribution] = <<-HTML - © 2011–2017 - - JSDoc 3 contributors -
      - Licensed under - - CC BY-SA 3.0 - + © 2011–2017 the contributors to the JSDoc 3 documentation project
      + Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0. HTML end end diff --git a/public/icons/docs/jsdoc/16.png b/public/icons/docs/jsdoc/16.png deleted file mode 100644 index 6f1ad033fc675878a26f555b3d5ed3e2bb20c5df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmVFFHBu!2_DY>{fO7sT4hR@Oq1T~0gErQ_a-d&UygIdmA zoVvK=S-!&={+#bS91gxpp*_^GMH_2;{snM^2TX8`3!LJ-$QF%%k-n<#Aj0{b=O*c^%Vip!t7AA$%7z?ta5k;(QSecTQ&6NBBn(op$Uk&@~y$c!49hn!_jY7{}3tZ@8JUX((kphkIz?CHCgq3_gdQ_gH8)1Et*VJVvAY zjx*R0hZZ7NTHyfP2m@_HH962hTd;PCybD|KrJ&o6!Bj^NhOjjive-NJU?Zkiab_8Z zup3iF2Tq_5+maWrqaVZ=uHy|hqZeOsHWl&#BeB09yILyhSL7b7OVypiCG?gG4m5BW z`!in-jr52KJdbV~*KirbVR15jhocF>E&N=DS~!rK z?!dFGzkp+SkaZ2b!@kwz$!Yw~d^Vf@NNDclmi2_B9_nYqz5|7!YAH=ZQ6|3@FFVm;;xx>_imYlQ>FG8{<8 z4iz3I Date: Sat, 28 Oct 2017 11:27:42 -0400 Subject: [PATCH 112/244] Add the Jekyll docs --- assets/stylesheets/application.css.scss | 1 + assets/stylesheets/pages/_jekyll.scss | 35 +++++++++++++++ lib/docs/filters/jekyll/clean_html.rb | 55 ++++++++++++++++++++++++ lib/docs/filters/jekyll/entries.rb | 29 +++++++++++++ lib/docs/scrapers/jekyll.rb | 34 +++++++++++++++ public/icons/docs/jekyll/16.png | Bin 0 -> 357 bytes public/icons/docs/jekyll/16@2x.png | Bin 0 -> 809 bytes public/icons/docs/jekyll/SOURCE | 1 + 8 files changed, 155 insertions(+) create mode 100644 assets/stylesheets/pages/_jekyll.scss create mode 100644 lib/docs/filters/jekyll/clean_html.rb create mode 100644 lib/docs/filters/jekyll/entries.rb create mode 100644 lib/docs/scrapers/jekyll.rb create mode 100644 public/icons/docs/jekyll/16.png create mode 100644 public/icons/docs/jekyll/16@2x.png create mode 100644 public/icons/docs/jekyll/SOURCE diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss index e4314a0f..26e0b885 100644 --- a/assets/stylesheets/application.css.scss +++ b/assets/stylesheets/application.css.scss @@ -55,6 +55,7 @@ 'pages/github', 'pages/go', 'pages/haskell', + 'pages/jekyll', 'pages/jquery', 'pages/julia', 'pages/knockout', diff --git a/assets/stylesheets/pages/_jekyll.scss b/assets/stylesheets/pages/_jekyll.scss new file mode 100644 index 00000000..2a30051f --- /dev/null +++ b/assets/stylesheets/pages/_jekyll.scss @@ -0,0 +1,35 @@ +._jekyll { + h2, h3 { @extend %block-heading; } + + .note { + @extend %note; + + h5 { + margin-top: 0.25em; + } + + position: relative; + &::after { + content: attr(data-type); + opacity: 0.5; + text-transform: uppercase; + position: absolute; + top: 0.25em; + right: 0.5em; + font-size: 0.8em; + pointer-events: none; + } + + // Other note types currently unstyled: + // plain + // tip + // feature + &.note-info { @extend %note-blue; } + &.note-warning { @extend %note-red; } + &.note-unreleased { @extend %note-orange; } + } + + pre { + font-size: inherit; + } +} diff --git a/lib/docs/filters/jekyll/clean_html.rb b/lib/docs/filters/jekyll/clean_html.rb new file mode 100644 index 00000000..d27d0ea4 --- /dev/null +++ b/lib/docs/filters/jekyll/clean_html.rb @@ -0,0 +1,55 @@ +module Docs + class Jekyll + class CleanHtmlFilter < Filter + def call + css('.improve, .section-nav').each(&:remove) + + css('div.highlighter-rouge').each do |node| + pre = node.at_css('pre') + + # copy over the highlighting metadata + match = /language-(\w+)/.match(node['class']) + # HACK: Prism shell highlighting highlights `|`, + # which makes the tree on this page look terrible + if match && !(slug == /structure/ && match[1] == 'sh') + lang = match[1] + if lang == 'sh' + lang = 'bash' + elsif lang == 'liquid' + lang = 'django' # Close enough. + end + pre['class'] = nil + pre['data-language'] = lang + end + + # Remove the server-rendered syntax highlighting + code = pre.at_css('code') + code.content = code.text + + # Remove the div.highlighter-rouge and div.highlight wrapping the
      +          node.add_next_sibling pre
      +          node.remove
      +        end
      +
      +        css('code').each do |node|
      +          node['class'] = ''
      +        end
      +
      +        css('.note').each do |node|
      +          node_type = /note ?(\w+)?/.match(node['class'])[1] || 'tip'
      +
      +          # 
      ...
      ...
      ->
      ...
      + (node > 'br').each(&:remove) + #
      ...

      ...

      ...

      ...
      -> + #
      ...

      ...
      ...

      ...
      + node.css('br + br').each(&:remove) + + node['class'] = "note note-#{node_type}" + node['data-type'] = node_type + end + + doc + end + end + end +end diff --git a/lib/docs/filters/jekyll/entries.rb b/lib/docs/filters/jekyll/entries.rb new file mode 100644 index 00000000..cf6b34b2 --- /dev/null +++ b/lib/docs/filters/jekyll/entries.rb @@ -0,0 +1,29 @@ +module Docs + class Jekyll + class EntriesFilter < Docs::EntriesFilter + + def get_name + at_css('h1').content + end + + def get_type + if /continuous-integration/.match(slug) + 'Deployment' + else + nav_link = doc.document # document + .at_css('aside li.current') # item in navbar + + if nav_link + nav_link + .parent #
        in navbar + .previous_element # header before
          + .content # category + else + 'Miscellaneous' + end + end + end + + end + end +end diff --git a/lib/docs/scrapers/jekyll.rb b/lib/docs/scrapers/jekyll.rb new file mode 100644 index 00000000..988e77bd --- /dev/null +++ b/lib/docs/scrapers/jekyll.rb @@ -0,0 +1,34 @@ +module Docs + class Jekyll < UrlScraper + self.type = 'jekyll' + self.release = '3.6.2' + self.base_url = 'https://jekyllrb.com/docs/' + self.root_path = 'home/' + self.links = { + home: 'https://jekyllrb.com/', + code: 'https://github.com/jekyll/jekyll' + } + + html_filters.push 'jekyll/clean_html', 'jekyll/entries' + + options[:trailing_slash] = true + options[:container] = 'article' + options[:skip] = [ + '', + '/' + ] + options[:skip_patterns] = [ + /conduct/, + /history/, + /maintaining/, + /contributing/ + ] + options[:attribution] = <<-HTML + © 2008–2017 Tom Preston-Werner and Jekyll contributors
          + Licensed under + + the MIT license + + HTML + end +end diff --git a/public/icons/docs/jekyll/16.png b/public/icons/docs/jekyll/16.png new file mode 100644 index 0000000000000000000000000000000000000000..aeb20c40aac35c0f9231dad3af159ffc04d1b60e GIT binary patch literal 357 zcmV-r0h<1aP)ZkG*L6}UgGQsla5#_yluBh(RmCt;+|=uGM|9F@cC%UZC}Qv! z(Cv2Qj(F<(eAa51FK^smUZ5z-@(NT{mbBf z4v^n=pxehvyWEb#h4SYDOw(lVL!b=>vvP@Mt0`yYBhMplK4C@hpsx|fe@Erl7e+#0 z?R%`BZE^kFN(_@SFO81lFrChrOhh7Jt`EX6TsqD_rl41{!e>3x00000NkvXXu0mjf DRkEVU literal 0 HcmV?d00001 diff --git a/public/icons/docs/jekyll/16@2x.png b/public/icons/docs/jekyll/16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1bf8b58f03aa7fd0d1550d9033551d377b18b62b GIT binary patch literal 809 zcmV+^1J?YBP)v?gVv$wmrI7KvbFleiPc*_{~=K}E2bS)Jt42j1Ju`+VN-`+a$yN9pM~ z5U`1%vdOXO0OC^*NNw9jUtd4FDUd^E{-K2q}?LGFvWl<;t%piV`hAE?+>?G<@GjN`aIDU6+iGj;<^D zCjn@h;NZb5zVD-H8bYkyzR~cwefw7QzaW#zkVqun%Kv8F`QvvS$B7;wU+6_uRe~Tu zig)rCi(~7Szv*9)Os44U?0VmP%PTC@YLrS-sA|Lj*<21OC9dmY7&>Bh7V&VB;ubSh z@}>du`Cb}}&vAaciI^!9dpv{o%VlnyKNo#1*u8rXN#`Yt7cXGUJx3@i=8muU%d1nZ zRztmiQzp#k3#{I{j<8>0C<-QE9zVudu^2jeXn>ZM7P{I}xKI8iSX?3A-io0K?168& zckj>W`+@EQJ@C&I{=zakAeL>+LXPpjC-HqhdVpMaH}&ZfI|j4FVkUac!Te!_v9Zyn zeCar<)?_HRSXo&qeB$O$D6+W zx)sng!8f~h;!e+^RP8nAqu>t>hAKQwE0D=#&?`@`Z)tH~$PhU`>9*q=7N`K2vuO9teJ0U zkmB9Dp$pFk{bgC!>5pxCQC(u-#7T6w&epzO7LE>b>F3L#`v3n5WxcauI^D{?{rg$9 nZ5}+h|5=iU0{DM8jVfLPD`NW9t^n>C00000NkvXXu0mjfVpxkO literal 0 HcmV?d00001 diff --git a/public/icons/docs/jekyll/SOURCE b/public/icons/docs/jekyll/SOURCE new file mode 100644 index 00000000..18496fca --- /dev/null +++ b/public/icons/docs/jekyll/SOURCE @@ -0,0 +1 @@ +https://avatars3.githubusercontent.com/u/3083652 From c349caf0f7b20190fedb1a93ec567f70a98ca90f Mon Sep 17 00:00:00 2001 From: Thibaut Courouble Date: Sun, 4 Feb 2018 11:20:23 -0500 Subject: [PATCH 113/244] Finish Jekyll scraper --- assets/images/docs-2.png | Bin 15956 -> 16287 bytes assets/images/docs-2@2x.png | Bin 38686 -> 39598 bytes assets/javascripts/news.json | 2 +- .../templates/pages/about_tmpl.coffee | 5 +++ assets/stylesheets/application-dark.css.scss | 1 + assets/stylesheets/global/_icons.scss | 1 + assets/stylesheets/pages/_jekyll.scss | 36 ++--------------- lib/docs/filters/jekyll/clean_html.rb | 38 ++++++------------ lib/docs/filters/jekyll/entries.rb | 3 +- lib/docs/scrapers/jekyll.rb | 22 +++++----- public/icons/docs/jekyll/16.png | Bin 357 -> 403 bytes public/icons/docs/jekyll/16@2x.png | Bin 809 -> 958 bytes public/icons/docs/jekyll/SOURCE | 2 +- 13 files changed, 37 insertions(+), 73 deletions(-) diff --git a/assets/images/docs-2.png b/assets/images/docs-2.png index cee86d69e5be1ed6b6864df58803e1306d805595..91de3f6babc807504e58e05cfc2247b414450ebc 100644 GIT binary patch delta 6532 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 MZ&hR~q>Tdp3o7B_!2kdN delta 6378 zcmbVORZ!gBmqY^u8z49t26y{#NPwWh-5nAnxI=*X;V!`)f)m``fp3__o1u1?&&_~)~#$n%C1EELW7jNT|)wc}4WQ#M7lw~y)H1_r*- z*YRLWb)!#A$NQ=ipsL4dFgA@ya(YPhp||+yH&-DFrn5u{r)<}TNht-eEClHkA z;7^|lO{55W%*$vN@A+P4IvJ^>AH88aD9^R&v->={Muu9-v+gDYUQG`>u|D3i9Vm}G zBk}Te(Dq&RCovMK?!HqyX+Lj@VUuq$Bs$gO1z<2*4E)+V$aa#}7kcgtKKm7M*)*Bz zPVJ=2ZXr{peOv=e_l$vxv8vw)-s8hx`@LgSC&x7w(%YkB5;MjBL7iV~6*ocG&?hR! zC3HAbZ0rX$N=K7XZ9NF*cv$FPr*u7R_Y3t+1g}P#<4H~Y=BC);+g^3I4cEcd=zI*{ z2fSI0jBQo%AvQTp?G4{*G&OrLO*u!59hLXt0+B1miTxTz2~yQ>a~ z#9qHUN}?Z4XTvmEssH9$S%BVCjJ}q{j5vyclczvbhxNhH*LRCkYb*(m>1`{)^^1I^ zFA_Ut?JI-17s|7H_YZ*u>y~w*_lZ2LnSdu+Pt%VHe|Ps|xg`PxVS$3|<&L(MyGIVa z+MDC1W8z^tR%XG3AHky_F*tl@L}nW9gn?yjc@eABolrKMweZcPcLHe5yTa}=MJ`@FWkeG-_rr-zQrM}=RiK@+?ml6R+XVujtjQX^ zfZOKw5!$;Zh@(8@**I8U|4KUnP$TLJ*5wKBXbV5YQGZ6&-TD-NoOO0grT4{|0-Wyy z6A1t3pLK*_`!{kq1G{nB3e26B&9T4JeLF9bo_)(gzuQFh8W2^d=#1)}U*YPYXUy>5 z`hQ8aL(jklHa~8jHPfHsXOWleF6Je6cB^wQ<&UhR9~l3_SbRzWiq9?v0Hby0eX#Cz zdlKw`UMm@+rY4bGC<(4ep==o$%Vgu1l(v}HU}MFh>_1PAZ?KPu^B@LCm|^wt7ILHI zWss4Znu0)o3#YIfCZb;M{r;H9?}fiDBQ@!NwqG9$!;>zCA2MLBC2Lh!Wkh3-o%~XS zp^i*VG??yEj%}c+Gno+sk(+Lv(C_wQ3gKBfpHi}nr#;&`*KvJ+x5z|pF-$z`w;_!5 z!&<#T-HT^r0G^m)R5-$kG^v7JAhtd1d|OX|05qP5upoI<3j$wUu?@^(_y6Rrpfkgs z*qhgrAR6DHhr)7M^p>TY-74vAvy-b_=x6g5c(3``N+03Yv*`fO`TF}z$A8w!Z1>s4 z&J^1C4SLNbn7sqdD^1qEza2%qOE{8Mid0H~(pBzo9Qk|%D6+=VU!RL99xT&Dp~^+FSP@<|}?^TCaVxB}L37LP2B3yf$ONrw=L7@8n9@9&>DcIZd;jF`Am z#bNDB5b`_tG%Ygx6My(oSd!N z6FR=@;Nm{&Khp5NMjP7zdEiKbf=6vjI~t*-CPtX9&>x~B@eBf8b9gwTRVaGPoOLiA z1S-8Q^tJx3TJ#t*Q{e&ke4O>RVJ$yP8tO_7udVDx(g|s#k_%7nv6_WupYlc1l^j(P zpTXyNpGQEQ;Jhs$?wZxAZs+plW6C#69d%)f(CNVF>=uku)zaXA0A6KB;z2vU-_mjQ z(bS$ZFq_sFP9LhOQSCBB)8wViE{m_rt)R2650|M0Bka+P-kXOdm_Z24y6Y8;rr%&8 zvLlYur~|VT=A(zfZ-rtb*Sa#%Hl_DRl4o%_ifn+}NU&8i65l@u;0$*@s{2=L@*GK0 zHbPai$J@N!1%cc3v=y(i!R@WgPJv&qvU03#L42O>nlPWfw5@sJNNc+jYdMz54gDdC zAEcYpc`tpRZ*>WkJd~oK5gm;!lU2Ry=(&en7)1=T7lck>cX8`vavue_oYl|ouq@ES zS(*X1${N?4zA}x(-aM2zVV810RF#vXF9{@s#UnbeFsY)3K>5kBRapg*3oqvn+kS5n z26a5Jehzq+D0Z%8vfN^*cj)niGtS?%-RrQr5cUe599vQ;SiXyPcb#6mm&x(A9P&B% z=L6z=-R$6@pMJS-uW>xo92Da$PWuk;TgDN9S2>W%vT51V3qaHQ?ZA;sqy(`lFsD&$yT_0 za%NvNIGbJ}i!r3|x9a|OJ3S1>sCx4SLAvl3A2x#~ti za_bYR)K7A3(`wb5$e@r*1X@X{{kp**6$=xDEGB_cEQw|W4p2|Xs_n=GC;B?@n=YuW z7UAh8CuhsOX@gBRu|Ip+s1jrJ(Ff~|TqESxV|-7wdgKBkvMb7wGz-#iigxaAG;h#|Yxh)*1w6^D62n zsaF^T`3|F;L@Hi}=j@paH8+|k=(pCXgTf%5z#0-h8JSR4_vMAgt&8Mltz%Na`Hg{Ovm&!-(4enw4|{;oXV7tmr2+7TaZ(jc?Zzqp zxC+kY`q(~DQu-;>2EkMM)P5g7Nsse`7dzc{PVS`{8)0UPxQhp2FL|QGx*@BMGm<2R z=?tp{Naoc$2@+NQ=EpPL^r7rLZcGS1_=f1sU?pA~lZiFXc1|ZN<~H~Q6#n7emRI0M zcCLd3zCkbWHk*$R$s%CGXK{Xi2Q}*JMppau#*0>qq{l=ZajQ1@X%ZPkNh&*^A9%T+ zS@>4pKyuc8Sxg7hw9OnV`RMBWJYw=r%c(X>ZidO#Pu{9F6pF&3Ow?(sl-a$eX%X#* z9m>>oJ9HRvVASz`X679%gK*zaRA1I`4s%N~Oz!UWxt;nMN-WTkZWa$}`8CF8F4Tv2 zjSa&g6_0gk%b<*Zott|ZRKpN%DOmGQ^lFE}qy9cY>*7gO2Lov@Rw)b_3zKu{e)9T9 zSIyVQjNl`kL}2=PhSqO{CzXO|=vZ|n_nGtC550DNS$Ez$MaDcQLb^Scr|2%Vdf@AH-X3ua3LG0ENwWL z$CmEk@dH<2^Y_i(h1V576DR!DQ>?o4SeN)OvGN(ydzS!i^!#l{{^vG%9%e4wfUrr@ zc}y%LUxa0vknuP#57Ovo6mGwM8}N9c_bzJt4?2!)XZ$V1+s5#uj!9fB?oo^fCqwf{ zw1qovr=8IZ65pKh$Cg`z8-rS3azX~X>Nii30IvCF)1H*9=#$yQ*OB6)) z2Jk(&au#54n<2AfiSt@KjS@OU^qx!yGU^ES3yJ`fen<-J9jojmI#`xrP$};ABCfcX zX-t7ya<+o$n0ceRIiwqPPF6}#6`$wgQBtP$ z``MHNzi9m+<18DxveOJKM_p;PpaJiyD>AJ?D2R+$@kg&(vD7hlyEc<; zDdl_wCsEGg!9Pxt;(a%y(`X}R^J0$CO5SNwju})frXaqD5bQNuN0kl4^f(Pa-giO$ zIsjUEGG53vF>ITiLN1?G8aEa{;FITzRi4BV6LFq_E%~cWWkx&IgXaaOuq7nlF6q3R z)JgVPl67u5OC5pUxguFyyjRlZYL}l+DArleKAk+>@O$_xK!2XHXL4<-tRylSq%Lh+ z=v~{lzI`pcr`GEFtFV1aD&^p)K>qYLn;p1729{T1W%l5~D2H%BM7jw$A~9U)!)Qe| zopMF%N<~b7T`N;mEed~5j6qc@Cgo8X{K)M=Qt2Xkrr3}`py=i(uyHv&NuEs={yxC= zbdUV9j85nPW5Db&txe*=hTIN@lyWqow7EXRx2e17E`;@N+grBblq!!j%t77*8IT%J zMY9t6KEHM~Gd+(8t13FbL-$tvg$hUuu!D9Gx1Oy=s~jpj$xqc z9;>%~x*x(g9H&UZ)8=UGV_iy0uW4C(=O7(d3&qaPi}O3MxA)M^$!kG1I7;1I?~lvt zVl1Oo`HK_TZ_DkBgs&lBaDlrALqkT!8!R{FSq~=vstyaw-CZH)eks@&z#)wLyLrJ2 zBou6#BPxT2IX9wu!Q~Y>ht*~JDJ3SC7OhY#`e7;96>3`(>C24ha*B(Gg9TWx%0a+S z(%>oj)8{D3@DD{_L$%Yk)NI~T3B6@*8i~5cp>tK85XRyfBtya;lsZ$dj&uAw~S=A(YpcDOxcw^K``awd6N8-%fGA-yL~6!Xd{UI`=&|DJ z<*h{p?YZBV7a?jyb-ENmZ zML^k9NU#xkXt}Wtec$H|shfh|RTo!jOAger*L)(sF41t%)?5Is$hq)DF1>=E6xFVw z)?u61TsmnM0(0)#-^eAz=-vf}qH->=++<*=A-_N-sMfvfNIklGYrBR=y(I;3gtiT* z?)13l{U+&DpT8ZG8Gk9-1L>0*gGd{h>hVzSnoiNmLO8kK1Z?^?V-2X|Ps?&NqBP3r z&7lN{l8yJKbnHCLmlnl;RVpejC`t&-Cpd4(g&ybB0vISr-)Y8Wj0YLw=~+Toymk%6 zvoyWE@8vlQOpYz=_|xc)`zF9x|`JA-yP7>|hh zBxV{KgqNLYGtEBJYwu(JRUNXSH~>=!*$VjbF~47JaUrg?vU}&_8`}^)_AM^QS6U(j zCm*oP_M*?KdhDVFp`*m2bF{U2|2(fvaNQeHosWpk`AUNt?5ZQkZ@?j-B}qhNSNR^v zU+j$W%qM}qg+b@xWn=`Evj?xD7T>uIu6Jso7zFgN!*hF+p!`kybmh_rmd)dJpdqAX zpr&|+L&^5_D6`{LVMNi}0}WX8^VSy+BLfQTfw}Bag}a9fnDxlC%I7Wz(RdUj|L!QST(66reqr|`i1|u&^;gx* z%eiV(sEwbKZ|t>hH8U5Xa^35BO`4 zSLij2B>dG|s%~gtEBajRy02D>&B9Vf6aS~7R4OH%#l;pEhME3w0*0Z)n;XxLloaA~ z{?X3}rGFAIpK{yi3xCCFg>dU;BlGn1#AC7aDxJJ32w%G@f5wLIi&hyOGK*Gu0j|hd zadsw`*2=T+A`KV1<{z)l&ww!)jNuMuoj1l7HqP;t+?rD5{2@7!;EHU!)F|I$wXw)$ zcU)cd+{wAdLC$2h((vxlC2K92tPL7 z=S-xyX4pb&#`t*puN`=Ry$eZl{W$;lczm_88I+fpnCp0V@_%@MiL^qe+ab|Ji^im# zm4xdjs{NT2%?%k=Xz6!FMl06YC&7-ME@Ott<-7|0Ch;@sxy<{kLys&HksRtjqw7z~ zmC?PgSRns7a&HT1@)Uj}h0s)=f8F+!AjYrEpLbjl4i%9{&%hJeM0R&~zkh{jK=qf_ z(oL?&0LmAw0RmhXTZfQJ7T0yyP&yN>r2J!|t&B$xkLdJ3hC)3y0lN^-oHcS~(Z@?Y zGrcDJtpBF}EZ40&u0E`$_C9I38nJBWA;XS-Elh-TllpgccEoZ-e4*6R z#TXFZB1+YLgUJd9?3%KfOBoCN>iT+~^4s}xqd$Lbb8{*`j=xJ}f`IP!hp$d@pTwH8p4caiC7=> zbH+Z667Ri&LIIt8vWk=xD%T6#>cYR5vFPT;!^7*Vu5Q?L>t2@(9iW;}Z9*uzq;|YI z&}3#~D^$$jBgKc9)BVXG!bzaVYSiAWhA`U@bhf;FA4u0FZ!%q?3hIcRYyJ187Or#6 zPBe(Va7Q9hC1`n*${Vr6Pie-wB(qLbmpH_eDFX!E5R@lr^S`gv=ofo0FE5Q~%E)jf zhPX~ou6;}k&4u%ANy}@{aETZ~nKBQFYsnIqD2PyVm*P;eCWzH0WTjDhCz`=UPB)tTL&CU*c4WYQ86J3{~de zn9=_j_3!a)j*EkW@TdG9jLF|={)Yno1NIj({l5zRKXu;zFTDQ&TjS!O|LrX30a*T$ gV4BWPf`HJimL|;h{>#|n`Cmjt<8 diff --git a/assets/javascripts/news.json b/assets/javascripts/news.json index e998c941..ef724717 100644 --- a/assets/javascripts/news.json +++ b/assets/javascripts/news.json @@ -1,7 +1,7 @@ [ [ "2018-2-4", - "New documentation: JSDoc" + "New documentations: Jekyll and JSDoc" ], [ "2017-11-26", "New documentations: Bluebird, ESLint and Homebrew" diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee index adabe626..04da2985 100644 --- a/assets/javascripts/templates/pages/about_tmpl.coffee +++ b/assets/javascripts/templates/pages/about_tmpl.coffee @@ -320,6 +320,11 @@ credits = [ '2008-2017 Pivotal Labs', 'MIT', 'https://raw.githubusercontent.com/jasmine/jasmine/master/MIT.LICENSE' + ], [ + 'Jekyll', + '2008-2018 Tom Preston-Werner and Jekyll contributors', + 'MIT', + 'https://raw.githubusercontent.com/jekyll/jekyll/master/LICENSE' ], [ 'Jest', '2014-present Facebook Inc.', diff --git a/assets/stylesheets/application-dark.css.scss b/assets/stylesheets/application-dark.css.scss index 96d5e445..c8dc1f8f 100644 --- a/assets/stylesheets/application-dark.css.scss +++ b/assets/stylesheets/application-dark.css.scss @@ -55,6 +55,7 @@ 'pages/github', 'pages/go', 'pages/haskell', + 'pages/jekyll', 'pages/jquery', 'pages/julia', 'pages/knockout', diff --git a/assets/stylesheets/global/_icons.scss b/assets/stylesheets/global/_icons.scss index 08dcc4dd..427f0eea 100644 --- a/assets/stylesheets/global/_icons.scss +++ b/assets/stylesheets/global/_icons.scss @@ -168,3 +168,4 @@ ._icon-bluebird:before { background-position: -8rem -2rem; @extend %doc-icon-2; } ._icon-eslint:before { background-position: -9rem -2rem; @extend %doc-icon-2; } ._icon-homebrew:before { background-position: 0 -3rem; @extend %doc-icon-2; } +._icon-jekyll:before { background-position: -1rem -3rem; @extend %doc-icon-2; } diff --git a/assets/stylesheets/pages/_jekyll.scss b/assets/stylesheets/pages/_jekyll.scss index 2a30051f..00a86795 100644 --- a/assets/stylesheets/pages/_jekyll.scss +++ b/assets/stylesheets/pages/_jekyll.scss @@ -1,35 +1,7 @@ ._jekyll { - h2, h3 { @extend %block-heading; } + @extend %simple; - .note { - @extend %note; - - h5 { - margin-top: 0.25em; - } - - position: relative; - &::after { - content: attr(data-type); - opacity: 0.5; - text-transform: uppercase; - position: absolute; - top: 0.25em; - right: 0.5em; - font-size: 0.8em; - pointer-events: none; - } - - // Other note types currently unstyled: - // plain - // tip - // feature - &.note-info { @extend %note-blue; } - &.note-warning { @extend %note-red; } - &.note-unreleased { @extend %note-orange; } - } - - pre { - font-size: inherit; - } + .note.info { @extend %note-blue; } + .note.warning { @extend %note-red; } + .note.unreleased { @extend %note-orange; } } diff --git a/lib/docs/filters/jekyll/clean_html.rb b/lib/docs/filters/jekyll/clean_html.rb index d27d0ea4..67e29793 100644 --- a/lib/docs/filters/jekyll/clean_html.rb +++ b/lib/docs/filters/jekyll/clean_html.rb @@ -2,50 +2,38 @@ module Docs class Jekyll class CleanHtmlFilter < Filter def call - css('.improve, .section-nav').each(&:remove) + @doc = at_css('article') + + at_css('h1').content = 'Jekyll' if root_page? + + css('.improve, .section-nav').remove css('div.highlighter-rouge').each do |node| pre = node.at_css('pre') - # copy over the highlighting metadata - match = /language-(\w+)/.match(node['class']) + lang = node['class'][/language-(\w+)/, 1] # HACK: Prism shell highlighting highlights `|`, # which makes the tree on this page look terrible - if match && !(slug == /structure/ && match[1] == 'sh') - lang = match[1] - if lang == 'sh' - lang = 'bash' - elsif lang == 'liquid' - lang = 'django' # Close enough. - end - pre['class'] = nil + unless slug.include?('structure') && lang == 'sh' + lang = 'bash' if lang == 'sh' pre['data-language'] = lang end - # Remove the server-rendered syntax highlighting - code = pre.at_css('code') - code.content = code.text - - # Remove the div.highlighter-rouge and div.highlight wrapping the
          -          node.add_next_sibling pre
          -          node.remove
          +          pre.remove_attribute('class')
          +          pre.content = pre.content
          +          node.replace(pre)
                   end
           
          -        css('code').each do |node|
          -          node['class'] = ''
          -        end
          +        css('code').remove_attr('class')
           
                   css('.note').each do |node|
          -          node_type = /note ?(\w+)?/.match(node['class'])[1] || 'tip'
          +          node.name = 'blockquote'
           
                     # 
          ...
          ...
          ->
          ...
          (node > 'br').each(&:remove) #
          ...

          ...

          ...

          ...
          -> #
          ...

          ...
          ...

          ...
          node.css('br + br').each(&:remove) - - node['class'] = "note note-#{node_type}" - node['data-type'] = node_type end doc diff --git a/lib/docs/filters/jekyll/entries.rb b/lib/docs/filters/jekyll/entries.rb index cf6b34b2..fd8be9ac 100644 --- a/lib/docs/filters/jekyll/entries.rb +++ b/lib/docs/filters/jekyll/entries.rb @@ -1,13 +1,12 @@ module Docs class Jekyll class EntriesFilter < Docs::EntriesFilter - def get_name at_css('h1').content end def get_type - if /continuous-integration/.match(slug) + if slug.include?('continuous-integration') 'Deployment' else nav_link = doc.document # document diff --git a/lib/docs/scrapers/jekyll.rb b/lib/docs/scrapers/jekyll.rb index 988e77bd..1faaa9de 100644 --- a/lib/docs/scrapers/jekyll.rb +++ b/lib/docs/scrapers/jekyll.rb @@ -1,7 +1,7 @@ module Docs class Jekyll < UrlScraper self.type = 'jekyll' - self.release = '3.6.2' + self.release = '3.7.2' self.base_url = 'https://jekyllrb.com/docs/' self.root_path = 'home/' self.links = { @@ -12,23 +12,21 @@ module Docs html_filters.push 'jekyll/clean_html', 'jekyll/entries' options[:trailing_slash] = true - options[:container] = 'article' - options[:skip] = [ - '', - '/' - ] + options[:skip] = %w(sites/ upgrading/) options[:skip_patterns] = [ /conduct/, /history/, /maintaining/, - /contributing/ + /contributing/, ] + options[:replace_paths] = { + '' => 'home/', + '/' => 'home/' + } + options[:attribution] = <<-HTML - © 2008–2017 Tom Preston-Werner and Jekyll contributors
          - Licensed under - - the MIT license - + © 2008–2018 Tom Preston-Werner and Jekyll contributors
          + Licensed under the MIT license. HTML end end diff --git a/public/icons/docs/jekyll/16.png b/public/icons/docs/jekyll/16.png index aeb20c40aac35c0f9231dad3af159ffc04d1b60e..5ed82ea0bc206d0bc4c6834858b45ce4f397ff14 100644 GIT binary patch delta 376 zcmV-;0f+wO0+R!fB!5~-L_t(|0hLe#tejyGtc|#~ZQC}Y+Kn32wrxda^lTev+qTW= zUF`nf#MvEo_#dQF`GrrPzc89xS{?ux)PWR2q2zBtVKMIAzmJ-l8gDEXn?jikpg)by z47bx5P$*UKc)T?LI#U*~SS)AT+UekMc`zDH2t}jYh~o44LVtQzKq8gF;c%D$bfruV z27@y)(NlB=3mT;wet+-@k-J*0d6RYL7L~yC@k=T*-b9k|y0_-#+RNrG0(aOLxa#T~ ziQMgW`~I?ndr&iC43x{(AQTE6BNE_NmzNjKnhwU4X|TL};|0)%GC3R$539a=CE2=T z14JXo!>dw%CvkGuDwQ`%wyZ+K@G;OGJcf+mVj_W-pWjtQ<0pVUb|UP#`C=ln-|t^s zcKQ%1hmL}L=6v|Q-U~zmKA&%4_3=Zg)}f&U|g8i!_PH8zDUvKGyvY*L9t5TaH0 zV%OuPWIv0*MFZLogt`*kgfa+zMvxLST|nCS(b=BE!+XwoU!_pU$NZzzq=8M>C6n1% z*k4ToR4V68#F*T1j!wHxuh&~1plKS#ViDW6ux*R0YE^Cp-+wmbBf4v^n=pxehvyWEb#h4SYDOw(lVL!b=>vvP@M zt0`yYBhMplK0{$e@Sv{|$A3rV*B3@YVC{RXpKWpd+)50SGB1se<1n4hm`p?>V6G3s cFkCv$Kc=8pvchLQ(*OVf07*qoM6N<$g01tQyZ`_I diff --git a/public/icons/docs/jekyll/16@2x.png b/public/icons/docs/jekyll/16@2x.png index 1bf8b58f03aa7fd0d1550d9033551d377b18b62b..5abb95608aa85c634fb89c09ce52cbc0719e3998 100644 GIT binary patch delta 937 zcmV;a16KU02EGT7BYy*hNklzl2%e_U?wzu9d5#eTnk#Bxfm(b3V({`~ttJow;4 zIPJ7kaqqqN4rk0zWxCz|%>Y*94lp@6xwA^6!wi)MufOpo&VM-b3>>g)CTtpvc7!|qsM zzKoDXwN_{CAJFk&Bd!3UP}IF>_G}E%Sb~`kq9~!;?f%01;IlW)eaHY<`~86slBo>J zWInmw9@6J0aRtZ~3h%JiJDeV{F@z&A2-zI!LYA3N0DrIwPxGzfc6+5o=3|fX1nvF* zrb7JTXJ)=V=_00@&D~D(_fMaR*h7z@u+}1?*s>_PY^);p~sa89`k>H52s&z688QAm zif6ap39`clMS@5B+SB;|sDm(#ww{FmV!P~t%1LK1^JM|7%r$tNc84_c#`EycPCG+Q z0Dmq5$nLv8#E(DYA3UNcUTFO83rsun82nG|H&F2awZE|A9?ArdAY{MPJaa$(J8&P& zAoYp{4_kDu_odv?gVv$wmrI7KvbFleiPc*_{~= zK}E2bS)Jt42j1Ju`+VN-`+a$yN9pM~5U`1%vdOXO0OC^*NPlhHMqgh)^}0)CevWc^ z2G8?0PJvW1#oo?NCMOFpdF#wj;PHQ^Nk3XH_@S*RRpPOTQTN`K2 zo+Su^=${~$FA$H%X*3%2_YZJnc$h>Y&b6yoqgTMP+Ue-%!1Fw$ln5!2QZidEbLGmf zD2fs-KrUZE(|Q!7RS-qiGsKtlhrR@VI^ZR`kCh zlgW@sB;LyZX5IPYcO1uw9w1-nMO9UTAV7+D@)wI^>z2RiUyw|u=iw6!~oe`4k;zB>tYx>Vs;ksaFXH{GgR`X0rL4?8h?w=aeljrm?;x`JcIVjWp125 z7kw?*y?YNy=Ov35FJR0)M<^=hj<5L3t5dC3L%n}fCd}sxtlqkguwP*)3MOD4KgL+G z7&>`qfR>gPy4q5>PyQuXTp`}xilGVYfp58Y@6YJ_f$jr6@Xr+f!ZJD_mTk;Jj`6=I z@qIsffPY+fH}&ZfI|j4FVkUac!Te!_v9ZyneCar<)?_HRSXo&qeB$O$D6+Wx)sng!8f~h;!e+^RP8nAqu>t>hAKQw zE0D=#&?`@a^ivN1=Fg)Tfz1MEzE zfj9pQJz!0K!{k|}i&AN7W9EXFXb4qcpsbm1XprLFyP*ru2mNJP*6ELJdQn|s;KWIE zx6anSUKWlHa_Q&Gq5A*-3T3^sVLIK)zWw`IwQU|exc^y_hXVM2IE^Y^11n Date: Sat, 28 Oct 2017 07:39:26 -0400 Subject: [PATCH 114/244] Update Prism --- assets/javascripts/vendor/prism.js | 282 +++++++++++++++-------------- 1 file changed, 147 insertions(+), 135 deletions(-) diff --git a/assets/javascripts/vendor/prism.js b/assets/javascripts/vendor/prism.js index a23384a3..4708065f 100644 --- a/assets/javascripts/vendor/prism.js +++ b/assets/javascripts/vendor/prism.js @@ -460,10 +460,6 @@ Token.stringify = function(o, language, parent) { parent: parent }; - if (env.type == 'comment') { - env.attributes['spellcheck'] = 'true'; - } - if (o.alias) { var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias]; Array.prototype.push.apply(env.classes, aliases); @@ -539,7 +535,7 @@ Prism.languages.markup = { 'doctype': //i, 'cdata': //i, 'tag': { - pattern: /<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\s\S])*\1|[^\s'">=]+))?)*\s*\/?>/i, + pattern: /<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i, inside: { 'tag': { pattern: /^<\/?[^\s>\/]+/i, @@ -549,9 +545,15 @@ Prism.languages.markup = { } }, 'attr-value': { - pattern: /=(?:('|")[\s\S]*?(\1)|[^\s>]+)/i, + pattern: /=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i, inside: { - 'punctuation': /[=>"']/ + 'punctuation': [ + /^=/, + { + pattern: /(^|[^\\])["']/, + lookbehind: true + } + ] } }, 'punctuation': /\/?>/, @@ -586,19 +588,19 @@ Prism.languages.svg = Prism.languages.markup; Prism.languages.css = { 'comment': /\/\*[\s\S]*?\*\//, 'atrule': { - pattern: /@[\w-]+?.*?(;|(?=\s*\{))/i, + pattern: /@[\w-]+?.*?(?:;|(?=\s*\{))/i, inside: { 'rule': /@[\w-]+/ // See rest below } }, - 'url': /url\((?:(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i, - 'selector': /[^\{\}\s][^\{\};]*?(?=\s*\{)/, + 'url': /url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i, + 'selector': /[^{}\s][^{};]*?(?=\s*\{)/, 'string': { - pattern: /("|')(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, + pattern: /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, greedy: true }, - 'property': /(\b|\B)[\w-]+(?=\s*:)/i, + 'property': /[\w-]+(?=\s*:)/i, 'important': /\B!important\b/i, 'function': /[-a-z0-9]+(?=\()/i, 'punctuation': /[(){};:]/ @@ -615,10 +617,10 @@ if (Prism.languages.markup) { alias: 'language-css' } }); - + Prism.languages.insertBefore('inside', 'attr-value', { 'style-attr': { - pattern: /\s*style=("|').*?\1/i, + pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i, inside: { 'attr-name': { pattern: /^\s*style/i, @@ -646,18 +648,18 @@ Prism.languages.clike = { } ], 'string': { - pattern: /(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, + pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, greedy: true }, 'class-name': { - pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i, + pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i, lookbehind: true, inside: { - punctuation: /(\.|\\)/ + punctuation: /[.\\]/ } }, - 'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/, - 'boolean': /\b(true|false)\b/, + 'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/, + 'boolean': /\b(?:true|false)\b/, 'function': /[a-z0-9_]+(?=\()/i, 'number': /\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i, 'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/, @@ -665,10 +667,10 @@ Prism.languages.clike = { }; Prism.languages.javascript = Prism.languages.extend('clike', { - 'keyword': /\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/, - 'number': /\b-?(0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/, + 'keyword': /\b(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/, + 'number': /\b-?(?:0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|\d*\.?\d+(?:[Ee][+-]?\d+)?|NaN|Infinity)\b/, // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444) - 'function': /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i, + 'function': /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*\()/i, 'operator': /-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/ }); @@ -677,12 +679,17 @@ Prism.languages.insertBefore('javascript', 'keyword', { pattern: /(^|[^/])\/(?!\/)(\[[^\]\r\n]+]|\\.|[^/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/, lookbehind: true, greedy: true + }, + // This must be declared before keyword because we use "function" inside the look-forward + 'function-variable': { + pattern: /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)\s*=>))/i, + alias: 'function' } }); Prism.languages.insertBefore('javascript', 'string', { 'template-string': { - pattern: /`(?:\\\\|\\?[^\\])*?`/, + pattern: /`(?:\\[\s\S]|[^\\`])*`/, greedy: true, inside: { 'interpolation': { @@ -714,8 +721,8 @@ if (Prism.languages.markup) { Prism.languages.js = Prism.languages.javascript; Prism.languages.c = Prism.languages.extend('clike', { - 'keyword': /\b(_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/, - 'operator': /\-[>-]?|\+\+?|!=?|<>?=?|==?|&&?|\|?\||[~^%?*\/]/, + 'keyword': /\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/, + 'operator': /-[>-]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/]/, 'number': /\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)[ful]*\b/i }); @@ -723,39 +730,39 @@ Prism.languages.insertBefore('c', 'string', { 'macro': { // allow for multiline macro definitions // spaces after the # character compile fine with gcc - pattern: /(^\s*)#\s*[a-z]+([^\r\n\\]|\\.|\\(?:\r\n?|\n))*/im, + pattern: /(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im, lookbehind: true, alias: 'property', inside: { // highlight the path of the include statement as a string 'string': { - pattern: /(#\s*include\s*)(<.+?>|("|')(\\?.)+?\3)/, + pattern: /(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/, lookbehind: true }, // highlight macro directives as keywords 'directive': { - pattern: /(#\s*)\b(define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/, + pattern: /(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/, lookbehind: true, alias: 'keyword' } } }, // highlight predefined macros as constants - 'constant': /\b(__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/ + 'constant': /\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/ }); delete Prism.languages.c['class-name']; delete Prism.languages.c['boolean']; Prism.languages.cpp = Prism.languages.extend('c', { - 'keyword': /\b(alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/, - 'boolean': /\b(true|false)\b/, - 'operator': /[-+]{1,2}|!=?|<{1,2}=?|>{1,2}=?|\->|:{1,2}|={1,2}|\^|~|%|&{1,2}|\|?\||\?|\*|\/|\b(and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/ + 'keyword': /\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/, + 'boolean': /\b(?:true|false)\b/, + 'operator': /--?|\+\+?|!=?|<{1,2}=?|>{1,2}=?|->|:{1,2}|={1,2}|\^|~|%|&{1,2}|\|\|?|\?|\*|\/|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/ }); Prism.languages.insertBefore('cpp', 'keyword', { 'class-name': { - pattern: /(class\s+)[a-z0-9_]+/i, + pattern: /(class\s+)\w+/i, lookbehind: true } }); @@ -774,20 +781,20 @@ Prism.languages.coffeescript = Prism.languages.extend('javascript', { // Strings are multiline { - pattern: /'(?:\\?[^\\])*?'/, + pattern: /'(?:\\[\s\S]|[^\\'])*'/, greedy: true }, { // Strings are multiline - pattern: /"(?:\\?[^\\])*?"/, + pattern: /"(?:\\[\s\S]|[^\\"])*"/, greedy: true, inside: { 'interpolation': interpolation } } ], - 'keyword': /\b(and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/, + 'keyword': /\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/, 'class-member': { pattern: /@(?!\d)\w+/, alias: 'variable' @@ -813,7 +820,7 @@ Prism.languages.insertBefore('coffeescript', 'comment', { Prism.languages.insertBefore('coffeescript', 'string', { 'inline-javascript': { - pattern: /`(?:\\?[\s\S])*?`/, + pattern: /`(?:\\[\s\S]|[^\\`])*`/, inside: { 'delimiter': { pattern: /^`|`$/, @@ -862,7 +869,7 @@ delete Prism.languages.coffeescript['template-string']; /#(?!\{[^\r\n]*?\}).*/, /^=begin(?:\r?\n|\r)(?:.*(?:\r?\n|\r))*?=end/m ], - 'keyword': /\b(alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|false|for|if|in|module|new|next|nil|not|or|raise|redo|require|rescue|retry|return|self|super|then|throw|true|undef|unless|until|when|while|yield)\b/ + 'keyword': /\b(?:alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|false|for|if|in|module|new|next|nil|not|or|raise|redo|require|rescue|retry|return|self|super|then|throw|true|undef|unless|until|when|while|yield)\b/ }); var interpolation = { @@ -879,7 +886,7 @@ delete Prism.languages.coffeescript['template-string']; Prism.languages.insertBefore('ruby', 'keyword', { 'regex': [ { - pattern: /%r([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1[gim]{0,3}/, + pattern: /%r([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[gim]{0,3}/, greedy: true, inside: { 'interpolation': interpolation @@ -920,18 +927,18 @@ delete Prism.languages.coffeescript['template-string']; greedy: true } ], - 'variable': /[@$]+[a-zA-Z_][a-zA-Z_0-9]*(?:[?!]|\b)/, - 'symbol': /:[a-zA-Z_][a-zA-Z_0-9]*(?:[?!]|\b)/ + 'variable': /[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/, + 'symbol': /:[a-zA-Z_]\w*(?:[?!]|\b)/ }); Prism.languages.insertBefore('ruby', 'number', { - 'builtin': /\b(Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|File|Fixnum|Float|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/, - 'constant': /\b[A-Z][a-zA-Z_0-9]*(?:[?!]|\b)/ + 'builtin': /\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|Fixnum|Float|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/, + 'constant': /\b[A-Z]\w*(?:[?!]|\b)/ }); Prism.languages.ruby.string = [ { - pattern: /%[qQiIwWxs]?([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1/, + pattern: /%[qQiIwWxs]?([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/, greedy: true, inside: { 'interpolation': interpolation @@ -967,7 +974,7 @@ delete Prism.languages.coffeescript['template-string']; } }, { - pattern: /("|')(#\{[^}]+\}|\\(?:\r?\n|\r)|\\?.)*?\1/, + pattern: /("|')(?:#\{[^}]+\}|\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, greedy: true, inside: { 'interpolation': interpolation @@ -978,7 +985,7 @@ delete Prism.languages.coffeescript['template-string']; Prism.languages.d = Prism.languages.extend('clike', { 'string': [ // r"", x"" - /\b[rx]"(\\.|[^\\"])*"[cwd]?/, + /\b[rx]"(?:\\[\s\S]|[^\\"])*"[cwd]?/, // q"[]", q"()", q"<>", q"{}" /\bq"(?:\[[\s\S]*?\]|\([\s\S]*?\)|<[\s\S]*?>|\{[\s\S]*?\})"/, // q"IDENT @@ -990,7 +997,7 @@ Prism.languages.d = Prism.languages.extend('clike', { // Characters /'(?:\\'|\\?[^']+)'/, - /(["`])(\\.|(?!\1)[^\\])*\1[cwd]?/ + /(["`])(?:\\[\s\S]|(?!\1)[^\\])*\1[cwd]?/ ], 'number': [ @@ -1023,7 +1030,7 @@ Prism.languages.d.comment = [ Prism.languages.insertBefore('d', 'comment', { 'token-string': { // Allow one level of nesting - pattern: /\bq\{(?:|\{[^}]*\}|[^}])*\}/, + pattern: /\bq\{(?:\{[^}]*\}|[^}])*\}/, alias: 'string' } }); @@ -1047,12 +1054,12 @@ Prism.languages.elixir = { pattern: /(^|[^#])#(?![{#]).*/m, lookbehind: true }, - // ~r"""foo""", ~r'''foo''', ~r/foo/, ~r|foo|, ~r"foo", ~r'foo', ~r(foo), ~r[foo], ~r{foo}, ~r - 'regex': /~[rR](?:("""|'''|[\/|"'])(?:\\.|(?!\1)[^\\])+\1|\((?:\\\)|[^)])+\)|\[(?:\\\]|[^\]])+\]|\{(?:\\\}|[^}])+\}|<(?:\\>|[^>])+>)[uismxfr]*/, + // ~r"""foo""" (multi-line), ~r'''foo''' (multi-line), ~r/foo/, ~r|foo|, ~r"foo", ~r'foo', ~r(foo), ~r[foo], ~r{foo}, ~r + 'regex': /~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/, 'string': [ { - // ~s"""foo""", ~s'''foo''', ~s/foo/, ~s|foo|, ~s"foo", ~s'foo', ~s(foo), ~s[foo], ~s{foo}, ~s - pattern: /~[cCsSwW](?:("""|'''|[\/|"'])(?:\\.|(?!\1)[^\\])+\1|\((?:\\\)|[^)])+\)|\[(?:\\\]|[^\]])+\]|\{(?:\\\}|#\{[^}]+\}|[^}])+\}|<(?:\\>|[^>])+>)[csa]?/, + // ~s"""foo""" (multi-line), ~s'''foo''' (multi-line), ~s/foo/, ~s|foo|, ~s"foo", ~s'foo', ~s(foo), ~s[foo], ~s{foo} (with interpolation care), ~s + pattern: /~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/, greedy: true, inside: { // See interpolation below @@ -1067,7 +1074,7 @@ Prism.languages.elixir = { }, { // Multi-line strings are allowed - pattern: /("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/, + pattern: /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, greedy: true, inside: { // See interpolation below @@ -1136,15 +1143,15 @@ Prism.languages.elixir.string.forEach(function(o) { Prism.languages.erlang = { 'comment': /%.+/, 'string': { - pattern: /"(?:\\?.)*?"/, + pattern: /"(?:\\.|[^\\"\r\n])*"/, greedy: true }, 'quoted-function': { - pattern: /'(?:\\.|[^'\\])+'(?=\()/, + pattern: /'(?:\\.|[^\\'\r\n])+'(?=\()/, alias: 'function' }, 'quoted-atom': { - pattern: /'(?:\\.|[^'\\])+'/, + pattern: /'(?:\\.|[^\\'\r\n])+'/, alias: 'atom' }, 'boolean': /\b(?:true|false)\b/, @@ -1178,20 +1185,20 @@ Prism.languages.erlang = { }; Prism.languages.go = Prism.languages.extend('clike', { - 'keyword': /\b(break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/, - 'builtin': /\b(bool|byte|complex(64|128)|error|float(32|64)|rune|string|u?int(8|16|32|64|)|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(ln)?|real|recover)\b/, - 'boolean': /\b(_|iota|nil|true|false)\b/, + 'keyword': /\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/, + 'builtin': /\b(?:bool|byte|complex(?:64|128)|error|float(?:32|64)|rune|string|u?int(?:8|16|32|64)?|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(?:ln)?|real|recover)\b/, + 'boolean': /\b(?:_|iota|nil|true|false)\b/, 'operator': /[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./, 'number': /\b(-?(0x[a-f\d]+|(\d+\.?\d*|\.\d+)(e[-+]?\d+)?)i?)\b/i, 'string': { - pattern: /("|'|`)(\\?.|\r|\n)*?\1/, + pattern: /(["'`])(\\[\s\S]|(?!\1)[^\\])*\1/, greedy: true } }); delete Prism.languages.go['class-name']; Prism.languages.java = Prism.languages.extend('clike', { - 'keyword': /\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/, + 'keyword': /\b(?:abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/, 'number': /\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+(?:e[+-]?\d+)?[df]?\b/i, 'operator': { pattern: /(^|[^.])(?:\+[+=]?|-[-=]?|!=?|<>?>?=?|==?|&[&=]?|\|[|=]?|\*=?|\/=?|%=?|\^=?|[?:~])/m, @@ -1208,13 +1215,16 @@ Prism.languages.insertBefore('java','function', { }); Prism.languages.json = { - 'property': /"(?:\\.|[^\\"])*"(?=\s*:)/ig, - 'string': /"(?!:)(?:\\.|[^\\"])*"(?!:)/g, - 'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?)\b/g, - 'punctuation': /[{}[\]);,]/g, + 'property': /"(?:\\.|[^\\"\r\n])*"(?=\s*:)/i, + 'string': { + pattern: /"(?:\\.|[^\\"\r\n])*"(?!\s*:)/, + greedy: true + }, + 'number': /\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee][+-]?\d+)?)\b/, + 'punctuation': /[{}[\]);,]/, 'operator': /:/g, - 'boolean': /\b(true|false)\b/gi, - 'null': /\bnull\b/gi + 'boolean': /\b(?:true|false)\b/i, + 'null': /\bnull\b/i }; Prism.languages.jsonp = Prism.languages.json; @@ -1241,7 +1251,7 @@ Prism.languages.jsonp = Prism.languages.json; Prism.languages.insertBefore('kotlin', 'string', { 'raw-string': { - pattern: /(["'])\1\1[\s\S]*?\1{3}/, + pattern: /("""|''')[\s\S]*?\1/, alias: 'string' // See interpolation below } @@ -1306,7 +1316,7 @@ Prism.languages.nginx = Prism.languages.extend('clike', { pattern: /(^|[^"{\\])#.*/, lookbehind: true }, - 'keyword': /\b(?:CONTENT_|DOCUMENT_|GATEWAY_|HTTP_|HTTPS|if_not_empty|PATH_|QUERY_|REDIRECT_|REMOTE_|REQUEST_|SCGI|SCRIPT_|SERVER_|http|server|events|location|include|accept_mutex|accept_mutex_delay|access_log|add_after_body|add_before_body|add_header|addition_types|aio|alias|allow|ancient_browser|ancient_browser_value|auth|auth_basic|auth_basic_user_file|auth_http|auth_http_header|auth_http_timeout|autoindex|autoindex_exact_size|autoindex_localtime|break|charset|charset_map|charset_types|chunked_transfer_encoding|client_body_buffer_size|client_body_in_file_only|client_body_in_single_buffer|client_body_temp_path|client_body_timeout|client_header_buffer_size|client_header_timeout|client_max_body_size|connection_pool_size|create_full_put_path|daemon|dav_access|dav_methods|debug_connection|debug_points|default_type|deny|devpoll_changes|devpoll_events|directio|directio_alignment|disable_symlinks|empty_gif|env|epoll_events|error_log|error_page|expires|fastcgi_buffer_size|fastcgi_buffers|fastcgi_busy_buffers_size|fastcgi_cache|fastcgi_cache_bypass|fastcgi_cache_key|fastcgi_cache_lock|fastcgi_cache_lock_timeout|fastcgi_cache_methods|fastcgi_cache_min_uses|fastcgi_cache_path|fastcgi_cache_purge|fastcgi_cache_use_stale|fastcgi_cache_valid|fastcgi_connect_timeout|fastcgi_hide_header|fastcgi_ignore_client_abort|fastcgi_ignore_headers|fastcgi_index|fastcgi_intercept_errors|fastcgi_keep_conn|fastcgi_max_temp_file_size|fastcgi_next_upstream|fastcgi_no_cache|fastcgi_param|fastcgi_pass|fastcgi_pass_header|fastcgi_read_timeout|fastcgi_redirect_errors|fastcgi_send_timeout|fastcgi_split_path_info|fastcgi_store|fastcgi_store_access|fastcgi_temp_file_write_size|fastcgi_temp_path|flv|geo|geoip_city|geoip_country|google_perftools_profiles|gzip|gzip_buffers|gzip_comp_level|gzip_disable|gzip_http_version|gzip_min_length|gzip_proxied|gzip_static|gzip_types|gzip_vary|if|if_modified_since|ignore_invalid_headers|image_filter|image_filter_buffer|image_filter_jpeg_quality|image_filter_sharpen|image_filter_transparency|imap_capabilities|imap_client_buffer|include|index|internal|ip_hash|keepalive|keepalive_disable|keepalive_requests|keepalive_timeout|kqueue_changes|kqueue_events|large_client_header_buffers|limit_conn|limit_conn_log_level|limit_conn_zone|limit_except|limit_rate|limit_rate_after|limit_req|limit_req_log_level|limit_req_zone|limit_zone|lingering_close|lingering_time|lingering_timeout|listen|location|lock_file|log_format|log_format_combined|log_not_found|log_subrequest|map|map_hash_bucket_size|map_hash_max_size|master_process|max_ranges|memcached_buffer_size|memcached_connect_timeout|memcached_next_upstream|memcached_pass|memcached_read_timeout|memcached_send_timeout|merge_slashes|min_delete_depth|modern_browser|modern_browser_value|mp4|mp4_buffer_size|mp4_max_buffer_size|msie_padding|msie_refresh|multi_accept|open_file_cache|open_file_cache_errors|open_file_cache_min_uses|open_file_cache_valid|open_log_file_cache|optimize_server_names|override_charset|pcre_jit|perl|perl_modules|perl_require|perl_set|pid|pop3_auth|pop3_capabilities|port_in_redirect|post_action|postpone_output|protocol|proxy|proxy_buffer|proxy_buffer_size|proxy_buffering|proxy_buffers|proxy_busy_buffers_size|proxy_cache|proxy_cache_bypass|proxy_cache_key|proxy_cache_lock|proxy_cache_lock_timeout|proxy_cache_methods|proxy_cache_min_uses|proxy_cache_path|proxy_cache_use_stale|proxy_cache_valid|proxy_connect_timeout|proxy_cookie_domain|proxy_cookie_path|proxy_headers_hash_bucket_size|proxy_headers_hash_max_size|proxy_hide_header|proxy_http_version|proxy_ignore_client_abort|proxy_ignore_headers|proxy_intercept_errors|proxy_max_temp_file_size|proxy_method|proxy_next_upstream|proxy_no_cache|proxy_pass|proxy_pass_error_message|proxy_pass_header|proxy_pass_request_body|proxy_pass_request_headers|proxy_read_timeout|proxy_redirect|proxy_redirect_errors|proxy_send_lowat|proxy_send_timeout|proxy_set_body|proxy_set_header|proxy_ssl_session_reuse|proxy_store|proxy_store_access|proxy_temp_file_write_size|proxy_temp_path|proxy_timeout|proxy_upstream_fail_timeout|proxy_upstream_max_fails|random_index|read_ahead|real_ip_header|recursive_error_pages|request_pool_size|reset_timedout_connection|resolver|resolver_timeout|return|rewrite|root|rtsig_overflow_events|rtsig_overflow_test|rtsig_overflow_threshold|rtsig_signo|satisfy|satisfy_any|secure_link_secret|send_lowat|send_timeout|sendfile|sendfile_max_chunk|server|server_name|server_name_in_redirect|server_names_hash_bucket_size|server_names_hash_max_size|server_tokens|set|set_real_ip_from|smtp_auth|smtp_capabilities|so_keepalive|source_charset|split_clients|ssi|ssi_silent_errors|ssi_types|ssi_value_length|ssl|ssl_certificate|ssl_certificate_key|ssl_ciphers|ssl_client_certificate|ssl_crl|ssl_dhparam|ssl_engine|ssl_prefer_server_ciphers|ssl_protocols|ssl_session_cache|ssl_session_timeout|ssl_verify_client|ssl_verify_depth|starttls|stub_status|sub_filter|sub_filter_once|sub_filter_types|tcp_nodelay|tcp_nopush|timeout|timer_resolution|try_files|types|types_hash_bucket_size|types_hash_max_size|underscores_in_headers|uninitialized_variable_warn|upstream|use|user|userid|userid_domain|userid_expires|userid_name|userid_p3p|userid_path|userid_service|valid_referers|variables_hash_bucket_size|variables_hash_max_size|worker_connections|worker_cpu_affinity|worker_priority|worker_processes|worker_rlimit_core|worker_rlimit_nofile|worker_rlimit_sigpending|working_directory|xclient|xml_entities|xslt_entities|xslt_stylesheet|xslt_types)\b/i, + 'keyword': /\b(?:CONTENT_|DOCUMENT_|GATEWAY_|HTTP_|HTTPS|if_not_empty|PATH_|QUERY_|REDIRECT_|REMOTE_|REQUEST_|SCGI|SCRIPT_|SERVER_|http|events|accept_mutex|accept_mutex_delay|access_log|add_after_body|add_before_body|add_header|addition_types|aio|alias|allow|ancient_browser|ancient_browser_value|auth|auth_basic|auth_basic_user_file|auth_http|auth_http_header|auth_http_timeout|autoindex|autoindex_exact_size|autoindex_localtime|break|charset|charset_map|charset_types|chunked_transfer_encoding|client_body_buffer_size|client_body_in_file_only|client_body_in_single_buffer|client_body_temp_path|client_body_timeout|client_header_buffer_size|client_header_timeout|client_max_body_size|connection_pool_size|create_full_put_path|daemon|dav_access|dav_methods|debug_connection|debug_points|default_type|deny|devpoll_changes|devpoll_events|directio|directio_alignment|disable_symlinks|empty_gif|env|epoll_events|error_log|error_page|expires|fastcgi_buffer_size|fastcgi_buffers|fastcgi_busy_buffers_size|fastcgi_cache|fastcgi_cache_bypass|fastcgi_cache_key|fastcgi_cache_lock|fastcgi_cache_lock_timeout|fastcgi_cache_methods|fastcgi_cache_min_uses|fastcgi_cache_path|fastcgi_cache_purge|fastcgi_cache_use_stale|fastcgi_cache_valid|fastcgi_connect_timeout|fastcgi_hide_header|fastcgi_ignore_client_abort|fastcgi_ignore_headers|fastcgi_index|fastcgi_intercept_errors|fastcgi_keep_conn|fastcgi_max_temp_file_size|fastcgi_next_upstream|fastcgi_no_cache|fastcgi_param|fastcgi_pass|fastcgi_pass_header|fastcgi_read_timeout|fastcgi_redirect_errors|fastcgi_send_timeout|fastcgi_split_path_info|fastcgi_store|fastcgi_store_access|fastcgi_temp_file_write_size|fastcgi_temp_path|flv|geo|geoip_city|geoip_country|google_perftools_profiles|gzip|gzip_buffers|gzip_comp_level|gzip_disable|gzip_http_version|gzip_min_length|gzip_proxied|gzip_static|gzip_types|gzip_vary|if|if_modified_since|ignore_invalid_headers|image_filter|image_filter_buffer|image_filter_jpeg_quality|image_filter_sharpen|image_filter_transparency|imap_capabilities|imap_client_buffer|include|index|internal|ip_hash|keepalive|keepalive_disable|keepalive_requests|keepalive_timeout|kqueue_changes|kqueue_events|large_client_header_buffers|limit_conn|limit_conn_log_level|limit_conn_zone|limit_except|limit_rate|limit_rate_after|limit_req|limit_req_log_level|limit_req_zone|limit_zone|lingering_close|lingering_time|lingering_timeout|listen|location|lock_file|log_format|log_format_combined|log_not_found|log_subrequest|map|map_hash_bucket_size|map_hash_max_size|master_process|max_ranges|memcached_buffer_size|memcached_connect_timeout|memcached_next_upstream|memcached_pass|memcached_read_timeout|memcached_send_timeout|merge_slashes|min_delete_depth|modern_browser|modern_browser_value|mp4|mp4_buffer_size|mp4_max_buffer_size|msie_padding|msie_refresh|multi_accept|open_file_cache|open_file_cache_errors|open_file_cache_min_uses|open_file_cache_valid|open_log_file_cache|optimize_server_names|override_charset|pcre_jit|perl|perl_modules|perl_require|perl_set|pid|pop3_auth|pop3_capabilities|port_in_redirect|post_action|postpone_output|protocol|proxy|proxy_buffer|proxy_buffer_size|proxy_buffering|proxy_buffers|proxy_busy_buffers_size|proxy_cache|proxy_cache_bypass|proxy_cache_key|proxy_cache_lock|proxy_cache_lock_timeout|proxy_cache_methods|proxy_cache_min_uses|proxy_cache_path|proxy_cache_use_stale|proxy_cache_valid|proxy_connect_timeout|proxy_cookie_domain|proxy_cookie_path|proxy_headers_hash_bucket_size|proxy_headers_hash_max_size|proxy_hide_header|proxy_http_version|proxy_ignore_client_abort|proxy_ignore_headers|proxy_intercept_errors|proxy_max_temp_file_size|proxy_method|proxy_next_upstream|proxy_no_cache|proxy_pass|proxy_pass_error_message|proxy_pass_header|proxy_pass_request_body|proxy_pass_request_headers|proxy_read_timeout|proxy_redirect|proxy_redirect_errors|proxy_send_lowat|proxy_send_timeout|proxy_set_body|proxy_set_header|proxy_ssl_session_reuse|proxy_store|proxy_store_access|proxy_temp_file_write_size|proxy_temp_path|proxy_timeout|proxy_upstream_fail_timeout|proxy_upstream_max_fails|random_index|read_ahead|real_ip_header|recursive_error_pages|request_pool_size|reset_timedout_connection|resolver|resolver_timeout|return|rewrite|root|rtsig_overflow_events|rtsig_overflow_test|rtsig_overflow_threshold|rtsig_signo|satisfy|satisfy_any|secure_link_secret|send_lowat|send_timeout|sendfile|sendfile_max_chunk|server|server_name|server_name_in_redirect|server_names_hash_bucket_size|server_names_hash_max_size|server_tokens|set|set_real_ip_from|smtp_auth|smtp_capabilities|so_keepalive|source_charset|split_clients|ssi|ssi_silent_errors|ssi_types|ssi_value_length|ssl|ssl_certificate|ssl_certificate_key|ssl_ciphers|ssl_client_certificate|ssl_crl|ssl_dhparam|ssl_engine|ssl_prefer_server_ciphers|ssl_protocols|ssl_session_cache|ssl_session_timeout|ssl_verify_client|ssl_verify_depth|starttls|stub_status|sub_filter|sub_filter_once|sub_filter_types|tcp_nodelay|tcp_nopush|timeout|timer_resolution|try_files|types|types_hash_bucket_size|types_hash_max_size|underscores_in_headers|uninitialized_variable_warn|upstream|use|user|userid|userid_domain|userid_expires|userid_name|userid_p3p|userid_path|userid_service|valid_referers|variables_hash_bucket_size|variables_hash_max_size|worker_connections|worker_cpu_affinity|worker_priority|worker_processes|worker_rlimit_core|worker_rlimit_nofile|worker_rlimit_sigpending|working_directory|xclient|xml_entities|xslt_entities|xslt_stylesheet|xslt_types)\b/i }); Prism.languages.insertBefore('nginx', 'keyword', { @@ -1361,34 +1371,34 @@ Prism.languages.perl = { 'string': [ // q/.../ { - pattern: /\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1/, + pattern: /\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/, greedy: true }, - + // q a...a { - pattern: /\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:[^\\]|\\[\s\S])*?\1/, + pattern: /\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1/, greedy: true }, - + // q(...) { pattern: /\b(?:q|qq|qx|qw)\s*\((?:[^()\\]|\\[\s\S])*\)/, greedy: true }, - + // q{...} { pattern: /\b(?:q|qq|qx|qw)\s*\{(?:[^{}\\]|\\[\s\S])*\}/, greedy: true }, - + // q[...] { pattern: /\b(?:q|qq|qx|qw)\s*\[(?:[^[\]\\]|\\[\s\S])*\]/, greedy: true }, - + // q<...> { pattern: /\b(?:q|qq|qx|qw)\s*<(?:[^<>\\]|\\[\s\S])*>/, @@ -1397,7 +1407,7 @@ Prism.languages.perl = { // "...", `...` { - pattern: /("|`)(?:[^\\]|\\[\s\S])*?\1/, + pattern: /("|`)(?:(?!\1)[^\\]|\\[\s\S])*\1/, greedy: true }, @@ -1411,34 +1421,34 @@ Prism.languages.perl = { 'regex': [ // m/.../ { - pattern: /\b(?:m|qr)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1[msixpodualngc]*/, + pattern: /\b(?:m|qr)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/, greedy: true }, - + // m a...a { - pattern: /\b(?:m|qr)\s+([a-zA-Z0-9])(?:[^\\]|\\.)*?\1[msixpodualngc]*/, + pattern: /\b(?:m|qr)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/, greedy: true }, - + // m(...) { pattern: /\b(?:m|qr)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngc]*/, greedy: true }, - + // m{...} { pattern: /\b(?:m|qr)\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngc]*/, greedy: true }, - + // m[...] { pattern: /\b(?:m|qr)\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngc]*/, greedy: true }, - + // m<...> { pattern: /\b(?:m|qr)\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngc]*/, @@ -1449,46 +1459,46 @@ Prism.languages.perl = { // FIXME We don't handle change of separator like s(...)[...] // s/.../.../ { - pattern: /(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\2(?:[^\\]|\\[\s\S])*?\2[msixpodualngcer]*/, + pattern: /(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/, lookbehind: true, greedy: true }, - + // s a...a...a { - pattern: /(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:[^\\]|\\[\s\S])*?\2(?:[^\\]|\\[\s\S])*?\2[msixpodualngcer]*/, + pattern: /(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/, lookbehind: true, greedy: true }, - + // s(...)(...) { pattern: /(^|[^-]\b)(?:s|tr|y)\s*\((?:[^()\\]|\\[\s\S])*\)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngcer]*/, lookbehind: true, greedy: true }, - + // s{...}{...} { pattern: /(^|[^-]\b)(?:s|tr|y)\s*\{(?:[^{}\\]|\\[\s\S])*\}\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngcer]*/, lookbehind: true, greedy: true }, - + // s[...][...] { pattern: /(^|[^-]\b)(?:s|tr|y)\s*\[(?:[^[\]\\]|\\[\s\S])*\]\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngcer]*/, lookbehind: true, greedy: true }, - + // s<...><...> { pattern: /(^|[^-]\b)(?:s|tr|y)\s*<(?:[^<>\\]|\\[\s\S])*>\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngcer]*/, lookbehind: true, greedy: true }, - + // /.../ // The look-ahead tries to prevent two divisions on // the same line from being highlighted as regex. @@ -1508,7 +1518,7 @@ Prism.languages.perl = { // ${...} /[&*$@%]#?(?=\{)/, // $foo - /[&*$@%]#?((::)*'?(?!\d)[\w$]+)+(::)*/i, + /[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+)+(?:::)*/i, // $1 /[&*$@%]\d+/, // $_, @_, %! @@ -1522,7 +1532,7 @@ Prism.languages.perl = { }, 'vstring': { // v1.2, 1.2.3 - pattern: /v\d+(\.\d+)*|\d+(\.\d+){2,}/, + pattern: /v\d+(?:\.\d+)*|\d+(?:\.\d+){2,}/, alias: 'string' }, 'function': { @@ -1531,9 +1541,9 @@ Prism.languages.perl = { keyword: /sub/ } }, - 'keyword': /\b(any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|say|state|sub|switch|undef|unless|until|use|when|while)\b/, - 'number': /\b-?(0x[\dA-Fa-f](_?[\dA-Fa-f])*|0b[01](_?[01])*|(\d(_?\d)*)?\.?\d(_?\d)*([Ee][+-]?\d+)?)\b/, - 'operator': /-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/, + 'keyword': /\b(?:any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|say|state|sub|switch|undef|unless|until|use|when|while)\b/, + 'number': /\b-?(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0b[01](?:_?[01])*|(?:\d(?:_?\d)*)?\.?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)\b/, + 'operator': /-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(?:lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/, 'punctuation': /[{}[\];(),:]/ }; @@ -1551,7 +1561,7 @@ Prism.languages.perl = { */ Prism.languages.php = Prism.languages.extend('clike', { - 'keyword': /\b(and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i, + 'keyword': /\b(?:and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i, 'constant': /\b[A-Z0-9_]{2,}\b/, 'comment': { pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/, @@ -1653,32 +1663,34 @@ if (Prism.languages.markup) { }); } ; -Prism.languages.python= { - 'triple-quoted-string': { - pattern: /"""[\s\S]+?"""|'''[\s\S]+?'''/, - alias: 'string' - }, +Prism.languages.python = { 'comment': { pattern: /(^|[^\\])#.*/, lookbehind: true }, + 'triple-quoted-string': { + pattern: /("""|''')[\s\S]+?\1/, + greedy: true, + alias: 'string' + }, 'string': { - pattern: /("|')(?:\\\\|\\?[^\\\r\n])*?\1/, + pattern: /("|')(?:\\.|(?!\1)[^\\\r\n])*\1/, greedy: true }, - 'function' : { - pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_][a-zA-Z0-9_]*(?=\()/g, + 'function': { + pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g, lookbehind: true }, 'class-name': { - pattern: /(\bclass\s+)[a-z0-9_]+/i, + pattern: /(\bclass\s+)\w+/i, lookbehind: true }, - 'keyword' : /\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/, - 'boolean' : /\b(?:True|False)\b/, - 'number' : /\b-?(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i, - 'operator' : /[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/, - 'punctuation' : /[{}[\];(),.:]/ + 'keyword': /\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|pass|print|raise|return|try|while|with|yield)\b/, + 'builtin':/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/, + 'boolean': /\b(?:True|False|None)\b/, + 'number': /\b-?(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i, + 'operator': /[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/, + 'punctuation': /[{}[\];(),.:]/ }; (function(Prism) { @@ -1686,15 +1698,15 @@ Prism.languages.python= { var javascript = Prism.util.clone(Prism.languages.javascript); Prism.languages.jsx = Prism.languages.extend('markup', javascript); -Prism.languages.jsx.tag.pattern= /<\/?[\w\.:-]+\s*(?:\s+(?:[\w\.:-]+(?:=(?:("|')(\\?[\s\S])*?\1|[^\s'">=]+|(\{[\s\S]*?\})))?|\{\.{3}\w+\}))*\s*\/?>/i; +Prism.languages.jsx.tag.pattern= /<\/?[\w.:-]+\s*(?:\s+(?:[\w\.:-]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+|(?:\{[^}]*\})))?|\{\.{3}\w+\}))*\s*\/?>/i; -Prism.languages.jsx.tag.inside['attr-value'].pattern = /=(?!\{)(?:('|")[\s\S]*?(\1)|[^\s>]+)/i; +Prism.languages.jsx.tag.inside['attr-value'].pattern = /=(?!\{)(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">]+)/i; Prism.languages.insertBefore('inside', 'attr-name', { 'spread': { pattern: /\{\.{3}\w+\}/, inside: { - 'punctuation': /\{|\}|\./, + 'punctuation': /[{}]|\.{3}/, 'attr-value': /\w+/ } } @@ -1702,7 +1714,7 @@ Prism.languages.insertBefore('inside', 'attr-name', { var jsxExpression = Prism.util.clone(Prism.languages.jsx); -delete jsxExpression.punctuation +delete jsxExpression.punctuation; jsxExpression = Prism.languages.insertBefore('jsx', 'operator', { 'punctuation': /=(?={)|[{}[\];(),.:]/ @@ -1729,7 +1741,7 @@ Prism.languages.insertBefore('inside', 'attr-value',{ } ], - number: /\b(?:0b[01_]*[01]|0o[0-7_]*[0-7]|0x[0-9a-fA-F_]*[0-9a-fA-F]|(?:\d(?:[0-9_]*\d)?)(?:\.[0-9_]*\d)?(?:[eE][+-]?[0-9_]*\d)?)(?:_(?:[uif](?:8|16|32|64))?)?\b/, + number: /\b(?:0b[01_]*[01]|0o[0-7_]*[0-7]|0x[0-9a-fA-F_]*[0-9a-fA-F]|(?:\d(?:[0-9_]*\d)?)(?:\.[0-9_]*\d)?(?:[eE][+-]?[0-9_]*\d)?)(?:_(?:[uif](?:8|16|32|64))?)?\b/ }); var rest = Prism.util.clone(Prism.languages.crystal); @@ -1793,11 +1805,11 @@ Prism.languages.rust = { ], 'string': [ { - pattern: /b?r(#*)"(?:\\?.)*?"\1/, + pattern: /b?r(#*)"(?:\\.|(?!"\1)[^\\\r\n])*"\1/, greedy: true }, { - pattern: /b?("|')(?:\\?.)*?\1/, + pattern: /b?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/, greedy: true } ], @@ -1810,23 +1822,23 @@ Prism.languages.rust = { }, 'function': [ - /[a-z0-9_]+(?=\s*\()/i, + /\w+(?=\s*\()/, // Macros can use parens or brackets - /[a-z0-9_]+!(?=\s*\(|\[)/i + /\w+!(?=\s*\(|\[)/ ], 'macro-rules': { - pattern: /[a-z0-9_]+!/i, + pattern: /\w+!/, alias: 'function' }, // Hex, oct, bin, dec numbers with visual separators and type suffix - 'number': /\b-?(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(\d(_?\d)*)?\.?\d(_?\d)*([Ee][+-]?\d+)?)(?:_?(?:[iu](?:8|16|32|64)?|f32|f64))?\b/, + 'number': /\b-?(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(\d(?:_?\d)*)?\.?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:[iu](?:8|16|32|64)?|f32|f64))?\b/, // Closure params should not be confused with bitwise OR | 'closure-params': { pattern: /\|[^|]*\|(?=\s*[{-])/, inside: { - 'punctuation': /[\|:,]/, + 'punctuation': /[|:,]/, 'operator': /[&*]/ } }, @@ -1856,14 +1868,14 @@ Prism.languages.scss = Prism.languages.extend('css', { // this one was hard to do, so please be careful if you edit this one :) 'selector': { // Initial look-ahead is used to prevent matching of blank selectors - pattern: /(?=\S)[^@;\{\}\(\)]?([^@;\{\}\(\)]|&|#\{\$[-_\w]+\})+(?=\s*\{(\}|\s|[^\}]+(:|\{)[^\}]+))/m, + pattern: /(?=\S)[^@;{}()]?(?:[^@;{}()]|&|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}]+[:{][^}]+))/m, inside: { 'parent': { pattern: /&/, alias: 'important' }, - 'placeholder': /%[-_\w]+/, - 'variable': /\$[-_\w]+|#\{\$[-_\w]+\}/ + 'placeholder': /%[-\w]+/, + 'variable': /\$[-\w]+|#\{\$[-\w]+\}/ } } }); @@ -1879,20 +1891,20 @@ Prism.languages.insertBefore('scss', 'atrule', { }); Prism.languages.scss.property = { - pattern: /(?:[\w-]|\$[-_\w]+|#\{\$[-_\w]+\})+(?=\s*:)/i, + pattern: /(?:[\w-]|\$[-\w]+|#\{\$[-\w]+\})+(?=\s*:)/i, inside: { - 'variable': /\$[-_\w]+|#\{\$[-_\w]+\}/ + 'variable': /\$[-\w]+|#\{\$[-\w]+\}/ } }; Prism.languages.insertBefore('scss', 'important', { // var and interpolated vars - 'variable': /\$[-_\w]+|#\{\$[-_\w]+\}/ + 'variable': /\$[-\w]+|#\{\$[-\w]+\}/ }); Prism.languages.insertBefore('scss', 'function', { 'placeholder': { - pattern: /%[-_\w]+/, + pattern: /%[-\w]+/, alias: 'selector' }, 'statement': { @@ -1914,21 +1926,21 @@ Prism.languages.sql= { lookbehind: true }, 'string' : { - pattern: /(^|[^@\\])("|')(?:\\?[\s\S])*?\2/, + pattern: /(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\])*\2/, greedy: true, lookbehind: true }, - 'variable': /@[\w.$]+|@("|'|`)(?:\\?[\s\S])+?\1/, + 'variable': /@[\w.$]+|@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/, 'function': /\b(?:COUNT|SUM|AVG|MIN|MAX|FIRST|LAST|UCASE|LCASE|MID|LEN|ROUND|NOW|FORMAT)(?=\s*\()/i, // Should we highlight user defined functions too? 'keyword': /\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR VARYING|CHARACTER (?:SET|VARYING)|CHARSET|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COLUMNS|COMMENT|COMMIT|COMMITTED|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|DATA(?:BASES?)?|DATE(?:TIME)?|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITER(?:S)?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE(?: PRECISION)?|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE KEY|ELSE|ENABLE|ENCLOSED BY|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPE(?:D BY)?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTO|INVOKER|ISOLATION LEVEL|JOIN|KEYS?|KILL|LANGUAGE SQL|LAST|LEFT|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MODIFIES SQL DATA|MODIFY|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL(?: CHAR VARYING| CHARACTER(?: VARYING)?| VARCHAR)?|NATURAL|NCHAR(?: VARCHAR)?|NEXT|NO(?: SQL|CHECK|CYCLE)?|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READ(?:S SQL DATA|TEXT)?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEATABLE|REPLICATION|REQUIRE|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE MODE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|START(?:ING BY)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED BY|TEXT(?:SIZE)?|THEN|TIMESTAMP|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNPIVOT|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?)\b/i, 'boolean': /\b(?:TRUE|FALSE|NULL)\b/i, 'number': /\b-?(?:0x)?\d*\.?[\da-f]+\b/, - 'operator': /[-+*\/=%^~]|&&?|\|?\||!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i, + 'operator': /[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i, 'punctuation': /[;[\]()`,.]/ }; Prism.languages.typescript = Prism.languages.extend('javascript', { // From JavaScript Prism keyword list and TypeScript language spec: https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#221-reserved-words - 'keyword': /\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield|false|true|module|declare|constructor|string|Function|any|number|boolean|Array|enum|symbol|namespace|abstract|require|type)\b/ + 'keyword': /\b(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield|false|true|module|declare|constructor|string|Function|any|number|boolean|Array|symbol|namespace|abstract|require|type)\b/ }); Prism.languages.ts = Prism.languages.typescript; From 17094712e61ed5a736aa794a0c6d16a78a4a5e19 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Sat, 28 Oct 2017 11:27:15 -0400 Subject: [PATCH 115/244] Add bash, Django, and YAML syntax highlighting --- assets/javascripts/vendor/prism.js | 171 ++++++++++++++++++++++++++++- 1 file changed, 170 insertions(+), 1 deletion(-) diff --git a/assets/javascripts/vendor/prism.js b/assets/javascripts/vendor/prism.js index 4708065f..3dc04a14 100644 --- a/assets/javascripts/vendor/prism.js +++ b/assets/javascripts/vendor/prism.js @@ -1,4 +1,4 @@ -/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+c+cpp+coffeescript+ruby+d+elixir+erlang+go+java+json+kotlin+lua+nginx+nim+perl+php+python+jsx+crystal+rust+scss+sql+typescript */ +/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+c+bash+cpp+coffeescript+ruby+d+django+elixir+erlang+go+java+json+kotlin+lua+nginx+nim+perl+php+python+jsx+crystal+rust+scss+sql+typescript+yaml */ var _self = (typeof window !== 'undefined') ? window // if in browser : ( @@ -754,6 +754,87 @@ Prism.languages.insertBefore('c', 'string', { delete Prism.languages.c['class-name']; delete Prism.languages.c['boolean']; +(function(Prism) { + var insideString = { + variable: [ + // Arithmetic Environment + { + pattern: /\$?\(\([\s\S]+?\)\)/, + inside: { + // If there is a $ sign at the beginning highlight $(( and )) as variable + variable: [{ + pattern: /(^\$\(\([\s\S]+)\)\)/, + lookbehind: true + }, + /^\$\(\(/ + ], + number: /\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee]-?\d+)?)\b/, + // Operators according to https://www.gnu.org/software/bash/manual/bashref.html#Shell-Arithmetic + operator: /--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/, + // If there is no $ sign at the beginning highlight (( and )) as punctuation + punctuation: /\(\(?|\)\)?|,|;/ + } + }, + // Command Substitution + { + pattern: /\$\([^)]+\)|`[^`]+`/, + inside: { + variable: /^\$\(|^`|\)$|`$/ + } + }, + /\$(?:[\w#?*!@]+|\{[^}]+\})/i + ] + }; + + Prism.languages.bash = { + 'shebang': { + pattern: /^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/, + alias: 'important' + }, + 'comment': { + pattern: /(^|[^"{\\])#.*/, + lookbehind: true + }, + 'string': [ + //Support for Here-Documents https://en.wikipedia.org/wiki/Here_document + { + pattern: /((?:^|[^<])<<\s*)["']?(\w+?)["']?\s*\r?\n(?:[\s\S])*?\r?\n\2/, + lookbehind: true, + greedy: true, + inside: insideString + }, + { + pattern: /(["'])(?:\\[\s\S]|(?!\1)[^\\])*\1/, + greedy: true, + inside: insideString + } + ], + 'variable': insideString.variable, + // Originally based on http://ss64.com/bash/ + 'function': { + pattern: /(^|[\s;|&])(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|[\s;|&])/, + lookbehind: true + }, + 'keyword': { + pattern: /(^|[\s;|&])(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|[\s;|&])/, + lookbehind: true + }, + 'boolean': { + pattern: /(^|[\s;|&])(?:true|false)(?=$|[\s;|&])/, + lookbehind: true + }, + 'operator': /&&?|\|\|?|==?|!=?|<<>|<=?|>=?|=~/, + 'punctuation': /\$?\(\(?|\)\)?|\.\.|[{}[\];]/ + }; + + var inside = insideString.variable[1].inside; + inside['function'] = Prism.languages.bash['function']; + inside.keyword = Prism.languages.bash.keyword; + inside.boolean = Prism.languages.bash.boolean; + inside.operator = Prism.languages.bash.operator; + inside.punctuation = Prism.languages.bash.punctuation; +})(Prism); + Prism.languages.cpp = Prism.languages.extend('c', { 'keyword': /\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/, 'boolean': /\b(?:true|false)\b/, @@ -1046,6 +1127,48 @@ Prism.languages.insertBefore('d', 'function', { alias: 'variable' } }); +// Django/Jinja2 syntax definition for Prism.js syntax highlighter. +// Mostly it works OK but can paint code incorrectly on complex html/template tag combinations. + +var _django_template = { + 'property': { + pattern: /(?:{{|{%)[\s\S]*?(?:%}|}})/g, + greedy: true, + inside: { + 'string': { + pattern: /("|')(?:\\.|(?!\1)[^\\\r\n])*\1/, + greedy: true + }, + 'keyword': /\b(?:\||load|verbatim|widthratio|ssi|firstof|for|url|ifchanged|csrf_token|lorem|ifnotequal|autoescape|now|templatetag|debug|cycle|ifequal|regroup|comment|filter|endfilter|if|spaceless|with|extends|block|include|else|empty|endif|endfor|as|endblock|endautoescape|endverbatim|trans|endtrans|[Tt]rue|[Ff]alse|[Nn]one|in|is|static|macro|endmacro|call|endcall|set|endset|raw|endraw)\b/, + 'operator' : /[-+=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/, + 'function': /\b(?:_|abs|add|addslashes|attr|batch|callable|capfirst|capitalize|center|count|cut|d|date|default|default_if_none|defined|dictsort|dictsortreversed|divisibleby|e|equalto|escape|escaped|escapejs|even|filesizeformat|first|float|floatformat|force_escape|forceescape|format|get_digit|groupby|indent|int|iriencode|iterable|join|last|length|length_is|linebreaks|linebreaksbr|linenumbers|list|ljust|lower|make_list|map|mapping|number|odd|phone2numeric|pluralize|pprint|random|reject|rejectattr|removetags|replace|reverse|rjust|round|safe|safeseq|sameas|select|selectattr|sequence|slice|slugify|sort|string|stringformat|striptags|sum|time|timesince|timeuntil|title|trim|truncate|truncatechars|truncatechars_html|truncatewords|truncatewords_html|undefined|unordered_list|upper|urlencode|urlize|urlizetrunc|wordcount|wordwrap|xmlattr|yesno)\b/, + 'important': /\b-?\d+(?:\.\d+)?\b/, + 'variable': /\b\w+?\b/, + 'punctuation' : /[[\];(),.:]/ + } + } +}; + +Prism.languages.django = Prism.languages.extend('markup', {'comment': /(?:)/}); +// Updated html tag pattern to allow template tags inside html tags +Prism.languages.django.tag.pattern = /<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^>=]+))?)*\s*\/?>/i; +Prism.languages.insertBefore('django', 'entity', _django_template); +Prism.languages.insertBefore('inside', 'tag', _django_template, Prism.languages.django.tag); + +if (Prism.languages.javascript) { + // Combine js code and template tags painting inside