Skip to content

Vendor jQuery and Lunr.js locally for CSP compliance#169

Merged
alamb merged 1 commit intoapache:productionfrom
vinooganesh:vinooganesh/vendor-jquery
Feb 22, 2026
Merged

Vendor jQuery and Lunr.js locally for CSP compliance#169
alamb merged 1 commit intoapache:productionfrom
vinooganesh:vinooganesh/vendor-jquery

Conversation

@vinooganesh
Copy link
Collaborator

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

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
Copy link
Collaborator

@alamb alamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Image

@@ -0,0 +1,55 @@
{{/*
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.html

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 @@
/**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Collaborator

@alamb alamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, now I see what needs to happen is that we need to merge this other PR to switch:

Thanks @vinooganesh

@vinooganesh
Copy link
Collaborator Author

@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.

@alamb alamb merged commit be3a85b into apache:production Feb 22, 2026
1 check passed
@alamb
Copy link
Collaborator

alamb commented Feb 22, 2026

Thank you @vinooganesh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants