Merge pull request #6079 from influxdata/chore-js-refactor-footer-scripts-modules

Chore: JavaScript: refactor footer scripts modules
chore-js-refactor-footer-scripts-modules
Jason Stirnaman 2025-06-05 09:08:11 -05:00 committed by Jason Stirnaman
parent 47cb2ce617
commit 4973026adf
51 changed files with 19477 additions and 452 deletions

View File

@ -1,4 +1,4 @@
version: 2
version: 2.1
jobs:
build:
docker:
@ -41,7 +41,7 @@ jobs:
- /home/circleci/bin
- run:
name: Hugo Build
command: npx hugo --logLevel info --minify --destination workspace/public
command: npx hugo --config config/production/config.yml --logLevel info --minify --gc --destination workspace/public
- persist_to_workspace:
root: workspace
paths:
@ -68,7 +68,6 @@ jobs:
when: on_success
workflows:
version: 2
build:
jobs:
- build

View File

@ -1679,7 +1679,7 @@ The shortcode takes a regular expression for matching placeholder names.
Use the `code-placeholder-key` shortcode to format the placeholder names in
text that describes the placeholder--for example:
```
```markdown
{{% code-placeholders "DATABASE_NAME|USERNAME|PASSWORD_OR_TOKEN|API_TOKEN|exampleuser@influxdata.com" %}}
```sh
curl --request POST http://localhost:8086/write?db=DATABASE_NAME \
@ -1703,3 +1703,64 @@ InfluxDB API documentation when documentation is deployed.
Redoc generates HTML documentation using the InfluxDB `swagger.yml`.
For more information about generating InfluxDB API documentation, see the
[API Documentation README](https://github.com/influxdata/docs-v2/tree/master/api-docs#readme).
## JavaScript in the documentation UI
The InfluxData documentation UI uses JavaScript with ES6+ syntax and
`assets/js/main.js` as the entry point to import modules from
`assets/js`.
Only `assets/js/main.js` should be imported in HTML files.
`assets/js/main.js` registers components and initializes them on page load.
If you're adding UI functionality that requires JavaScript, follow these steps:
1. In your HTML file, add a `data-component` attribute to the element that
should be initialized by your JavaScript code. For example:
```html
<div data-component="my-component"></div>
```
2. Following the component pattern, create a single-purpose JavaScript module
(`assets/js/components/my-component.js`)
that exports a single function that receives the component element and initializes it.
3. In `assets/js/main.js`, import the module and register the component to ensure
the component is initialized on page load.
### Debugging JavaScript
To debug JavaScript code used in the InfluxData documentation UI:
1. In your JavaScript module, import debug helpers from `assets/js/utils/debug-helpers.js`.
These helpers provide breakpoints and console logging as a workaround for
Hugo's lack of source map support in the asset pipeline.
2. Insert debug statements by calling the helper functions in your code--for example:
```js
import { debugLog, debugBreak, debugInspect } from './utils/debug-helpers.js';
const data = debugInspect(someData, 'Data');
debugLog('Processing data', 'myFunction');
function processData() {
// Add a breakpoint that works with DevTools
debugBreak();
// Your existing code...
}
```
3. Start Hugo in development mode--for example:
```bash
yarn hugo server
```
4. In VS Code, go to Run > Start Debugging, and select the "Debug Docs (console-based)" configuration.
Your system uses the configuration in `launch.json` to launch the site in Chrome
and attach the debugger to the Developer Tools console.
Make sure to remove the debug statements before merging your changes.
The debug helpers are designed to be used in development and should not be used in production.

1
.gitignore vendored
View File

@ -21,6 +21,7 @@ node_modules
test-results.xml
/influxdb3cli-build-scripts/content
.vscode/*
!.vscode/launch.json
.idea
**/config.toml
package-lock.json

View File

@ -3,3 +3,4 @@
**/.svn
**/.hg
**/node_modules
assets/jsconfig.json

18
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,18 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Docs (console-based)",
"type": "chrome",
"request": "launch",
"url": "http://localhost:1313",
"webRoot": "${workspaceFolder}",
"skipFiles": [
"<node_internals>/**"
],
"sourceMaps": false,
"trace": true,
"smartStep": false
}
]
}

View File

@ -1667,7 +1667,7 @@ The shortcode takes a regular expression for matching placeholder names.
Use the `code-placeholder-key` shortcode to format the placeholder names in
text that describes the placeholder--for example:
```
```markdown
{{% code-placeholders "DATABASE_NAME|USERNAME|PASSWORD_OR_TOKEN|API_TOKEN|exampleuser@influxdata.com" %}}
```sh
curl --request POST http://localhost:8086/write?db=DATABASE_NAME \
@ -1691,3 +1691,64 @@ InfluxDB API documentation when documentation is deployed.
Redoc generates HTML documentation using the InfluxDB `swagger.yml`.
For more information about generating InfluxDB API documentation, see the
[API Documentation README](https://github.com/influxdata/docs-v2/tree/master/api-docs#readme).
## JavaScript in the documentation UI
The InfluxData documentation UI uses JavaScript with ES6+ syntax and
`assets/js/main.js` as the entry point to import modules from
`assets/js`.
Only `assets/js/main.js` should be imported in HTML files.
`assets/js/main.js` registers components and initializes them on page load.
If you're adding UI functionality that requires JavaScript, follow these steps:
1. In your HTML file, add a `data-component` attribute to the element that
should be initialized by your JavaScript code. For example:
```html
<div data-component="my-component"></div>
```
2. Following the component pattern, create a single-purpose JavaScript module
(`assets/js/components/my-component.js`)
that exports a single function that receives the component element and initializes it.
3. In `assets/js/main.js`, import the module and register the component to ensure
the component is initialized on page load.
### Debugging JavaScript
To debug JavaScript code used in the InfluxData documentation UI:
1. In your JavaScript module, import debug helpers from `assets/js/utils/debug-helpers.js`.
These helpers provide breakpoints and console logging as a workaround for
Hugo's lack of source map support in the asset pipeline.
2. Insert debug statements by calling the helper functions in your code--for example:
```js
import { debugLog, debugBreak, debugInspect } from './utils/debug-helpers.js';
const data = debugInspect(someData, 'Data');
debugLog('Processing data', 'myFunction');
function processData() {
// Add a breakpoint that works with DevTools
debugBreak();
// Your existing code...
}
```
3. Start Hugo in development mode--for example:
```bash
yarn hugo server
```
4. In VS Code, go to Run > Start Debugging, and select the "Debug Docs (console-based)" configuration.
Your system uses the configuration in `launch.json` to launch the site in Chrome
and attach the debugger to the Developer Tools console.
Make sure to remove the debug statements before merging your changes.
The debug helpers are designed to be used in development and should not be used in production.

View File

@ -0,0 +1,72 @@
// Memoize the mermaid module import
let mermaidPromise = null;
export default function Diagram({ component }) {
// Import mermaid.js module (memoized)
if (!mermaidPromise) {
mermaidPromise = import('mermaid');
}
mermaidPromise.then(({ default: mermaid }) => {
// Configure mermaid with InfluxData theming
mermaid.initialize({
startOnLoad: false, // We'll manually call run()
theme: document.body.classList.contains('dark-theme') ? 'dark' : 'default',
themeVariables: {
fontFamily: 'Proxima Nova',
fontSize: '16px',
lineColor: '#22ADF6',
primaryColor: '#22ADF6',
primaryTextColor: '#545454',
secondaryColor: '#05CE78',
tertiaryColor: '#f4f5f5',
},
securityLevel: 'loose', // Required for interactive diagrams
logLevel: 'error'
});
// Process the specific diagram component
try {
mermaid.run({ nodes: [component] });
} catch (error) {
console.error('Mermaid diagram rendering error:', error);
}
// Store reference to mermaid for theme switching
if (!window.mermaidInstances) {
window.mermaidInstances = new Map();
}
window.mermaidInstances.set(component, mermaid);
}).catch(error => {
console.error('Failed to load Mermaid library:', error);
});
// Listen for theme changes to refresh diagrams
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.attributeName === 'class' &&
document.body.classList.contains('dark-theme') !== window.isDarkTheme) {
window.isDarkTheme = document.body.classList.contains('dark-theme');
// Reload this specific diagram with new theme
if (window.mermaidInstances?.has(component)) {
const mermaid = window.mermaidInstances.get(component);
mermaid.initialize({
theme: window.isDarkTheme ? 'dark' : 'default'
});
mermaid.run({ nodes: [component] });
}
}
});
});
// Watch for theme changes on body element
observer.observe(document.body, { attributes: true });
// Return cleanup function to be called when component is destroyed
return () => {
observer.disconnect();
if (window.mermaidInstances?.has(component)) {
window.mermaidInstances.delete(component);
}
};
}

View File

@ -0,0 +1,180 @@
/**
* DocSearch component for InfluxData documentation
* Handles asynchronous loading and initialization of Algolia DocSearch
*/
const debug = false; // Set to true for debugging output
export default function DocSearch({ component }) {
// Store configuration from component data attributes
const config = {
apiKey: component.getAttribute('data-api-key'),
appId: component.getAttribute('data-app-id'),
indexName: component.getAttribute('data-index-name'),
inputSelector: component.getAttribute('data-input-selector'),
searchTag: component.getAttribute('data-search-tag'),
includeFlux: component.getAttribute('data-include-flux') === 'true',
includeResources:
component.getAttribute('data-include-resources') === 'true',
debug: component.getAttribute('data-debug') === 'true',
};
// Initialize global object to track DocSearch state
window.InfluxDocs = window.InfluxDocs || {};
window.InfluxDocs.search = {
initialized: false,
options: config,
};
// Load DocSearch asynchronously
function loadDocSearch() {
if (debug) {
console.log('Loading DocSearch script...');
}
const script = document.createElement('script');
script.src =
'https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js';
script.async = true;
script.onload = initializeDocSearch;
document.body.appendChild(script);
}
// Initialize DocSearch after script loads
function initializeDocSearch() {
if (debug) {
console.log('Initializing DocSearch...');
}
const multiVersion = ['influxdb'];
// Use object-based lookups instead of conditionals for version and product names
// These can be replaced with data from productData in the future
// Version display name mappings
const versionDisplayNames = {
cloud: 'Cloud (TSM)',
core: 'Core',
enterprise: 'Enterprise',
'cloud-serverless': 'Cloud Serverless',
'cloud-dedicated': 'Cloud Dedicated',
clustered: 'Clustered',
explorer: 'Explorer',
};
// Product display name mappings
const productDisplayNames = {
influxdb: 'InfluxDB',
influxdb3: 'InfluxDB 3',
explorer: 'InfluxDB 3 Explorer',
enterprise_influxdb: 'InfluxDB Enterprise',
flux: 'Flux',
telegraf: 'Telegraf',
chronograf: 'Chronograf',
kapacitor: 'Kapacitor',
platform: 'InfluxData Platform',
resources: 'Additional Resources',
};
// Initialize DocSearch with configuration
window.docsearch({
apiKey: config.apiKey,
appId: config.appId,
indexName: config.indexName,
inputSelector: config.inputSelector,
debug: config.debug,
transformData: function (hits) {
// Format version using object lookup instead of if-else chain
function fmtVersion(version, productKey) {
if (version == null) {
return '';
} else if (versionDisplayNames[version]) {
return versionDisplayNames[version];
} else if (multiVersion.includes(productKey)) {
return version;
} else {
return '';
}
}
hits.map((hit) => {
const pathData = new URL(hit.url).pathname
.split('/')
.filter((n) => n);
const product = productDisplayNames[pathData[0]] || pathData[0];
const version = fmtVersion(pathData[1], pathData[0]);
hit.product = product;
hit.version = version;
hit.hierarchy.lvl0 =
hit.hierarchy.lvl0 +
` <span class=\"search-product-version\">${product} ${version}</span>`;
hit._highlightResult.hierarchy.lvl0.value =
hit._highlightResult.hierarchy.lvl0.value +
` <span class=\"search-product-version\">${product} ${version}</span>`;
});
return hits;
},
algoliaOptions: {
hitsPerPage: 10,
facetFilters: buildFacetFilters(config),
},
autocompleteOptions: {
templates: {
header:
'<div class="search-all-content"><a href="https:\/\/support.influxdata.com" target="_blank">Search all InfluxData content <span class="icon-arrow-up-right"></span></a>',
empty:
'<div class="search-no-results"><p>Not finding what you\'re looking for?</p> <a href="https:\/\/support.influxdata.com" target="_blank">Search all InfluxData content <span class="icon-arrow-up-right"></span></a></div>',
},
},
});
// Mark DocSearch as initialized
window.InfluxDocs.search.initialized = true;
// Dispatch event for other components to know DocSearch is ready
window.dispatchEvent(new CustomEvent('docsearch-initialized'));
}
/**
* Helper function to build facet filters based on config
* - Uses nested arrays for AND conditions
* - Includes space after colon in filter expressions
*/
function buildFacetFilters(config) {
if (!config.searchTag) {
return ['latest:true'];
} else if (config.includeFlux) {
// Return a nested array to match original template structure
// Note the space after each colon
return [
[
'searchTag: ' + config.searchTag,
'flux:true',
'resources: ' + config.includeResources,
],
];
} else {
// Return a nested array to match original template structure
// Note the space after each colon
return [
[
'searchTag: ' + config.searchTag,
'resources: ' + config.includeResources,
],
];
}
}
// Load DocSearch when page is idle or after a slight delay
if ('requestIdleCallback' in window) {
requestIdleCallback(loadDocSearch);
} else {
setTimeout(loadDocSearch, 500);
}
// Return cleanup function
return function cleanup() {
// Clean up any event listeners if needed
if (debug) {
console.log('DocSearch component cleanup');
}
};
}

View File

@ -0,0 +1,6 @@
import SearchInteractions from '../utils/search-interactions';
export default function SidebarSearch({ component }) {
const searchInput = component.querySelector('.sidebar--search-field');
SearchInteractions({ searchInput });
}

View File

@ -1,30 +1,54 @@
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var date = new Date()
var currentTimestamp = date.toISOString().replace(/^(.*)(\.\d+)(Z)/, '$1$3') // 2023-01-01T12:34:56Z
var currentTime = date.toISOString().replace(/(^.*T)(.*)(Z)/, '$2') + '084216' // 12:34:56.000084216
import $ from 'jquery';
function currentDate(offset=0, trimTime=false) {
outputDate = new Date(date)
outputDate.setDate(outputDate.getDate() + offset)
var date = new Date();
var currentTimestamp = date.toISOString().replace(/^(.*)(\.\d+)(Z)/, '$1$3'); // 2023-01-01T12:34:56Z
// Microsecond offset appended to the current time string for formatting purposes
const MICROSECOND_OFFSET = '084216';
var currentTime =
date.toISOString().replace(/(^.*T)(.*)(Z)/, '$2') + MICROSECOND_OFFSET; // 12:34:56.000084216
function currentDate(offset = 0, trimTime = false) {
let outputDate = new Date(date);
outputDate.setDate(outputDate.getDate() + offset);
if (trimTime) {
return outputDate.toISOString().replace(/T.*$/, '') // 2023-01-01
return outputDate.toISOString().replace(/T.*$/, ''); // 2023-01-01
} else {
return outputDate.toISOString().replace(/T.*$/, 'T00:00:00Z') // 2023-01-01T00:00:00Z
return outputDate.toISOString().replace(/T.*$/, 'T00:00:00Z'); // 2023-01-01T00:00:00Z
}
}
function enterpriseEOLDate() {
var inTwoYears = date.setFullYear(date.getFullYear() + 2)
earliestEOL = new Date(inTwoYears)
return `${monthNames[earliestEOL.getMonth()]} ${earliestEOL.getDate()}, ${earliestEOL.getFullYear()}`
const monthNames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
var inTwoYears = new Date(date);
inTwoYears.setFullYear(inTwoYears.getFullYear() + 2);
let earliestEOL = new Date(inTwoYears);
return `${monthNames[earliestEOL.getMonth()]} ${earliestEOL.getDate()}, ${earliestEOL.getFullYear()}`;
}
$('span.current-timestamp').text(currentTimestamp)
$('span.current-time').text(currentTime)
$('span.enterprise-eol-date').text(enterpriseEOLDate)
$('span.current-date').each(function() {
var dayOffset = parseInt($(this).attr("offset"))
var trimTime = $(this).attr("trim-time") === "true"
$(this).text(currentDate(dayOffset, trimTime))
})
function initialize() {
$('span.current-timestamp').text(currentTimestamp);
$('span.current-time').text(currentTime);
$('span.enterprise-eol-date').text(enterpriseEOLDate);
$('span.current-date').each(function () {
var dayOffset = parseInt($(this).attr('offset'));
var trimTime = $(this).attr('trim-time') === 'true';
$(this).text(currentDate(dayOffset, trimTime));
});
}
export { initialize };

View File

@ -2,37 +2,24 @@
This feature is designed to callout new features added to the documentation
CSS is required for the callout bubble to determine look and position, but the
element must have the `callout` class and a unique id.
Callouts are treated as notifications and use the notification cookie API in
assets/js/cookies.js.
Callouts are treated as notifications and use the LocalStorage notification API.
*/
import $ from 'jquery';
import * as LocalStorageAPI from './local-storage.js';
// Get notification ID
function getCalloutID (el) {
function getCalloutID(el) {
return $(el).attr('id');
}
// Hide a callout and update the cookie with the viewed callout
function hideCallout (calloutID) {
if (!window.LocalStorageAPI.notificationIsRead(calloutID)) {
window.LocalStorageAPI.setNotificationAsRead(calloutID, 'callout');
$(`#${calloutID}`).fadeOut(200);
// Show the url feature callouts on page load
export default function FeatureCallout({ component }) {
const calloutID = getCalloutID($(component));
if (!LocalStorageAPI.notificationIsRead(calloutID, 'callout')) {
$(`#${calloutID}.feature-callout`)
.fadeIn(300)
.removeClass('start-position');
}
}
// Show the url feature callouts on page load
$(document).ready(function () {
$('.feature-callout').each(function () {
const calloutID = getCalloutID($(this));
if (!window.LocalStorageAPI.notificationIsRead(calloutID, 'callout')) {
$(`#${calloutID}.feature-callout`)
.fadeIn(300)
.removeClass('start-position');
}
});
});
// Hide the InfluxDB URL selector callout
// $('button.url-trigger, #influxdb-url-selector .close').click(function () {
// hideCallout('influxdb-url-selector');
// });

View File

@ -1,49 +1,148 @@
var tablesElement = $("#flux-group-keys-demo #grouped-tables")
import $ from 'jquery';
// Sample data
let data = [
[
{ _time: "2021-01-01T00:00:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "temp", _value: 110.3 },
{ _time: "2021-01-01T00:01:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "temp", _value: 112.5 },
{ _time: "2021-01-01T00:02:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "temp", _value: 111.9 }
{
_time: '2021-01-01T00:00:00Z',
_measurement: 'example',
loc: 'rm1',
sensorID: 'A123',
_field: 'temp',
_value: 110.3,
},
{
_time: '2021-01-01T00:01:00Z',
_measurement: 'example',
loc: 'rm1',
sensorID: 'A123',
_field: 'temp',
_value: 112.5,
},
{
_time: '2021-01-01T00:02:00Z',
_measurement: 'example',
loc: 'rm1',
sensorID: 'A123',
_field: 'temp',
_value: 111.9,
},
],
[
{ _time: "2021-01-01T00:00:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "hum", _value: 73.4 },
{ _time: "2021-01-01T00:01:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "hum", _value: 73.7 },
{ _time: "2021-01-01T00:02:00Z", _measurement: "example", loc: "rm1", sensorID: "A123", _field: "hum", _value: 75.1 }
{
_time: '2021-01-01T00:00:00Z',
_measurement: 'example',
loc: 'rm1',
sensorID: 'A123',
_field: 'hum',
_value: 73.4,
},
{
_time: '2021-01-01T00:01:00Z',
_measurement: 'example',
loc: 'rm1',
sensorID: 'A123',
_field: 'hum',
_value: 73.7,
},
{
_time: '2021-01-01T00:02:00Z',
_measurement: 'example',
loc: 'rm1',
sensorID: 'A123',
_field: 'hum',
_value: 75.1,
},
],
[
{ _time: "2021-01-01T00:00:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "temp", _value: 108.2 },
{ _time: "2021-01-01T00:01:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "temp", _value: 108.5 },
{ _time: "2021-01-01T00:02:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "temp", _value: 109.6 }
{
_time: '2021-01-01T00:00:00Z',
_measurement: 'example',
loc: 'rm2',
sensorID: 'B456',
_field: 'temp',
_value: 108.2,
},
{
_time: '2021-01-01T00:01:00Z',
_measurement: 'example',
loc: 'rm2',
sensorID: 'B456',
_field: 'temp',
_value: 108.5,
},
{
_time: '2021-01-01T00:02:00Z',
_measurement: 'example',
loc: 'rm2',
sensorID: 'B456',
_field: 'temp',
_value: 109.6,
},
],
[
{ _time: "2021-01-01T00:00:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "hum", _value: 71.8 },
{ _time: "2021-01-01T00:01:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "hum", _value: 72.3 },
{ _time: "2021-01-01T00:02:00Z", _measurement: "example", loc: "rm2", sensorID: "B456", _field: "hum", _value: 72.1 }
]
]
{
_time: '2021-01-01T00:00:00Z',
_measurement: 'example',
loc: 'rm2',
sensorID: 'B456',
_field: 'hum',
_value: 71.8,
},
{
_time: '2021-01-01T00:01:00Z',
_measurement: 'example',
loc: 'rm2',
sensorID: 'B456',
_field: 'hum',
_value: 72.3,
},
{
_time: '2021-01-01T00:02:00Z',
_measurement: 'example',
loc: 'rm2',
sensorID: 'B456',
_field: 'hum',
_value: 72.1,
},
],
];
// Default group key
let groupKey = ["_measurement", "loc", "sensorID", "_field"]
let groupKey = ['_measurement', 'loc', 'sensorID', '_field'];
export default function FluxGroupKeysDemo({ component }) {
$('.column-list label').click(function () {
toggleCheckbox($(this));
groupKey = getChecked(component);
groupData();
buildGroupExample(component);
});
// Group and render tables on load
groupData();
}
// Build a table group (group key and table) using an array of objects
function buildTable(inputData) {
// Build the group key string
function wrapString(column, value) {
var stringColumns = ["_measurement", "loc", "sensorID", "_field"]
var stringColumns = ['_measurement', 'loc', 'sensorID', '_field'];
if (stringColumns.includes(column)) {
return '"' + value + '"'
return '"' + value + '"';
} else {
return value
return value;
}
}
var groupKeyString = "Group key instance = [" + (groupKey.map(column => column + ": " + wrapString(column, (inputData[0])[column])) ).join(", ") + "]";
var groupKeyLabel = document.createElement("p");
groupKeyLabel.className = "table-group-key"
groupKeyLabel.innerHTML = groupKeyString
var groupKeyString =
'Group key instance = [' +
groupKey
.map((column) => column + ': ' + wrapString(column, inputData[0][column]))
.join(', ') +
']';
var groupKeyLabel = document.createElement('p');
groupKeyLabel.className = 'table-group-key';
groupKeyLabel.innerHTML = groupKeyString;
// Extract column headers
var columns = [];
@ -54,56 +153,57 @@ function buildTable(inputData) {
}
}
}
// Create the table element
var table = document.createElement("table");
const table = document.createElement('table');
// Create the table header
for (let i = 0; i < columns.length; i++) {
var header = table.createTHead();
var th = document.createElement("th");
var th = document.createElement('th');
th.innerHTML = columns[i];
if (groupKey.includes(columns[i])) {
th.className = "grouped-by";
th.className = 'grouped-by';
}
header.appendChild(th);
}
// Add inputData to the HTML table
for (let i = 0; i < inputData.length; i++) {
tr = table.insertRow(-1);
let tr = table.insertRow(-1);
for (let j = 0; j < columns.length; j++) {
var td = tr.insertCell(-1);
td.innerHTML = inputData[i][columns[j]];
// Highlight the value if column is part of the group key
if (groupKey.includes(columns[j])) {
td.className = "grouped-by";
td.className = 'grouped-by';
}
}
}
// Create a table group with group key and table
var tableGroup = document.createElement("div");
tableGroup.innerHTML += groupKeyLabel.outerHTML + table.outerHTML
var tableGroup = document.createElement('div');
tableGroup.innerHTML += groupKeyLabel.outerHTML + table.outerHTML;
return tableGroup
return tableGroup;
}
// Clear and rebuild all HTML tables
function buildTables(data) {
existingTables = tablesElement[0]
let tablesElement = $('#flux-group-keys-demo #grouped-tables');
let existingTables = tablesElement[0];
while (existingTables.firstChild) {
existingTables.removeChild(existingTables.firstChild);
}
for (let i = 0; i < data.length; i++) {
var table = buildTable(data[i])
var table = buildTable(data[i]);
tablesElement.append(table);
}
}
// Group data based on the group key and output new tables
function groupData() {
let groupedData = data.flat()
let groupedData = data.flat();
function groupBy(array, f) {
var groups = {};
@ -114,20 +214,19 @@ function groupData() {
});
return Object.keys(groups).map(function (group) {
return groups[group];
})
});
}
groupedData = groupBy(groupedData, function (r) {
return groupKey.map(v => r[v]);
return groupKey.map((v) => r[v]);
});
buildTables(groupedData);
}
// Get selected column names
var checkboxes = $("input[type=checkbox]");
function getChecked() {
function getChecked(component) {
// Get selected column names
var checkboxes = $(component).find('input[type=checkbox]');
var checked = [];
for (var i = 0; i < checkboxes.length; i++) {
var checkbox = checkboxes[i];
@ -141,17 +240,12 @@ function toggleCheckbox(element) {
}
// Build example group function
function buildGroupExample() {
var columnCollection = getChecked().map(i => '<span class=\"s2\">"' + i + '"</span>').join(", ")
$("pre#group-by-example")[0].innerHTML = "data\n <span class='nx'>|></span> group(columns<span class='nx'>:</span> [" + columnCollection + "])";
function buildGroupExample(component) {
var columnCollection = getChecked(component)
.map((i) => '<span class=\"s2\">"' + i + '"</span>')
.join(', ');
$('pre#group-by-example')[0].innerHTML =
"data\n <span class='nx'>|></span> group(columns<span class='nx'>:</span> [" +
columnCollection +
'])';
}
$(".column-list label").click(function () {
toggleCheckbox($(this))
groupKey = getChecked();
groupData();
buildGroupExample();
});
// Group and render tables on load
groupData()

View File

@ -1,22 +0,0 @@
$('.exp-btn').click(function() {
var targetBtnElement = $(this).parent()
$('.exp-btn > p', targetBtnElement).fadeOut(100);
setTimeout(function() {
$('.exp-btn-links', targetBtnElement).fadeIn(200)
$('.exp-btn', targetBtnElement).addClass('open');
$('.close-btn', targetBtnElement).fadeIn(200);
}, 100);
})
$('.close-btn').click(function() {
var targetBtnElement = $(this).parent().parent()
$('.exp-btn-links', targetBtnElement).fadeOut(100)
$('.exp-btn', targetBtnElement).removeClass('open');
$(this).fadeOut(100);
setTimeout(function() {
$('p', targetBtnElement).fadeIn(100);
}, 100);
})
/////////////////////////////// EXPANDING BUTTONS //////////////////////////////

View File

@ -1 +0,0 @@
export * from './main.js';

View File

@ -1,41 +1,58 @@
// Dynamically update keybindings or hotkeys
function getPlatform() {
if (/Mac/.test(navigator.platform)) {
return "osx"
} else if (/Win/.test(navigator.platform)) {
return "win"
} else if (/Linux/.test(navigator.platform)) {
return "linux"
} else {
return "other"
}
import { getPlatform } from './utils/user-agent-platform.js';
import $ from 'jquery';
/**
* Adds OS-specific class to component
* @param {string} osClass - OS-specific class to add
* @param {Object} options - Component options
* @param {jQuery} options.$component - jQuery element reference
*/
function addOSClass(osClass, { $component }) {
$component.addClass(osClass);
}
const platform = getPlatform()
/**
* Updates keybinding display based on detected platform
* @param {Object} options - Component options
* @param {jQuery} options.$component - jQuery element reference
* @param {string} options.platform - Detected platform
*/
function updateKeyBindings({ $component, platform }) {
const osx = $component.data('osx');
const linux = $component.data('linux');
const win = $component.data('win');
function addOSClass(osClass) {
$('.keybinding').addClass(osClass)
}
let keybind;
function updateKeyBindings() {
$('.keybinding').each(function() {
var osx = $(this).data("osx")
var linux = $(this).data("linux")
var win = $(this).data("win")
if (platform === "other") {
if (win != linux) {
var keybind = '<code class="osx">' + osx + '</code> for macOS, <code>' + linux + '</code> for Linux, and <code>' + win + '</code> for Windows';
} else {
var keybind = '<code>' + linux + '</code> for Linux and Windows and <code class="osx">' + osx + '</code> for macOS';
}
if (platform === 'other') {
if (win !== linux) {
keybind =
`<code class="osx">${osx}</code> for macOS, ` +
`<code>${linux}</code> for Linux, ` +
`and <code>${win}</code> for Windows`;
} else {
var keybind = '<code>' + $(this).data(platform) + '</code>'
keybind =
`<code>${linux}</code> for Linux and Windows and ` +
`<code class="osx">${osx}</code> for macOS`;
}
} else {
keybind = `<code>${$component.data(platform)}</code>`;
}
$(this).html(keybind)
})
$component.html(keybind);
}
addOSClass(platform)
updateKeyBindings()
/**
* Initialize and render platform-specific keybindings
* @param {Object} options - Component options
* @param {HTMLElement} options.component - DOM element
* @returns {void}
*/
export default function KeyBinding({ component }) {
// Initialize keybindings
const platform = getPlatform();
const $component = $(component);
addOSClass(platform, { $component });
updateKeyBindings({ $component, platform });
}

View File

@ -3,8 +3,8 @@ function countTag(tag) {
return $(".visible[data-tags*='" + tag + "']").length
}
function getFilterCounts() {
$('#list-filters label').each(function() {
function getFilterCounts($labels) {
$labels.each(function() {
var tagName = $('input', this).attr('name').replace(/[\W/]+/, "-");
var tagCount = countTag(tagName);
$(this).attr('data-count', '(' + tagCount + ')');
@ -16,35 +16,39 @@ function getFilterCounts() {
})
}
// Get initial filter count on page load
getFilterCounts()
export default function ListFilters({ component }) {
const $labels = $(component).find('label');
const $inputs = $(component).find('input');
$("#list-filters input").click(function() {
getFilterCounts($labels);
// List of tags to hide
var tagArray = $("#list-filters input:checkbox:checked").map(function(){
return $(this).attr('name').replace(/[\W]+/, "-");
}).get();
$inputs.click(function() {
// List of tags to restore
var restoreArray = $("#list-filters input:checkbox:not(:checked)").map(function(){
return $(this).attr('name').replace(/[\W]+/, "-");
}).get();
// List of tags to hide
var tagArray = $(component).find("input:checkbox:checked").map(function(){
return $(this).attr('name').replace(/[\W]+/, "-");
}).get();
// Actions for filter select
if ( $(this).is(':checked') ) {
$.each( tagArray, function( index, value ) {
$(".filter-item.visible:not([data-tags~='" + value + "'])").removeClass('visible').fadeOut()
})
} else {
$.each( restoreArray, function( index, value ) {
$(".filter-item:not(.visible)[data-tags~='" + value + "']").addClass('visible').fadeIn()
})
$.each( tagArray, function( index, value ) {
$(".filter-item.visible:not([data-tags~='" + value + "'])").removeClass('visible').hide()
})
}
// List of tags to restore
var restoreArray = $(component).find("input:checkbox:not(:checked)").map(function(){
return $(this).attr('name').replace(/[\W]+/, "-");
}).get();
// Refresh filter count
getFilterCounts()
});
// Actions for filter select
if ( $(this).is(':checked') ) {
$.each( tagArray, function( index, value ) {
$(".filter-item.visible:not([data-tags~='" + value + "'])").removeClass('visible').fadeOut()
})
} else {
$.each( restoreArray, function( index, value ) {
$(".filter-item:not(.visible)[data-tags~='" + value + "']").addClass('visible').fadeIn()
})
$.each( tagArray, function( index, value ) {
$(".filter-item.visible:not([data-tags~='" + value + "'])").removeClass('visible').hide()
})
}
// Refresh filter count
getFilterCounts($labels);
});
}

View File

@ -82,13 +82,16 @@ function getPreferences() {
//////////// MANAGE INFLUXDATA DOCS URLS IN LOCAL STORAGE //////////////////////
////////////////////////////////////////////////////////////////////////////////
const defaultUrls = {};
// Guard against pageParams being null/undefined and safely access nested properties
if (pageParams && pageParams.influxdb_urls) {
Object.entries(pageParams.influxdb_urls).forEach(([product, {providers}]) => {
defaultUrls[product] = providers.filter(provider => provider.name === 'Default')[0]?.regions[0]?.url;
});
Object.entries(pageParams.influxdb_urls).forEach(
([product, { providers }]) => {
defaultUrls[product] =
providers.filter((provider) => provider.name === 'Default')[0]
?.regions[0]?.url || 'https://cloud2.influxdata.com';
}
);
}
export const DEFAULT_STORAGE_URLS = {
@ -177,7 +180,10 @@ const defaultNotificationsObj = {
function getNotifications() {
// Initialize notifications data if it doesn't already exist
if (localStorage.getItem(notificationStorageKey) === null) {
initializeStorageItem('notifications', JSON.stringify(defaultNotificationsObj));
initializeStorageItem(
'notifications',
JSON.stringify(defaultNotificationsObj)
);
}
// Retrieve and parse the notifications data as JSON
@ -221,7 +227,10 @@ function setNotificationAsRead(notificationID, notificationType) {
readNotifications.push(notificationID);
notificationsObj[notificationType + 's'] = readNotifications;
localStorage.setItem(notificationStorageKey, JSON.stringify(notificationsObj));
localStorage.setItem(
notificationStorageKey,
JSON.stringify(notificationsObj)
);
}
// Export functions as a module and make the file backwards compatible for non-module environments until all remaining dependent scripts are ported to modules

View File

@ -3,15 +3,19 @@
// If you need to pass parameters from the calling Hugo page, you can import them here like so:
// import * as pageParams from '@params';
// Import dependencies that we still need to load in the global scope
import $ from 'jquery';
/** Import modules that are not components.
* TODO: Refactor these into single-purpose component modules.
*/
import * as apiLibs from './api-libs.js';
import * as codeControls from './code-controls.js';
import * as contentInteractions from './content-interactions.js';
import * as datetime from './datetime.js';
import { delay } from './helpers.js';
import { InfluxDBUrl } from './influxdb-url.js';
import * as localStorage from './local-storage.js';
import * as localStorage from './local-storage.js';
import * as modals from './modals.js';
import * as notifications from './notifications.js';
import * as pageContext from './page-context.js';
@ -29,8 +33,17 @@ import * as v3Wayfinding from './v3-wayfinding.js';
import AskAITrigger from './ask-ai-trigger.js';
import CodePlaceholder from './code-placeholders.js';
import { CustomTimeTrigger } from './custom-timestamps.js';
import Diagram from './components/diagram.js';
import DocSearch from './components/doc-search.js';
import FeatureCallout from './feature-callouts.js';
import FluxGroupKeysDemo from './flux-group-keys.js';
import FluxInfluxDBVersionsTrigger from './flux-influxdb-versions.js';
import KeyBinding from './keybindings.js';
import ListFilters from './list-filters.js';
import ProductSelector from './version-selector.js';
import ReleaseToc from './release-toc.js';
import { SearchButton } from './search-button.js';
import SidebarSearch from './components/sidebar-search.js';
import { SidebarToggle } from './sidebar-toggle.js';
import Theme from './theme.js';
import ThemeSwitch from './theme-switch.js';
@ -49,8 +62,17 @@ const componentRegistry = {
'ask-ai-trigger': AskAITrigger,
'code-placeholder': CodePlaceholder,
'custom-time-trigger': CustomTimeTrigger,
'diagram': Diagram,
'doc-search': DocSearch,
'feature-callout': FeatureCallout,
'flux-group-keys-demo': FluxGroupKeysDemo,
'flux-influxdb-versions-trigger': FluxInfluxDBVersionsTrigger,
'keybinding': KeyBinding,
'list-filters': ListFilters,
'product-selector': ProductSelector,
'release-toc': ReleaseToc,
'search-button': SearchButton,
'sidebar-search': SidebarSearch,
'sidebar-toggle': SidebarToggle,
'theme': Theme,
'theme-switch': ThemeSwitch
@ -72,6 +94,11 @@ function initGlobals() {
window.influxdatadocs.toggleModal = modals.toggleModal;
window.influxdatadocs.componentRegistry = componentRegistry;
// Re-export jQuery to global namespace for legacy scripts
if (typeof window.jQuery === 'undefined') {
window.jQuery = window.$ = $;
}
return window.influxdatadocs;
}
@ -122,6 +149,7 @@ function initModules() {
apiLibs.initialize();
codeControls.initialize();
contentInteractions.initialize();
datetime.initialize();
InfluxDBUrl();
notifications.initialize();
pageFeedback.initialize();

View File

@ -1,69 +1,59 @@
/////////////////////////// Table of Contents Script ///////////////////////////
/*
* This script is used to generate a table of contents for the
* release notes pages.
*/
* This script is used to generate a table of contents for the
* release notes pages.
*/
export default function ReleaseToc({ component }) {
// Use jQuery filter to get an array of all the *release* h2 elements
const releases = $('h2').filter(
(_i, el) => !el.id.match(/checkpoint-releases/)
);
// Get all h2 elements that are not checkpoint-releases
const releases = Array.from(document.querySelectorAll('h2')).filter(
el => !el.id.match(/checkpoint-releases/)
);
// Extract data about each release from the array of releases
const releaseData = releases.map((_i, el) => ({
name: el.textContent,
id: el.id,
class: el.getAttribute('class'),
date: el.getAttribute('date'),
}));
// Extract data about each release from the array of releases
const releaseData = releases.map(el => ({
name: el.textContent,
id: el.id,
class: el.getAttribute('class'),
date: el.getAttribute('date')
}));
// Use release data to generate a list item for each release
getReleaseItem = (releaseData) => {
var li = document.createElement('li');
if (releaseData.class !== null) {
li.className = releaseData.class;
}
li.innerHTML = `<a href="#${releaseData.id}">${releaseData.name}</a>`;
li.setAttribute('date', releaseData.date);
return li;
};
// Use release data to generate a list item for each release
function getReleaseItem(releaseData) {
const li = document.createElement("li");
if (releaseData.class !== null) {
li.className = releaseData.class;
}
li.innerHTML = `<a href="#${releaseData.id}">${releaseData.name}</a>`;
li.setAttribute('date', releaseData.date);
return li;
}
// Use jQuery each to build the release table of contents
releaseData.each((_i, release) => {
$('#release-toc ul')[0].appendChild(getReleaseItem(release));
});
// Build the release table of contents
const releaseTocUl = document.querySelector('#release-toc ul');
releaseData.forEach(release => {
releaseTocUl.appendChild(getReleaseItem(release));
});
/*
* This script is used to expand the release notes table of contents by the
* number specified in the `show` attribute of `ul.release-list`.
* Once all the release items are visible, the "Show More" button is hidden.
*/
const showMoreBtn = document.querySelector('#release-toc .show-more');
if (showMoreBtn) {
showMoreBtn.addEventListener('click', function () {
/*
* This script is used to expand the release notes table of contents by the
* number specified in the `show` attribute of `ul.release-list`.
* Once all the release items are visible, the "Show More" button is hidden.
*/
$('#release-toc .show-more').click(function () {
const itemHeight = 1.885; // Item height in rem
const releaseNum = releaseData.length;
const maxHeight = releaseNum * itemHeight;
const releaseList = document.getElementById('release-list');
const releaseIncrement = Number(releaseList.getAttribute('show'));
const currentHeightMatch = releaseList.style.height.match(/\d+\.?\d+/);
const currentHeight = currentHeightMatch
? Number(currentHeightMatch[0])
: 0;
const releaseIncrement = Number($('#release-list')[0].getAttribute('show'));
const currentHeight = Number(
$('#release-list')[0].style.height.match(/\d+\.?\d+/)[0]
);
const potentialHeight = currentHeight + releaseIncrement * itemHeight;
const newHeight = potentialHeight > maxHeight ? maxHeight : potentialHeight;
releaseList.style.height = `${newHeight}rem`;
$('#release-list')[0].style.height = `${newHeight}rem`;
if (newHeight >= maxHeight) {
// Simple fade out
showMoreBtn.style.transition = 'opacity 0.1s';
showMoreBtn.style.opacity = 0;
setTimeout(() => {
showMoreBtn.style.display = 'none';
}, 100);
$('#release-toc .show-more').fadeOut(100);
}
});
}

View File

@ -1,10 +0,0 @@
// Fade content wrapper when focusing on search input
$('#algolia-search-input').focus(function() {
$('.content-wrapper').fadeTo(300, .35);
})
// Hide search dropdown when leaving search input
$('#algolia-search-input').blur(function() {
$('.content-wrapper').fadeTo(200, 1);
$('.ds-dropdown-menu').hide();
})

View File

@ -1,20 +1,21 @@
import Theme from './theme.js';
export default function ThemeSwitch({ component }) {
if ( component == undefined) {
if (component === undefined) {
component = document;
}
component.querySelectorAll(`.theme-switch-light`).forEach((button) => {
button.addEventListener('click', function(event) {
component.querySelectorAll('.theme-switch-light').forEach((button) => {
button.addEventListener('click', function (event) {
event.preventDefault();
Theme({ style: 'light-theme' });
Theme({ component, style: 'light-theme' });
});
});
component.querySelectorAll(`.theme-switch-dark`).forEach((button) => {
button.addEventListener('click', function(event) {
component.querySelectorAll('.theme-switch-dark').forEach((button) => {
button.addEventListener('click', function (event) {
event.preventDefault();
Theme({ style: 'dark-theme' });
Theme({ component, style: 'dark-theme' });
});
});
}

View File

@ -0,0 +1,38 @@
/**
* Helper functions for debugging without source maps
* Example usage:
* In your code, you can use these functions like this:
* ```javascript
* import { debugLog, debugBreak, debugInspect } from './debug-helpers.js';
*
* const data = debugInspect(someData, 'Data');
* debugLog('Processing data', 'myFunction');
*
* function processData() {
* // Add a breakpoint that works with DevTools
* debugBreak();
*
* // Your existing code...
* }
* ```
*
* @fileoverview DEVELOPMENT USE ONLY - Functions should not be committed to production
*/
/* eslint-disable no-debugger */
/* eslint-disable-next-line */
// NOTE: These functions are detected by ESLint rules to prevent committing debug code
export function debugLog(message, context = '') {
const contextStr = context ? `[${context}]` : '';
console.log(`DEBUG${contextStr}: ${message}`);
}
export function debugBreak() {
debugger;
}
export function debugInspect(value, label = 'Inspect') {
console.log(`DEBUG[${label}]:`, value);
return value;
}

View File

@ -0,0 +1,107 @@
/**
* Manages search interactions for DocSearch integration
* Uses MutationObserver to watch for dropdown creation
*/
export default function SearchInteractions({ searchInput }) {
const contentWrapper = document.querySelector('.content-wrapper');
let observer = null;
let dropdownObserver = null;
let dropdownMenu = null;
const debug = false; // Set to true for debugging logs
// Fade content wrapper when focusing on search input
function handleFocus() {
contentWrapper.style.opacity = '0.35';
contentWrapper.style.transition = 'opacity 300ms';
}
// Hide search dropdown when leaving search input
function handleBlur(event) {
// Only process blur if not clicking within dropdown
const relatedTarget = event.relatedTarget;
if (
relatedTarget &&
(relatedTarget.closest('.algolia-autocomplete') ||
relatedTarget.closest('.ds-dropdown-menu'))
) {
return;
}
contentWrapper.style.opacity = '1';
contentWrapper.style.transition = 'opacity 200ms';
// Hide dropdown if it exists
if (dropdownMenu) {
dropdownMenu.style.display = 'none';
}
}
// Add event listeners
searchInput.addEventListener('focus', handleFocus);
searchInput.addEventListener('blur', handleBlur);
// Use MutationObserver to detect when dropdown is added to the DOM
observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type === 'childList') {
const newDropdown = document.querySelector(
'.ds-dropdown-menu:not([data-monitored])'
);
if (newDropdown) {
// Save reference to dropdown
dropdownMenu = newDropdown;
newDropdown.setAttribute('data-monitored', 'true');
// Monitor dropdown removal/display changes
dropdownObserver = new MutationObserver((dropdownMutations) => {
for (const dropdownMutation of dropdownMutations) {
if (debug) {
if (
dropdownMutation.type === 'attributes' &&
dropdownMutation.attributeName === 'style'
) {
console.log(
'Dropdown style changed:',
dropdownMenu.style.display
);
}
}
}
});
// Observe changes to dropdown attributes (like style)
dropdownObserver.observe(dropdownMenu, {
attributes: true,
attributeFilter: ['style'],
});
// Add event listeners to keep dropdown open when interacted with
dropdownMenu.addEventListener('mousedown', (e) => {
// Prevent blur on searchInput when clicking in dropdown
e.preventDefault();
});
}
}
}
});
// Start observing the document body for dropdown creation
observer.observe(document.body, {
childList: true,
subtree: true,
});
// Return cleanup function
return function cleanup() {
searchInput.removeEventListener('focus', handleFocus);
searchInput.removeEventListener('blur', handleBlur);
if (observer) {
observer.disconnect();
}
if (dropdownObserver) {
dropdownObserver.disconnect();
}
};
}

View File

@ -0,0 +1,29 @@
/**
* Platform detection utility functions
* Provides methods for detecting user's operating system
*/
/**
* Detects user's operating system using modern techniques
* Falls back to userAgent parsing when newer APIs aren't available
* @returns {string} Operating system identifier ("osx", "win", "linux", or "other")
*/
export function getPlatform() {
// Try to use modern User-Agent Client Hints API first (Chrome 89+, Edge 89+)
if (navigator.userAgentData && navigator.userAgentData.platform) {
const platform = navigator.userAgentData.platform.toLowerCase();
if (platform.includes('mac')) return 'osx';
if (platform.includes('win')) return 'win';
if (platform.includes('linux')) return 'linux';
}
// Fall back to userAgent string parsing
const userAgent = navigator.userAgent.toLowerCase();
if (userAgent.includes('mac') || userAgent.includes('iphone') || userAgent.includes('ipad')) return 'osx';
if (userAgent.includes('win')) return 'win';
if (userAgent.includes('linux') || userAgent.includes('android')) return 'linux';
return 'other';
}

View File

@ -1,19 +1,21 @@
// Select the product dropdown and dropdown items
const productDropdown = document.querySelector("#product-dropdown");
const dropdownItems = document.querySelector("#dropdown-items");
export default function ProductSelector({ component }) {
// Select the product dropdown and dropdown items
const productDropdown = component.querySelector("#product-dropdown");
const dropdownItems = component.querySelector("#dropdown-items");
// Expand the menu on click
if (productDropdown) {
productDropdown.addEventListener("click", function() {
productDropdown.classList.toggle("open");
dropdownItems.classList.toggle("open");
// Expand the menu on click
if (productDropdown) {
productDropdown.addEventListener("click", function() {
productDropdown.classList.toggle("open");
dropdownItems.classList.toggle("open");
});
}
// Close the dropdown by clicking anywhere else
document.addEventListener("click", function(e) {
// Check if the click was outside of the '.product-list' container
if (!e.target.closest('.product-list')) {
dropdownItems.classList.remove("open");
}
});
}
// Close the dropdown by clicking anywhere else
document.addEventListener("click", function(e) {
// Check if the click was outside of the '.product-list' container
if (!e.target.closest('.product-list')) {
dropdownItems.classList.remove("open");
}
});

View File

@ -0,0 +1,18 @@
/*
Datetime Components
----------------------------------------------
*/
.current-timestamp,
.current-date,
.current-time,
.enterprise-eol-date {
color: $current-timestamp-color;
display: inline-block;
font-family: $proxima;
white-space: nowrap;
}
.nowrap {
white-space: nowrap;
}

View File

@ -16,6 +16,10 @@
background: $article-code-bg !important;
font-size: .85em;
font-weight: $medium;
p {
background: $article-bg !important;
}
}
.node {

View File

@ -23,6 +23,7 @@
"layouts/syntax-highlighting",
"layouts/algolia-search-overrides",
"layouts/landing",
"layouts/datetime",
"layouts/error-page",
"layouts/footer-widgets",
"layouts/modals",

View File

@ -203,6 +203,12 @@ $article-btn-text-hover: $g20-white;
$article-nav-icon-bg: $g5-pepper;
$article-nav-acct-bg: $g3-castle;
// Datetime shortcode colors
$current-timestamp-color: $g15-platinum;
$current-date-color: $g15-platinum;
$current-time-color: $g15-platinum;
$enterprise-eol-date-color: $g15-platinum;
// Error Page Colors
$error-page-btn: $b-pool;
$error-page-btn-text: $g20-white;

View File

@ -203,6 +203,12 @@ $article-btn-text-hover: $g20-white !default;
$article-nav-icon-bg: $g6-smoke !default;
$article-nav-acct-bg: $g5-pepper !default;
// Datetime Colors
$current-timestamp-color: $article-text !default;
$current-date-color: $article-text !default;
$current-time-color: $article-text !default;
$enterprise-eol-date-color: $article-text !default;
// Error Page Colors
$error-page-btn: $b-pool !default;
$error-page-btn-text: $g20-white !default;

View File

@ -0,0 +1,40 @@
# Production overrides for CI/CD builds
baseURL: 'https://docs.influxdata.com/'
# Production environment parameters
params:
env: production
environment: production
# Enable minification for production
minify:
disableJS: false
disableCSS: false
disableHTML: false
minifyOutput: true
# Production asset processing
build:
writeStats: false
useResourceCacheWhen: "fallback"
buildOptions:
sourcemap: false
target: "es2015"
# Asset processing configuration
assetDir: "assets"
# Mount assets for production
module:
mounts:
- source: assets
target: assets
- source: node_modules
target: assets/node_modules
# Disable development server settings
server: {}
# Suppress the warning mentioned in the error
ignoreLogs:
- 'warning-goldmark-raw-html'

View File

@ -1,20 +1,106 @@
baseURL: 'http://localhost:1315/'
languageCode: en-us
title: InfluxDB Documentation
server:
port: 1315
# Git history information for lastMod-type functionality
enableGitInfo: true
# Syntax Highlighting
pygmentsCodefences: true
pygmentsUseClasses: true
# Preserve case in article tags
preserveTaxonomyNames: true
# Generate a robots.txt
enableRobotsTXT: true
# Markdown rendering options
blackfriday:
hrefTargetBlank: true
smartDashes: false
# Copy taxonomies from main config
taxonomies:
influxdb/v2/tag: influxdb/v2/tags
influxdb/cloud/tag: influxdb/cloud/tags
influxdb3/cloud-serverless/tag: influxdb/cloud-serverless/tags
influxdb3/cloud-dedicated/tag: influxdb/cloud-dedicated/tags
influxdb3/clustered/tag: influxdb3/clustered/tags
influxdb3/core/tag: influxdb3/core/tags
influxdb3/enterprise/tag: influxdb3/enterprise/tags
flux/v0/tag: flux/v0/tags
markup:
goldmark:
renderer:
unsafe: true
extensions:
linkify: false
parser:
attribute:
block: true
privacy:
googleAnalytics:
anonymizeIP: false
disable: false
respectDoNotTrack: true
useSessionStorage: false
youtube:
disable: false
privacyEnhanced: true
outputFormats:
json:
mediaType: application/json
baseName: pages
isPlainText: true
# Asset processing for testing (disable minification)
build:
writeStats: false
useResourceCacheWhen: "fallback"
noJSConfigInAssets: false
# Asset processing configuration
assetDir: "assets"
module:
mounts:
- source: assets
target: assets
- source: node_modules
target: assets/node_modules
# Override settings for testing
buildFuture: true
# Configure what content is built in testing env
params:
env: testing
environment: testing
buildTestContent: true
# Configure the server for testing
server:
port: 1315
baseURL: 'http://localhost:1315/'
watchChanges: true
disableLiveReload: false
# Keep your shared content exclusions
ignoreFiles:
- "content/shared/.*"
# Ignore specific warning logs
ignoreLogs:
- warning-goldmark-raw-html
- warning-goldmark-raw-html
# Disable minification for testing
minify:
disableJS: true
disableCSS: true
disableHTML: true
minifyOutput: false

View File

@ -1267,3 +1267,106 @@ This is small tab 2.4 content.
{{% /tab-content %}}
{{< /tabs-wrapper >}}
## Group key demo
Used to demonstrate Flux group keys
{{< tabs-wrapper >}}
{{% tabs "small" %}}
[Input](#)
[Output](#)
<span class="tab-view-output">Click to view output</span>
{{% /tabs %}}
{{% tab-content %}}
The following data is output from the last `filter()` and piped forward into `group()`:
> [!Note]
> `_start` and `_stop` columns have been omitted.
{{% flux/group-key "[_measurement=home, room=Kitchen, _field=hum]" true %}}
| _time | _measurement | room | _field | _value |
| :------------------- | :----------- | :---------- | :----- | :----- |
| 2022-01-01T08:00:00Z | home | Kitchen | hum | 35.9 |
| 2022-01-01T09:00:00Z | home | Kitchen | hum | 36.2 |
| 2022-01-01T10:00:00Z | home | Kitchen | hum | 36.1 |
{{% flux/group-key "[_measurement=home, room=Living Room, _field=hum]" true %}}
| _time | _measurement | room | _field | _value |
| :------------------- | :----------- | :---------- | :----- | :----- |
| 2022-01-01T08:00:00Z | home | Living Room | hum | 35.9 |
| 2022-01-01T09:00:00Z | home | Living Room | hum | 35.9 |
| 2022-01-01T10:00:00Z | home | Living Room | hum | 36 |
{{% flux/group-key "[_measurement=home, room=Kitchen, _field=temp]" true %}}
| _time | _measurement | room | _field | _value |
| :------------------- | :----------- | :---------- | :----- | :----- |
| 2022-01-01T08:00:00Z | home | Kitchen | temp | 21 |
| 2022-01-01T09:00:00Z | home | Kitchen | temp | 23 |
| 2022-01-01T10:00:00Z | home | Kitchen | temp | 22.7 |
{{% flux/group-key "[_measurement=home, room=Living Room, _field=temp]" true %}}
| _time | _measurement | room | _field | _value |
| :------------------- | :----------- | :---------- | :----- | :----- |
| 2022-01-01T08:00:00Z | home | Living Room | temp | 21.1 |
| 2022-01-01T09:00:00Z | home | Living Room | temp | 21.4 |
| 2022-01-01T10:00:00Z | home | Living Room | temp | 21.8 |
{{% /tab-content %}}
{{% tab-content %}}
When grouped by `_field`, all rows with the `temp` field will be in one table
and all the rows with the `hum` field will be in another.
`_measurement` and `room` columns no longer affect how rows are grouped.
{{% note %}}
`_start` and `_stop` columns have been omitted.
{{% /note %}}
{{% flux/group-key "[_field=hum]" true %}}
| _time | _measurement | room | _field | _value |
| :------------------- | :----------- | :---------- | :----- | :----- |
| 2022-01-01T08:00:00Z | home | Kitchen | hum | 35.9 |
| 2022-01-01T09:00:00Z | home | Kitchen | hum | 36.2 |
| 2022-01-01T10:00:00Z | home | Kitchen | hum | 36.1 |
| 2022-01-01T08:00:00Z | home | Living Room | hum | 35.9 |
| 2022-01-01T09:00:00Z | home | Living Room | hum | 35.9 |
| 2022-01-01T10:00:00Z | home | Living Room | hum | 36 |
{{% flux/group-key "[_field=temp]" true %}}
| _time | _measurement | room | _field | _value |
| :------------------- | :----------- | :---------- | :----- | :----- |
| 2022-01-01T08:00:00Z | home | Kitchen | temp | 21 |
| 2022-01-01T09:00:00Z | home | Kitchen | temp | 23 |
| 2022-01-01T10:00:00Z | home | Kitchen | temp | 22.7 |
| 2022-01-01T08:00:00Z | home | Living Room | temp | 21.1 |
| 2022-01-01T09:00:00Z | home | Living Room | temp | 21.4 |
| 2022-01-01T10:00:00Z | home | Living Room | temp | 21.8 |
{{% /tab-content %}}
{{< /tabs-wrapper >}}
## datetime/current-timestamp shortcode
### Default usage
{{< datetime/current-timestamp >}}
### Format YYYY-MM-DD HH:mm:ss
{{< datetime/current-timestamp format="YYYY-MM-DD HH:mm:ss" >}}
### Format with UTC timezone
{{< datetime/current-timestamp format="YYYY-MM-DD HH:mm:ss" timezone="UTC" >}}
### Format with America/New_York timezone
{{< datetime/current-timestamp format="YYYY-MM-DD HH:mm:ss" timezone="America/New_York" >}}

View File

@ -66,6 +66,23 @@ cloud:
- name: East US (Virginia)
location: Virginia, USA
url: https://eastus-1.azure.cloud2.influxdata.com
serverless:
product: InfluxDB Cloud
providers:
- name: Amazon Web Services
short_name: AWS
iox: true
regions:
- name: US East (Virginia)
location: Virginia, USA
url: https://us-east-1-1.aws.cloud2.influxdata.com
iox: true
- name: EU Frankfurt
location: Frankfurt, Germany
url: https://eu-central-1-1.aws.cloud2.influxdata.com
iox: true
cloud_dedicated:
providers:
- name: Default

View File

@ -106,6 +106,33 @@ export default [
files: ['assets/js/**/*.js'],
rules: {
// Rules specific to JavaScript in Hugo assets
// Prevent imports from debug-helpers.js
'no-restricted-imports': [
'error',
{
paths: [
{
name: './utils/debug-helpers.js',
message:
'Remove debugging functions before committing. Debug helpers should not be used in production code.',
},
{
name: '/utils/debug-helpers.js',
message:
'Remove debugging functions before committing. Debug helpers should not be used in production code.',
},
],
},
],
// Prevent use of debug functions in production code
'no-restricted-syntax': [
'error',
{
selector: 'CallExpression[callee.name=/^debug(Log|Break|Inspect)$/]',
message:
'Remove debugging functions before committing. Debug helpers should not be used in production code.',
},
],
},
},
{

View File

@ -17,7 +17,26 @@ enableRobotsTXT: true
# Custom staging params
params:
env: staging
environment: staging
server:
disableLiveReload: true
# Staging uses the same asset processing as production
# Enable minification for staging
minify:
disableJS: false
disableCSS: false
disableHTML: false
minifyOutput: true
# Staging asset processing
build:
writeStats: false
useResourceCacheWhen: "always"
buildOptions:
sourcemap: false
target: "es2015"
# Markdown rendering options
blackfriday:

View File

@ -49,21 +49,48 @@ privacy:
youtube:
disable: false
privacyEnhanced: true
outputFormats:
json:
mediaType: application/json
baseName: pages
isPlainText: true
# Asset processing configuration for development
build:
# Ensure Hugo correctly processes JavaScript modules
jsConfig:
nodeEnv: "development"
writeStats: false
useResourceCacheWhen: "fallback"
noJSConfigInAssets: false
# Asset processing configuration
assetDir: "assets"
module:
mounts:
- source: assets
target: assets
- source: node_modules
target: assets/node_modules
target: assets/node_modules
# Development settings
params:
env: development
environment: development
# Configure the server for development
server:
port: 1313
baseURL: 'http://localhost:1313/'
watchChanges: true
disableLiveReload: false
# Ignore specific warning logs
ignoreLogs:
- warning-goldmark-raw-html
# Disable minification for development
minify:
disableJS: true
disableCSS: true
disableHTML: true
minifyOutput: false

18019
hugo_stats.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,7 @@
<div class="home-content">
<div class="section search">
<div class="sidebar--search">
<div class="sidebar--search" data-component="sidebar-search">
<input class="sidebar--search-field"
id="algolia-search-input"
type="text"

View File

@ -13,7 +13,7 @@
{{ $urlCalloutText := $scratch.Get "urlCalloutText" }}
<!-- {{ if or $isOSS $isCloud $isHome }}
<div class="feature-callout start-position" id="callout-url-selector">
<div class="feature-callout start-position" id="callout-url-selector" data-component="feature-callout">
<p>{{ $urlCalloutText }} <a href="#" class="close"><span class="icon-remove"></span></a></p>
</div>
{{ end }} -->

View File

@ -1,18 +1,3 @@
{{ $jquery := resources.Get "js/jquery-3.5.0.min.js" }}
{{ $versionSelector := resources.Get "js/version-selector.js" }}
{{ $searchInteractions := resources.Get "js/search-interactions.js" }}
{{ $listFilters := resources.Get "js/list-filters.js" }}
{{ $featureCallouts := resources.Get "js/feature-callouts.js" }}
{{ $keybindings := resources.Get "js/keybindings.js" }}
{{ $fluxGroupKeys := resources.Get "js/flux-group-keys.js" }}
{{ $dateTime := resources.Get "js/datetime.js" }}
{{ $homepageInteractions := resources.Get "js/home-interactions.js" }}
{{ $releaseTOC := resources.Get "/js/release-toc.js" }}
{{ $footerjs := slice $jquery $versionSelector $searchInteractions $listFilters $featureCallouts $keybindings $homepageInteractions | resources.Concat "js/footer.bundle.js" | resources.Fingerprint }}
{{ $fluxGroupKeyjs := $fluxGroupKeys | resources.Fingerprint }}
{{ $dateTimejs := $dateTime | resources.Fingerprint }}
{{ $releaseTOCjs := $releaseTOC | resources.Fingerprint }}
<!-- Load cloudUrls array -->
<script type="text/javascript">
cloudUrls = [
@ -21,37 +6,3 @@
{{ end -}}
]
</script>
{{ if .Page.HasShortcode "diagram" }}
<!-- Load mermaid.js for diagrams -->
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script>
mermaid.initialize({
startOnLoad: true,
themeVariables: {
fontFamily: "Proxima Nova",
fontSize: '18px',
}
})
</script>
{{ end }}
<!-- Load group key demo JS if when the group key demo shortcode is present -->
{{ if .Page.HasShortcode "flux/group-key-demo" }}
<script type="text/javascript" src="{{ $fluxGroupKeyjs.RelPermalink }}"></script>
{{ end }}
<!-- Load datetime js if when datetime shortcodes are present -->
{{ if or (.Page.HasShortcode "datetime/current-time") (.Page.HasShortcode "datetime/current-timestamp")
(.Page.HasShortcode "datetime/current-date") (.Page.HasShortcode "datetime/enterprise-eol-date") }}
<script type="text/javascript" src="{{ $dateTimejs.RelPermalink }}"></script>
{{ end }}
<!-- Load code release-toc js when release-toc shortcode is present -->
{{ if .Page.HasShortcode "release-toc" }}
<script type="text/javascript" src="{{ $releaseTOCjs.RelPermalink }}"></script>
{{ end }}
<!-- Load footer.js -->
<script type="text/javascript" src="{{ $footerjs.RelPermalink }}"></script>

View File

@ -7,84 +7,15 @@
{{ $includeFlux := and (in $fluxSupported $product) (in $influxdbFluxSupport $version) }}
{{ $includeResources := not (in (slice "cloud-serverless" "cloud-dedicated" "clustered" "core" "enterprise" "explorer") $version) }}
<script src="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"></script>
<script>
var multiVersion = ['influxdb']
docsearch({
apiKey: '501434b53a46a92a7931aecc7c9672e2',
appId: 'WHM9UWMP6M',
indexName: 'influxdata',
inputSelector: '#algolia-search-input',
// Set debug to true if you want to inspect the dropdown
debug: true,
transformData: function (hits) {
function fmtVersion (version, productKey) {
if (version == null) {
return '';
} else if (version === 'cloud') {
return 'Cloud (TSM)';
} else if (version === 'core') {
return 'Core';
} else if (version === 'enterprise') {
return 'Enterprise';
} else if (version === 'explorer') {
return 'Explorer';
} else if (version === 'cloud-serverless') {
return 'Cloud Serverless';
} else if (version === 'cloud-dedicated') {
return 'Cloud Dedicated';
} else if (version === 'clustered') {
return 'Clustered';
} else if (multiVersion.includes(productKey)) {
return version;
} else {
return '';
}
};
productNames = {
influxdb: 'InfluxDB',
influxdb3: 'InfluxDB 3',
enterprise_influxdb: 'InfluxDB Enterprise',
flux: 'Flux',
telegraf: 'Telegraf',
chronograf: 'Chronograf',
kapacitor: 'Kapacitor',
platform: 'InfluxData Platform',
resources: 'Additional Resources',
};
hits.map(hit => {
pathData = new URL(hit.url).pathname.split('/').filter(n => n);
product = productNames[pathData[0]];
version = fmtVersion(pathData[1], pathData[0]);
hit.product = product;
hit.version = version;
hit.hierarchy.lvl0 =
hit.hierarchy.lvl0 +
` <span class=\"search-product-version\">${product} ${version}</span>`;
hit._highlightResult.hierarchy.lvl0.value =
hit._highlightResult.hierarchy.lvl0.value +
` <span class=\"search-product-version\">${product} ${version}</span>`;
});
return hits;
},
algoliaOptions: {
hitsPerPage: 10,
'facetFilters': [
{{ if or (eq $product "platform") (eq $product "resources") (le (len $productPathData) 1) }}
'latest:true'
{{ else if $includeFlux }}
['searchTag: {{ $product }}-{{ $version }}', 'flux:true', 'resources:{{ $includeResources }}']
{{ else }}
['searchTag: {{ $product }}-{{ $version }}', 'resources:{{ $includeResources }}']
{{ end }}
]
},
autocompleteOptions: {
templates: {
header: '<div class="search-all-content"><a href="https:\/\/support.influxdata.com" target="_blank">Search all InfluxData content <span class="icon-arrow-up-right"></span></a>',
empty: '<div class="search-no-results"><p>Not finding what you\'re looking for?</p> <a href="https:\/\/support.influxdata.com" target="_blank">Search all InfluxData content <span class="icon-arrow-up-right"></span></a></div>'
}
}
});
</script>
<!-- DocSearch Component Container -->
<div
data-component="doc-search"
data-api-key="501434b53a46a92a7931aecc7c9672e2"
data-app-id="WHM9UWMP6M"
data-index-name="influxdata"
data-input-selector="#algolia-search-input"
data-search-tag="{{ $product }}-{{ $version }}"
data-include-flux="{{ $includeFlux }}"
data-include-resources="{{ $includeResources }}"
data-debug="{{ if hugo.IsProduction }}false{{ else }}true{{ end }}"
></div>

View File

@ -5,28 +5,104 @@
<!-- Get site data -->
<!-- Load cloudUrls array -->
{{ $cloudUrls := slice }}
{{- range.Site.Data.influxdb_urls.cloud.providers }}
{{- range.regions }}
{{ $cloudUrls = $cloudUrls | append "{{ safeHTML .url }}" }}
{{- range .Site.Data.influxdb_urls.cloud.providers }}
{{- range .regions }}
{{ $cloudUrls = $cloudUrls | append (safeHTML .url) }}
{{ end -}}
{{ end -}}
{{ $products := .Site.Data.products }}
{{ $influxdb_urls := .Site.Data.influxdb_urls }}
<!-- Build main.js -->
{{ with resources.Get "js/index.js" }}
{{ $opts := dict
"minify" hugo.IsProduction
"sourceMap" (cond hugo.IsProduction "" "external")
"targetPath" "js/main.js"
"params" (dict "product" $product "currentVersion" $currentVersion "isServer" hugo.IsServer "products" $products "influxdb_urls" $influxdb_urls "cloudUrls" $cloudUrls)
}}
{{ with . | js.Build $opts }}
{{ if hugo.IsProduction }}
{{ with . | fingerprint }}
<script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script>
{{ end }}
{{ else }}
<script src="{{ .RelPermalink }}"></script>
{{ $isDevelopmentOrTesting := or (eq .Site.Params.environment "development") (eq .Site.Params.environment "testing") (eq (getenv "HUGO_ENV") "development") (eq (getenv "HUGO_ENV") "testing") (not hugo.IsProduction) }}
{{ if $isDevelopmentOrTesting }}
{{/* Load individual JS files for debugging with ESM format */}}
{{ $sharedParams := dict "product" $product "currentVersion" $currentVersion "isServer" hugo.IsServer "products" $products "influxdb_urls" $influxdb_urls "cloudUrls" $cloudUrls }}
{{/* Load main.js first to ensure proper initialization */}}
{{ $mainJS := resources.Get "js/main.js" }}
{{ if $mainJS }}
{{ $opts := dict
"sourceMap" "external"
"sourcesContent" true
"targetPath" "js/main.js"
"format" "esm"
"bundle" false
"minify" false
"target" "es2017"
"write" true
"params" $sharedParams
}}
{{ $processed := $mainJS | js.Build $opts }}
{{ if $processed }}
<script type="module" src="{{ $processed.RelPermalink }}"></script>
{{ end }}
{{ end }}
{{ end }}
{{/* Load other individual JS files for debugging with error handling */}}
{{ $jsDir := "assets/js" }}
{{ if fileExists $jsDir }}
{{ range $file := (readDir $jsDir) }}
{{ if and (strings.HasSuffix $file.Name ".js") (ne $file.Name "main.js") }}
{{ $jsPath := printf "js/%s" $file.Name }}
{{ $jsRes := resources.Get $jsPath }}
{{ with $jsRes }}
{{ $opts := dict
"sourceMap" ""
"targetPath" $jsPath
"format" "esm"
"bundle" false
"minify" false
"target" "es2015"
"write" true
"params" $sharedParams
}}
{{ $out := . | js.Build $opts }}
{{/* Add descriptive debug comments at the beginning of each file */}}
{{ $debugHeader := printf "// DEBUG MODE: %s\n// Original file: assets/js/%s\n\n" $file.Name $file.Name }}
{{ $modifiedContent := printf "%s%s" $debugHeader $out.Content }}
{{ $out = resources.FromString $jsPath $modifiedContent }}
<script type="module" src="{{ $out.RelPermalink }}"></script>
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ else }}
{{/* Production environment: Use IIFE for better compatibility */}}
{{ $mainJS := resources.Get "js/main.js" }}
{{ if $mainJS }}
{{ $sharedParams := dict "product" $product "currentVersion" $currentVersion "isServer" hugo.IsServer "products" $products "influxdb_urls" $influxdb_urls "cloudUrls" $cloudUrls }}
{{ $opts := dict
"minify" hugo.IsProduction
"sourceMap" ""
"targetPath" "js/main.js"
"params" $sharedParams
"format" "iife"
"target" "es2019"
"splitting" false
"external" (slice "*")
"define" (dict
"process.env.NODE_ENV" "\"production\""
)
}}
{{ $processed := "" }}
{{ with $mainJS }}
{{ $processed = . | js.Build $opts }}
{{ end }}
{{ if $processed }}
{{ if hugo.IsProduction }}
{{ $fingerprinted := $processed | fingerprint }}
{{ if $fingerprinted }}
<script defer src="{{ $fingerprinted.RelPermalink }}" integrity="{{ $fingerprinted.Data.Integrity }}" crossorigin="anonymous"></script>
{{ end }}
{{ else }}
<script defer src="{{ $processed.RelPermalink }}"></script>
{{ end }}
{{ end }}
{{ end }}
{{ end }}

View File

@ -49,7 +49,7 @@
<aside class="sidebar">
{{ partial "sidebar/sidebar-toggle.html" (dict "state" "Close") }}
<div class="search-and-nav-toggle">
<div class="sidebar--search">
<div class="sidebar--search" data-component="sidebar-search">
<input class="sidebar--search-field"
id="algolia-search-input"
type="text"

View File

@ -43,7 +43,7 @@ Identify products by their product path. Dictionary schema:
{{ $templateDefaults := dict "context" . "productInfo" $productInfo "altLinks" $altLinks "pageRoot" $pageRoot "useRootProductLink" $useRootProductLink }}
<div class="product-list">
<div class="product-list" data-component="product-selector">
<div id="product-dropdown">
<p class="selected">{{ index (index $productInfo $pageRoot) 0 | default "Select product" }}</p>
</div>

View File

@ -1,3 +1,3 @@
<div class="mermaid">
<div class="mermaid" data-component="diagram">
{{.Inner}}
</div>

View File

@ -1,4 +1,4 @@
<div id="flux-group-keys-demo">
<div id="flux-group-keys-demo" data-component="flux-group-keys-demo">
<div id="group-by-columns">
<ul class="column-list">
<li>

View File

@ -5,4 +5,4 @@
{{- $mac := .Get "mac" | default $default -}}
{{- $win := .Get "win" | default $default -}}
{{- $linux := .Get "linux" | default $default -}}
<span class="keybinding" data-osx="{{ $mac }}" data-win="{{ $win }}" data-linux="{{ $linux }}"><code>{{ $default }}</code></span>
<span class="keybinding" data-osx="{{ $mac }}" data-win="{{ $win }}" data-linux="{{ $linux }}" data-component="keybinding"><code>{{ $default }}</code></span>

View File

@ -1,6 +1,6 @@
{{ $source := .Get 0 | default "telegraf"}}
<div id="list-filters">
<div id="list-filters" data-component="list-filters">
{{ range ( index .Site.Data.list_filters $source) }}
{{ $numValues := len .values }}

View File

@ -2,7 +2,7 @@
{{- $currentVersion := index $productPathData 1 -}}
{{- $show := .Get "show" | default 12 -}}
<div id="release-toc" class="{{ $currentVersion }}">
<div id="release-toc" class="{{ $currentVersion }}" data-component="release-toc">
<ul id="release-list" style="height: calc({{ $show }} * 1.885rem);" show="{{ $show }}">
<!-- PLACEHOLDER FOR JS-GENERATED LIST ITEMS -->
</ul>

View File

@ -66,8 +66,6 @@
"test:links:api-docs": "node cypress/support/run-e2e-specs.js --spec \"cypress/e2e/content/article-links.cy.js\" /influxdb3/core/api/,/influxdb3/enterprise/api/,/influxdb3/cloud-dedicated/api/,/influxdb3/cloud-dedicated/api/v1/,/influxdb/cloud-dedicated/api/v1/,/influxdb/cloud-dedicated/api/management/,/influxdb3/cloud-dedicated/api/management/",
"test:shortcode-examples": "node cypress/support/run-e2e-specs.js --spec \"cypress/e2e/content/article-links.cy.js\" content/example.md"
},
"main": "assets/js/main.js",
"module": "assets/js/main.js",
"type": "module",
"browserslist": [
"last 2 versions",