Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/_config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
theme: minima
title: "QQL — Qdrant Query Language"
description: "SQL-like query language and CLI for Qdrant vector database — INSERT, SEARCH, hybrid search, reranking, quantization, and more."
url: "https://pavanjava.github.io/qql"
Expand Down
113 changes: 113 additions & 0 deletions docs/_layouts/default.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ page.title }} | QQL Documentation</title>
<meta name="description" content="{{ site.description }}">
<link rel="stylesheet" href="{{ '/assets/css/style.css' | relative_url }}">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="docs/_layouts/default.html"
if [ ! -f "$FILE" ]; then
  echo "Missing file: $FILE"
  exit 1
fi

echo "== File: $FILE =="
nl -ba "$FILE" | sed -n '1,120p'

Repository: pavanjava/qql

Length of output: 158


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="docs/_layouts/default.html"
nl -ba "$FILE" | sed -n '1,120p'

Repository: pavanjava/qql

Length of output: 100


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="docs/_layouts/default.html"
nl -ba "$FILE" | sed -n '1,120p'

Repository: pavanjava/qql

Length of output: 100


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="docs/_layouts/default.html"
if [ ! -f "$FILE" ]; then
  echo "Missing file: $FILE"
  exit 1
fi

nl -ba "$FILE" | sed -n '1,120p'

Repository: pavanjava/qql

Length of output: 101


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="docs/_layouts/default.html"
test -f "$FILE"

echo "== File: $FILE =="
# Show first 120 lines with line numbers (cat -n is more widely available than nl)
cat -n "$FILE" | sed -n '1,120p'

echo "== Lines containing highlight.js (if any) =="
rg -n "highlight\.js" "$FILE" || true

echo "== Lines 1-60 excerpt (verbatim context) =="
sed -n '1,60p' "$FILE"

Repository: pavanjava/qql

Length of output: 7987


🌐 Web query:

cdnjs highlight.js 11.9.0 github-dark.min.css integrity

💡 Result:

The Highlight.js 11.9.0 library is hosted on cdnjs, and you can access the github-dark.min.css file via the following URL: https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css [1]. While Highlight.js provides Subresource Integrity (SRI) digests for its CDN-hosted assets to ensure security [2][3], there is no single, universally managed list that explicitly embeds the SRI hash directly within the library's metadata for every individual style file in the same way it does for the core JavaScript files [3]. To obtain the correct integrity hash for github-dark.min.css, you should generate it directly from the source file at the CDN URL using a tool like the SRI Hash Generator or by running a command such as openssl dgst -sha384 -binary | openssl base64 -A on the downloaded file. Using a hardcoded hash from a third-party source is generally discouraged to avoid potential mismatches if CDN assets are updated or modified. [1][2][3]

Citations:


Add SRI to cdnjs highlight.js assets

docs/_layouts/default.html loads highlight.js CSS/JS from cdnjs at lines 9, 42, and 43 without integrity (SRI) and crossorigin. Add integrity (SHA-384) and crossorigin="anonymous" for each of the exact URLs.

Suggested patch
-  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
+  <link rel="stylesheet"
+        href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css"
+        integrity="<SRI_HASH>"
+        crossorigin="anonymous">
...
-  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
-  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sql.min.js"></script>
+  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"
+          integrity="<SRI_HASH>"
+          crossorigin="anonymous"></script>
+  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sql.min.js"
+          integrity="<SRI_HASH>"
+          crossorigin="anonymous"></script>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/_layouts/default.html` at line 9, Add Subresource Integrity and
crossorigin attributes to the CDN links for highlight.js by adding
integrity="sha384-<SHA384_FOR_CSS>" and crossorigin="anonymous" to the <link>
tag that loads
https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css
and likewise adding integrity="sha384-<SHA384_FOR_JS>" and
crossorigin="anonymous" to each <script> tag that loads
https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js and
https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/javascript.min.js
(use the correct SHA-384 hashes for these exact files); ensure the integrity
values match the exact file contents so browsers can verify them.

</head>
<body>
<div class="app-container">
<aside class="sidebar">
<div class="sidebar-header">
<a href="{{ '/' | relative_url }}" class="brand">QQL</a>
<p class="version">CLI & Language</p>
</div>
<nav class="sidebar-nav">
<ul>
<li class="nav-heading">Documentation</li>
<li><a href="{{ '/getting-started.html' | relative_url }}" class="{% if page.url contains 'getting-started' %}active{% endif %}">Getting Started</a></li>
<li><a href="{{ '/insert.html' | relative_url }}" class="{% if page.url contains 'insert' %}active{% endif %}">INSERT / BULK</a></li>
<li><a href="{{ '/search.html' | relative_url }}" class="{% if page.url contains 'search' %}active{% endif %}">SEARCH / Hybrid</a></li>
<li><a href="{{ '/filters.html' | relative_url }}" class="{% if page.url contains 'filters' %}active{% endif %}">WHERE Filters</a></li>
<li><a href="{{ '/collections.html' | relative_url }}" class="{% if page.url contains 'collections' %}active{% endif %}">Collections</a></li>
<li><a href="{{ '/scripts.html' | relative_url }}" class="{% if page.url contains 'scripts' %}active{% endif %}">Scripts & Dump</a></li>
<li><a href="{{ '/programmatic.html' | relative_url }}" class="{% if page.url contains 'programmatic' %}active{% endif %}">Programmatic API</a></li>
<li><a href="{{ '/reference.html' | relative_url }}" class="{% if page.url contains 'reference' %}active{% endif %}">Reference</a></li>
</ul>
</nav>
<div class="sidebar-footer">
<a href="https://github.com/pavanjava/qql" target="_blank" rel="noopener">GitHub</a>
<a href="https://pypi.org/project/qql-cli/" target="_blank" rel="noopener">PyPI</a>
</div>
</aside>
<main class="main-content">
<div class="content-wrapper">
{{ content }}
</div>
</main>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/sql.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Apply true syntax highlighting
hljs.highlightAll();

document.querySelectorAll('.content-wrapper pre').forEach(pre => {
// Create wrapper
const wrapper = document.createElement('div');
wrapper.className = 'code-wrapper';
pre.parentNode.insertBefore(wrapper, pre);
wrapper.appendChild(pre);

// Create copy button
const btn = document.createElement('button');
btn.className = 'copy-btn';
btn.textContent = 'Copy';

btn.addEventListener('click', () => {
const code = pre.querySelector('code');
const text = code ? code.innerText : pre.innerText;

const markCopied = () => {
btn.textContent = 'Copied!';
btn.classList.add('copied');
setTimeout(() => {
btn.textContent = 'Copy';
btn.classList.remove('copied');
}, 2000);
};

const markFailed = () => {
btn.textContent = 'Copy failed';
btn.classList.add('copy-error');
setTimeout(() => {
btn.textContent = 'Copy';
btn.classList.remove('copy-error');
}, 2000);
};

const fallbackCopy = () => {
const ta = document.createElement('textarea');
ta.value = text;
ta.style.position = 'fixed';
ta.style.opacity = '0';
document.body.appendChild(ta);
ta.select();
try {
const copied = document.execCommand('copy');
if (copied) markCopied();
else markFailed();
} catch (e) {
markFailed();
} finally {
document.body.removeChild(ta);
}
};

if (navigator.clipboard?.writeText) {
navigator.clipboard.writeText(text).then(markCopied).catch(fallbackCopy);
} else {
fallbackCopy();
}
});

wrapper.appendChild(btn);
});
});
</script>
</body>
</html>
Loading
Loading