Vendor jQuery and Lunr.js locally for CSP compliance#169
Vendor jQuery and Lunr.js locally for CSP compliance#169alamb merged 1 commit intoapache:productionfrom
Conversation
Apache's Content Security Policy on parquet.apache.org blocks scripts from external CDNs. Docsy loads jQuery from code.jquery.com and Lunr from unpkg.com, both of which get blocked, breaking all JS on the production site. This vendors both libraries in static/js/ and overrides Docsy's head.html to load them from the site itself. Same versions, just self-hosted. jQuery is still needed — Docsy's base.js and offline-search.js both depend on it (see google/docsy#1436 for their effort to drop it). Part of apache#163
alamb
left a comment
There was a problem hiding this comment.
Thank you @vinooganesh. I reviewed the contents of the inlined files and they look good to me.
However, when I tested this locally, I couldn't figure out how to actually search the docs. Any hints about how to do that?
| @@ -0,0 +1,55 @@ | |||
| {{/* | |||
There was a problem hiding this comment.
I used the following instructions to compare the content of this PR with the template:
Specifically you can see the diff here:
diff -du ~/go/pkg/mod/github.com/google/docsy@v0.12.0/layouts/_partials/head.html layouts/partials/head.html/Users/andrewlamb/go/pkg/mod/github.com/google/docsy@v0.12.0/layouts/_partials/head.html 2026-02-11 07:27:43
+++ layouts/partials/head.html 2026-02-21 14:42:21
@@ -1,3 +1,15 @@
+{{/*
+ Project-level override of Docsy's layouts/_partials/head.html
+
+ Why this file exists:
+ Apache's Content Security Policy (CSP) blocks resources from external CDNs.
+ The upstream Docsy theme loads jQuery from code.jquery.com and Lunr from
+ unpkg.com, both of which are blocked on parquet.apache.org. This override
+ loads vendored copies from static/js/ instead. It also removes the Algolia
+ DocSearch CSS block since we use Lunr offline search.
+
+ See: https://github.com/apache/parquet-site/issues/163
+*/ -}}
{{/* cSpell:ignore docsearch opengraph outputformat */ -}}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
@@ -26,41 +38,18 @@
{{ partial "schema.html" . -}}
{{ partial "twitter_cards.html" . -}}
{{ partialCached "head-css.html" . "head-css-cache-key" -}}
-<script
- src="https://code.jquery.com/jquery-3.7.1.min.js"
- integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g=="
- crossorigin="anonymous"></script>
+<script src="{{ "js/jquery-3.7.1.min.js" | relURL }}"></script>
{{ if .Site.Params.offlineSearch -}}
-<script defer
- src="https://unpkg.com/lunr@2.3.9/lunr.min.js"
- integrity="sha384-203J0SNzyqHby3iU6hzvzltrWi/M41wOP5Gu+BiJMz5nwKykbkUx8Kp7iti0Lpli"
- crossorigin="anonymous"></script>
+<script defer src="{{ "js/lunr-2.3.9.min.js" | relURL }}"></script>
{{ end -}}
{{ if .Site.Params.prism_syntax_highlighting -}}
<link rel="stylesheet" href="{{ "css/prism.css" | relURL }}"/>
{{ end -}}
-{{ template "algolia/head" . -}}
-
{{ partial "hooks/head-end.html" . -}}
{{/* To comply with GDPR, cookie consent scripts places in head-end must execute before Google Analytics is enabled */ -}}
{{ if hugo.IsProduction -}}
{{ partial "google_analytics.html" . -}}
-{{ end -}}
-
-{{ define "algolia/head" -}}
-
-{{ if and .Site.Params.search (isset .Site.Params.search "algolia") -}}
-<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3.8.2"
- integrity="sha512-l7pkV1dOURFyHCeH8I4fK9lCkQKuqhlsTCqRl3zktifDlB8oTUJ+mJPgYkK9kHpUut8j1iPquTv32t6hvTPv3g=="
- crossorigin="anonymous" />
-{{ end -}}
-
-{{ if ne .Site.Params.algolia_docsearch nil -}}
-{{ warnf `Config 'params.algolia_docsearch' is deprecated: use 'params.search.algolia'
- For details, see https://www.docsy.dev/docs/adding-content/search/#algolia-docsearch.` -}}
-{{ end -}}
-
{{ end -}}
andrewlamb@Andrews-MacBook-Pro-3:~/Software/parquet-site$ tkdiff ~/go/pkg/mod/github.com/google/docsy@v0.12.0/layouts/_partials/head.html layouts/partials/head.htmlThere was a problem hiding this comment.
I also computed the Subresource Intrgrity codes https://www.w3.org/TR/sri/
jquery matches
andrewlamb@Andrews-MacBook-Pro-3:~/Software/parquet-site$ echo sha512-$(openssl dgst -sha512 -binary static/js/jquery-3.7.1.min.js | openssl base64 -A)
sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==
And so does lunr
andrewlamb@Andrews-MacBook-Pro-3:~/Software/parquet-site$ echo sha384-$(openssl dgst -sha384 -binary static/js/lunr-2.3.9.min.js | openssl base64 -A)
sha384-203J0SNzyqHby3iU6hzvzltrWi/M41wOP5Gu+BiJMz5nwKykbkUx8Kp7iti0Lpli
| @@ -0,0 +1,2 @@ | |||
| /*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ | |||
There was a problem hiding this comment.
I downloaded the copy of jquery from https://code.jquery.com/jquery-3.7.1.min.js and verified that is the same as committed here (aka the code has not been tampered with):
andrewlamb@Andrews-MacBook-Pro-3:~/Software/parquet-site$ md5sum static/js/jquery-3.7.1.min.js ~/Downloads/jquery-3.7.1.min.js
2c872dbe60f4ba70fb85356113d8b35e static/js/jquery-3.7.1.min.js
2c872dbe60f4ba70fb85356113d8b35e /Users/andrewlamb/Downloads/jquery-3.7.1.min.js| @@ -0,0 +1,6 @@ | |||
| /** | |||
There was a problem hiding this comment.
I verified this is the same as what is currently hosted in https://unpkg.com/lunr@2.3.9/lunr.min.js
What is what is referred to
md5sum ~/Downloads/lunr.min.js static/js/lunr-2.3.9.min.js
4b684389f3179bfb6f7048d14e2da4e9 /Users/andrewlamb/Downloads/lunr.min.js
4b684389f3179bfb6f7048d14e2da4e9 static/js/lunr-2.3.9.min.js
alamb
left a comment
There was a problem hiding this comment.
Actually, now I see what needs to happen is that we need to merge this other PR to switch:
Thanks @vinooganesh
|
@alamb - Yeah, I separated out the two (vendor + enabling the search). Maybe that was more confusing than I intended it to be. But once we've merged this one, we can enable the other one pretty quickly! Apologies for the confusion on this. |
|
Thank you @vinooganesh |
CC @alamb
Apache's CSP on parquet.apache.org blocks scripts from external CDNs. Docsy loads jQuery from code.jquery.com and Lunr from unpkg.com, both of which get blocked, breaking all JS on the production site.
This vendors both libraries in static/js/ and overrides Docsy's head.html to load them from the site itself. Same versions, just self-hosted.
jQuery is still needed (to address @alamb comment from #163) because Docsy's base.js and offline-search.js both depend on it (see google/docsy#1436 for their effort to drop it).
Part of #163