Skip to content

Commit 7c630af

Browse files
Merge branch 'master' into ida.adjivon/DOCS-13199-pana-segments-page
2 parents 840ccc0 + 134a109 commit 7c630af

File tree

459 files changed

+17340
-7814
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

459 files changed

+17340
-7814
lines changed

.husky/check-circular-aliases.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def get_staged_files():
5757
"""Get staged markdown files or all files if no staged files."""
5858
try:
5959
result = subprocess.run(
60-
['git', 'diff', '--cached', '--name-only', '--diff-filter=ACM'],
60+
['git', 'diff', '--cached', '--name-only', '--diff-filter=ACMR'],
6161
capture_output=True,
6262
text=True,
6363
check=True
@@ -76,14 +76,20 @@ def check_circular_aliases():
7676
"""Check for circular aliases in markdown files."""
7777
errors = []
7878
staged_files = get_staged_files()
79-
79+
8080
for file_path in staged_files:
81-
if not file_path or not os.path.exists(file_path):
81+
if not file_path:
8282
continue
83-
83+
8484
try:
85-
with open(file_path, 'r', encoding='utf-8') as f:
86-
content = f.read()
85+
# Read the STAGED version of the file, not the working directory version
86+
result = subprocess.run(
87+
['git', 'show', f':{file_path}'],
88+
capture_output=True,
89+
text=True,
90+
check=True
91+
)
92+
content = result.stdout
8793

8894
frontmatter = parse_frontmatter(content)
8995
aliases = frontmatter.get('aliases', [])

.vale.ini

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ Datadog.Trademarks = NO
1010
BlockIgnores = (?s) *({{< ?code-block [^>]* >}}.*?{{< ?/ ?code-block >}}), \
1111
(?s) *({{< ?img [^>]*>}}), \
1212
(?s) *({{< ?(w|/w)hatsnext [^>]*>}}), \
13-
(?s) *({{< ?(n|/n)extlink [^>]*>}})
13+
(?s) *({{< ?(n|/n)extlink [^>]*>}}), \
14+
(?s) *({%\s*if\s+[^%]*%}), \
15+
(?s) *({%\s*partial\s+[^%]*\/%})
1416
TokenIgnores = ({{< ?site-region [^>]* >}})
1517

1618
[*.html]

.vscode/markdoc.code-snippets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"scope": "markdoc",
1111
"prefix": ";;callout",
1212
"body": [
13-
"{% callout src=\"${1:https://www.example.com}\" header=\"${2:Join the Preview!}\" btn_hidden=${3|false,true|} %}",
13+
"{% callout url=\"${1:https://www.example.com}\" header=\"${2:Join the Preview!}\" btn_hidden=${3|false,true|} %}",
1414
"${4:Callout content goes here.}",
1515
"{% /callout %}"
1616
],

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ placeholders: hugpython update_pre_build
161161
hugpython: local/etc/requirements3.txt
162162
@${PY3} -m venv --clear $@ && . $@/bin/activate && $@/bin/pip install --upgrade pip wheel && $@/bin/pip install -r $<;\
163163
if [[ "$(CI_COMMIT_REF_NAME)" != "" ]]; then \
164-
$@/bin/pip install https://binaries.ddbuild.io/dd-source/python/assetlib-0.0.72592276-py3-none-any.whl; \
164+
$@/bin/pip install https://binaries.ddbuild.io/dd-source/python/assetlib-0.0.94619755-py3-none-any.whl; \
165165
fi
166166

167167
update_pre_build: hugpython

assets/scripts/components/async-loading.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { updateTOC, buildTOCMap } from './table-of-contents';
22
import initCodeTabs from './codetabs';
33
import { redirectToRegion, hideTOCItems } from '../region-redirects';
44
import { initCopyCode } from './copy-code';
5+
import { initCopyPageButton } from './copy-page-button';
56
import { initializeIntegrations } from './integrations';
67
import { initializeGroupedListings } from './grouped-item-listings';
78
import {updateMainContentAnchors, reloadWistiaVidScripts, gtag, getCookieByName } from '../helpers/helpers';
@@ -260,6 +261,7 @@ function loadPage(newUrl) {
260261
toggleMultiCodeLangNav(pageCodeLang);
261262
hideTOCItems(true)
262263
initCopyCode()
264+
initCopyPageButton()
263265

264266
// Gtag virtual pageview
265267
gtag('config', gaTag, { page_path: pathName });
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
let pageTextLoadingPromise = null;
2+
3+
const pageTextCache = {
4+
mdUrl: null,
5+
text: null
6+
};
7+
8+
export function initCopyPageButton() {
9+
const copyBtn = document.getElementById('page-copy-btn');
10+
11+
if (copyBtn) {
12+
copyBtn.addEventListener('mouseenter', function () {
13+
loadPageText();
14+
});
15+
16+
copyBtn.addEventListener('click', function (e) {
17+
e.preventDefault();
18+
copyPageText();
19+
});
20+
}
21+
}
22+
23+
/**
24+
* Copy the page text to clipboard
25+
* and display a success indicator.
26+
*/
27+
async function copyPageText() {
28+
const text = await loadPageText();
29+
await navigator.clipboard.writeText(text);
30+
31+
displaySuccessFeedback();
32+
}
33+
34+
/**
35+
* Build the URL of the plaintext page
36+
* from the URL of the HTML page.
37+
*/
38+
function getMdUrl() {
39+
const commitRef = document.documentElement.dataset.commitRef || '';
40+
const commitRefLen = commitRef.length ? commitRef.length + 1 : 0;
41+
42+
// Remove branch name from pathname if in preview/staging
43+
let pathname = window.location.pathname;
44+
if (commitRefLen > 0) {
45+
pathname = pathname.slice(commitRefLen);
46+
}
47+
48+
let url = `https://docs.datadoghq.com` + pathname;
49+
if (url.endsWith('/')) {
50+
url = url.slice(0, -1);
51+
}
52+
return url + '.md';
53+
}
54+
55+
/**
56+
* Attempt to load the page's .md URL contents,
57+
* failing over to extracting the text from the DOM.
58+
*/
59+
async function loadPageText() {
60+
const mdUrl = getMdUrl();
61+
62+
// If already cached, return immediately
63+
if (pageTextCache.mdUrl === mdUrl && pageTextCache.text) {
64+
return pageTextCache.text;
65+
}
66+
67+
// If currently loading, wait for the existing promise
68+
if (pageTextLoadingPromise) {
69+
return pageTextLoadingPromise;
70+
}
71+
72+
// Start a new load
73+
pageTextLoadingPromise = (async () => {
74+
try {
75+
const response = await fetch(mdUrl, { credentials: 'omit' });
76+
77+
if (!response.ok) {
78+
throw new Error(`Failed to fetch Markdown: ${response.status}`);
79+
}
80+
81+
const text = await response.text();
82+
pageTextCache.mdUrl = mdUrl;
83+
pageTextCache.text = text;
84+
return text;
85+
} catch (err) {
86+
// Fail over to extracting text from the DOM
87+
const text = extractPageText();
88+
pageTextCache.text = text;
89+
pageTextCache.mdUrl = mdUrl;
90+
return text;
91+
} finally {
92+
pageTextLoadingPromise = null;
93+
}
94+
})();
95+
96+
return pageTextLoadingPromise;
97+
}
98+
99+
/**
100+
* Show "Copied" feedback and a success icon.
101+
*/
102+
function displaySuccessFeedback() {
103+
const copyText = document.getElementById('page-copy-text');
104+
const copiedText = document.getElementById('page-copied-text');
105+
106+
copyText.style.display = 'none';
107+
copiedText.style.display = 'inline';
108+
109+
const beforeIcon = document.querySelector('#page-copy-btn .copy-btn-icon__before');
110+
const afterIcon = document.querySelector('#page-copy-btn .copy-btn-icon__after');
111+
112+
beforeIcon.style.opacity = '0';
113+
afterIcon.style.opacity = '1';
114+
115+
setTimeout(() => {
116+
copyText.style.display = 'inline';
117+
copiedText.style.display = 'none';
118+
beforeIcon.style.opacity = '1';
119+
afterIcon.style.opacity = '0';
120+
}, 3000);
121+
}
122+
123+
/**
124+
* Extract the content of the page from the DOM
125+
* (used as a fallback if fetching the .md file fails).
126+
*/
127+
function extractPageText() {
128+
const mainContent = document.getElementById('mainContent');
129+
if (!mainContent) {
130+
return '';
131+
}
132+
133+
const lines = [];
134+
const walker = document.createTreeWalker(mainContent, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, {
135+
acceptNode: function (node) {
136+
// Skip hidden elements
137+
if (node.nodeType === Node.ELEMENT_NODE) {
138+
const style = window.getComputedStyle(node);
139+
if (style.display === 'none' || style.visibility === 'hidden') {
140+
return NodeFilter.FILTER_REJECT;
141+
}
142+
}
143+
return NodeFilter.FILTER_ACCEPT;
144+
}
145+
});
146+
147+
let currentNode;
148+
let lastAddedNewline = false;
149+
150+
while ((currentNode = walker.nextNode())) {
151+
if (currentNode.nodeType === Node.TEXT_NODE) {
152+
const text = currentNode.textContent.trim();
153+
if (text) {
154+
lines.push(text);
155+
lastAddedNewline = false;
156+
}
157+
} else if (currentNode.nodeType === Node.ELEMENT_NODE) {
158+
const tagName = currentNode.tagName.toLowerCase();
159+
160+
// Handle headings
161+
if (/^h[1-6]$/.test(tagName)) {
162+
if (!lastAddedNewline && lines.length > 0) {
163+
lines.push('\n');
164+
}
165+
const level = parseInt(tagName[1]);
166+
const headingText = currentNode.textContent.trim();
167+
lines.push('\n' + '#'.repeat(level) + ' ' + headingText + '\n\n');
168+
lastAddedNewline = true;
169+
// Skip children since we already got the text
170+
walker.currentNode = currentNode;
171+
continue;
172+
}
173+
174+
// Handle links
175+
if (tagName === 'a' && currentNode.href) {
176+
const linkText = currentNode.textContent.trim();
177+
if (linkText) {
178+
lines.push(`[${linkText}](${currentNode.href})`);
179+
lastAddedNewline = false;
180+
}
181+
// Skip children since we already got the text
182+
walker.currentNode = currentNode;
183+
continue;
184+
}
185+
186+
// Add newlines for block elements
187+
if (['p', 'div', 'li', 'br', 'hr'].includes(tagName)) {
188+
if (!lastAddedNewline && lines.length > 0) {
189+
lines.push('\n');
190+
lastAddedNewline = true;
191+
}
192+
}
193+
}
194+
}
195+
196+
return lines
197+
.join(' ')
198+
.replace(/ +\n/g, '\n')
199+
.replace(/\n{3,}/g, '\n\n')
200+
.trim();
201+
}

0 commit comments

Comments
 (0)