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: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ To check or apply style, read the relevant pass file(s) and use them as guidance

- **Python SDK functions**: Module-level functions in the Python SDK are listed in the [Global Functions overview](/models/ref/python/functions).
- **`.editorconfig`**: An `.editorconfig` file in the repository root enforces indentation and whitespace automatically. Most editors apply it with no configuration. If yours doesn't support it natively, install the EditorConfig plugin (https://editorconfig.org/#download).
- **Consistent language tab labels**: When an example offers multiple languages — in a `<CodeGroup>` or across `<Tab title="...">` blocks — label every tab with the same canonical name everywhere: `Python`, `TypeScript` (never `Typescript`), `Bash`. In a `<CodeGroup>`, give each fence a lowercase lexer **and** that canonical title (e.g. a `python` fence titled `Python`); never leave a language fence untitled. The reader's **Python/TypeScript** choice carries from page to page via `code-group-language-persist.js` (repo root), which matches those two labels case-insensitively — so inconsistent casing of them silently resets it. Other labels like `Bash` are only for in-page consistency and are intentionally not persisted across pages. Don't add a competing per-page persistence script.

## Working with the repository

Expand Down
183 changes: 183 additions & 0 deletions code-group-language-persist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/**
* code-group-language-persist.js
*
* Remembers the language a reader picks in a code example and re-applies it on
* every page, for BOTH of Mintlify's tab systems:
*
* 1. <CodeGroup> (code-only tabs): Mintlify already persists these in
* localStorage["code"], but CASE-SENSITIVELY by exact label.
* 2. <Tabs>/<Tab title="..."> (content tabs, e.g. Python vs TypeScript on
* /weave/quickstart): these have NO cross-page persistence in Mintlify —
* they reset to the first tab on every page. The URL #slug hash only
* deep-links within a single page and is dropped on navigation.
*
* Content tabs are the dominant language-switch pattern in these docs (hundreds
* of <Tab title="Python">/<Tab title="TypeScript">), so without this the reader
* has to re-pick their language on every page. This script gives both systems
* unified, case-insensitive, cross-page persistence.
*
* How it works:
* - Remember: a capture-phase pointerdown/click listener stores the chosen
* tab's label in localStorage when the label is an SDK language (see
* LANGUAGES — only Python/TypeScript). The whitelist stops both descriptive
* tabs ("Web App", "Summary metrics") and incidental code tabs ("Bash",
* "cURL") from clobbering the saved language.
* - Restore: on load, after hydration, and on SPA route changes (a
* MutationObserver), any tab whose label matches the saved language (compared
* case-insensitively) is selected. Tabs already active are skipped, so this
* coexists with Mintlify's own <CodeGroup> restore without fighting it.
*
* Selection uses a real pointer sequence, not element.click(): Mintlify's tabs
* activate on pointer/mouse-down, and a synthetic click() does not switch them.
*
* Depends only on the ARIA tab contract Mintlify renders (role="tab", with
* data-state="active" for code groups or aria-selected="true" for content
* tabs), so it is resilient to theme class-name churn.
*
* Environment:
* - Loaded globally by Mintlify for every docs page (any .js in the content
* root is injected — see .mintignore). Wrapped in an IIFE.
*/

(function () {
var STORAGE_KEY = 'wandb.docs.codeLanguage';

/**
* The SDK languages whose choice should follow the reader from page to page,
* compared lower-cased. Deliberately limited to Python and TypeScript — the
* two W&B SDK languages and the only genuine cross-page preference.
*
* Incidental code tabs (Bash, shell, cURL, YAML, JSON, …) are intentionally
* NOT listed: persisting them would let a click on, say, a Bash tab overwrite
* the saved Python/TypeScript choice, and a later page whose tabs are only
* Python/TypeScript has no Bash match — so it would silently fall back to its
* first tab, defeating the persistence. Restore is case-insensitive, so the
* canonical labels here cover "python"/"Python"/"TypeScript" alike; short
* aliases (py/ts) are omitted on purpose — storing "ts" would not match a
* "TypeScript" tab and would reintroduce that same fall-back bug.
*/
var LANGUAGES = {
python: 1, typescript: 1
};

/** Read the saved language, tolerant of disabled/throwing localStorage. */
function read() {
try { return localStorage.getItem(STORAGE_KEY); } catch (e) { return null; }
}

/** Persist the chosen language, tolerant of private-mode write failures. */
function write(value) {
try { localStorage.setItem(STORAGE_KEY, value); } catch (e) { /* ignore */ }
}

/**
* Visible label of a tab element.
* @param {Element} tab
* @returns {string}
*/
function labelOf(tab) {
return (tab.textContent || '').trim();
}

/**
* Whether a label is one of the known languages we should remember.
* @param {string} label
* @returns {boolean}
*/
function isLanguage(label) {
return !!LANGUAGES[label.toLowerCase()];
}

/**
* Whether a tab is the currently-selected one in its group. Code groups use
* data-state="active"; content tabs use aria-selected="true".
* @param {Element} tab
* @returns {boolean}
*/
function isActive(tab) {
return tab.getAttribute('data-state') === 'active' ||
tab.getAttribute('aria-selected') === 'true';
}

/**
* Selects a tab the way a real click does. Mintlify's tabs activate on
* pointer/mouse-down, not on a synthetic element.click(), so dispatch a full
* pointer sequence.
* @param {Element} tab
*/
function activate(tab) {
var opts = { bubbles: true, cancelable: true, view: window, button: 0, isPrimary: true };
if (window.PointerEvent) tab.dispatchEvent(new PointerEvent('pointerdown', opts));
tab.dispatchEvent(new MouseEvent('mousedown', opts));
if (window.PointerEvent) tab.dispatchEvent(new PointerEvent('pointerup', opts));
tab.dispatchEvent(new MouseEvent('mouseup', opts));
tab.dispatchEvent(new MouseEvent('click', opts));
}

/**
* Capture-phase selection handler. Records the chosen tab's label when it
* names a language, so the choice survives navigation. Bound to pointerdown
* (when tabs actually select) and click (covers keyboard activation).
* @param {Event} e
*/
function onSelect(e) {
var tab = e.target && e.target.closest ? e.target.closest('[role="tab"]') : null;
if (!tab) return;
var label = labelOf(tab);
if (label && isLanguage(label)) write(label);
}

/**
* Selects the saved language in every group that isn't already on it.
* Self-terminating: tabs already active are skipped, so the synthetic clicks
* we trigger here do not cause an observe/click feedback loop, and we never
* fight Mintlify's own already-applied <CodeGroup> selection.
*/
function restore() {
var want = read();
if (!want) return;
want = want.toLowerCase();
var tabs = document.querySelectorAll('[role="tab"]');
for (var i = 0; i < tabs.length; i++) {
var tab = tabs[i];
if (labelOf(tab).toLowerCase() === want && !isActive(tab)) {
activate(tab);
}
}
}

// Debounce restore() into a single run after a burst of DOM mutations.
var pending = false;
function schedule() {
if (pending) return;
pending = true;
setTimeout(function () { pending = false; restore(); }, 80);
}

function start() {
// Capture phase so we observe the selection around Mintlify's own handling.
document.addEventListener('pointerdown', onSelect, true);
document.addEventListener('click', onSelect, true);

restore();
// Catch tabs that hydrate after first paint.
[300, 800, 1500].forEach(function (ms) { setTimeout(restore, ms); });

// Re-apply whenever new content renders (client-side route changes).
if (document.body) {
new MutationObserver(schedule).observe(document.body, {
childList: true,
subtree: true
});
}

// Re-apply after back/forward (bfcache) restores.
window.addEventListener('pageshow', restore);
}

if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', start);
} else {
start();
}
})();
2 changes: 1 addition & 1 deletion fr/weave/guides/tracking/view-call.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ Utilisez `weave.Markdown` pour personnaliser l’affichage de vos informations d
```
</Tab>

<Tab title="Typescript">
<Tab title="TypeScript">
```plaintext
This feature is not available in the TypeScript SDK yet.
```
Expand Down
2 changes: 1 addition & 1 deletion ja/weave/guides/tracking/view-call.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ W&amp;B Weave で Calls を作成したら、1 つの call を開いて、その
```
</Tab>

<Tab title="Typescript">
<Tab title="TypeScript">
```plaintext
この機能は、TypeScript SDK ではまだ利用できません。
```
Expand Down
2 changes: 1 addition & 1 deletion ko/weave/guides/tracking/view-call.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ W&amp;B Weave에서 Calls를 만든 후에는 특정 Call을 열어 입력, 출
```
</Tab>

<Tab title="Typescript">
<Tab title="TypeScript">
```plaintext
이 기능은 아직 TypeScript SDK에서 사용할 수 없습니다.
```
Expand Down
8 changes: 4 additions & 4 deletions weave/concepts/what-is-weave.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -84,23 +84,23 @@ To get started with Weave:

<CodeGroup>

```Python Python
```python Python
pip install weave
```

```Typescript Typescript
```typescript TypeScript
npm install weave
```
</CodeGroup>
3. In your script, import Weave and initialize a project. Replace `<your-team>` with your W&B team name and `<your-project>` with your W&B project name.

<CodeGroup>
```Python Python
```python Python
import weave
client = weave.init('<your-team>/<your-project>')
```

```TypeScript Typescript
```typescript TypeScript
import * as weave from 'weave';
const client = await weave.init('<your-team>/<your-project>');
```
Expand Down
4 changes: 2 additions & 2 deletions weave/guides/platform/weave-projects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,13 @@ When you open the new project's workspace, the UI offers quickstarts for both W&
To create a Weave project directly from your code, provide a new project path as an argument to `weave.init()`:

<CodeGroup>
```python
```python Python
import weave

weave.init('my-team/my-llm-app')
```

```typescript
```typescript TypeScript
import * as weave from 'weave';

await weave.init('my-team/my-llm-app');
Expand Down
2 changes: 1 addition & 1 deletion weave/guides/tracking/get-call-object.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def my_op():

my_op()
```
```typescript Typescript lines
```typescript TypeScript lines
function myFunction() {
...
}
Expand Down
2 changes: 1 addition & 1 deletion weave/guides/tracking/tracing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ An **Op** is a versioned, tracked function. When you decorate a function with `@
... }
```

```typescript Typescript
```typescript TypeScript
function myFunction() {
...
}
Expand Down
2 changes: 1 addition & 1 deletion weave/guides/tracking/view-call.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ if __name__ == "__main__":
rag_step("Tell me about OpenAI")
```
</Tab>
<Tab title="Typescript">
<Tab title="TypeScript">
```plaintext
This feature is not available in the TypeScript SDK yet.
```
Expand Down
Loading