Skip to content
Merged
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/references/style-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ Guidelines:
- Avoid including the sidebar navigation (it changes frequently).
- Always provide descriptive alt text.
- Use Markdown image syntax for content images. Do not use raw `<img>` tags for screenshots or diagrams.
- Use inline image syntax only (`![alt](~/assets/images/{product}/file.png)`). Do not use reference-style image links (`![alt][1]` with a `[1]: ~/assets/images/...` definition): Astro's asset pipeline does not resolve the `~/` alias in reference-style definitions, so the image renders as a broken relative URL.
- Store images in `src/assets/images/{product}/` and reference them with `~/assets/images/{product}/...`. This enables Astro's asset pipeline (optimization, responsive variants, cache-busting). Only use `public/` for assets that need a stable static URL (e.g. OG images, badges, files referenced from non-Astro contexts). Do not use `public/images/` for docs screenshots or diagrams.

```mdx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ description: Rules for image syntax and asset paths in MDX content.

- If a Markdown image uses empty alt text `![](...)` for a non-decorative content image → **suggestion**: add descriptive alt text per the style guide.

- If an added line uses a reference-style image link (`![Alt text][n]` that points to a `[n]: ~/assets/images/...` definition line) → **warning**: convert to inline image syntax `![Alt text](~/assets/images/{product}/file.png)`. Astro's asset pipeline resolves the `~/assets/images/` alias only for inline image syntax; reference-style definitions render as broken page-relative URLs. Exception: reference-style image links inside fenced code blocks or application code examples.

## Examples

Correct:
Expand All @@ -28,3 +30,8 @@ Incorrect:
```mdx
![Precursor mode selector](/images/precursor/precursor-rules.png)
```

```mdx
![Precursor mode selector][1]
[1]: ~/assets/images/precursor/precursor-rules.png
```
13 changes: 13 additions & 0 deletions .flue/evals/mocks/github-repo-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,19 @@ const FIXTURES: Record<string, Record<string, string>> = {
].join("\n"),
},

// Style-guide eval: reference-style image link (unresolved ~/ alias).
"eval-style-ref-img": {
"src/content/docs/cloudflare-challenges/precursor.mdx": [
"---",
"title: Precursor",
"---",
"",
"![Precursor mode selector][1]",
"",
"[1]: ~/assets/images/cloudflare-challenges/precursor-rules.png",
].join("\n"),
},

// Review-validator eval: file with an unhandled promise rejection.
"eval-val-unhandled-promise": {
"src/handler.ts": [
Expand Down
84 changes: 84 additions & 0 deletions .flue/evals/style-guide.eval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const RAW_IMG_SHA = "eval-style-raw-img";
const IMAGES_PATH_SHA = "eval-style-images-path";
const CORRECT_IMG_SHA = "eval-style-correct-img";
const FENCED_IMG_SHA = "eval-style-fenced-img";
const REF_IMG_SHA = "eval-style-ref-img";

describeEval("style-guide reviewer", { harness }, (it) => {
it("flags a full URL for an internal link", async ({ run }) => {
Expand Down Expand Up @@ -260,6 +261,89 @@ describeEval("style-guide reviewer", { harness }, (it) => {
);
});

it("flags a reference-style image link with an unresolved ~/ alias", async ({
run,
}) => {
const result = await run({
pullRequest: PR,
headSha: REF_IMG_SHA,
filename: "src/content/docs/cloudflare-challenges/precursor.mdx",
addedLines: [
{
line: 8,
content: "![Precursor mode selector][1]",
},
{
line: 10,
content:
"[1]: ~/assets/images/cloudflare-challenges/precursor-rules.png",
},
],
});

const findings = (result.output as { findings?: Finding[] })?.findings;
expect(findings).toBeDefined();

const refFinding = (findings ?? []).filter(
(f) =>
f.rule?.toLowerCase().includes("image") ||
f.rule?.toLowerCase().includes("reference") ||
f.rule?.toLowerCase().includes("inline") ||
f.evidence?.includes("[1]"),
);
expect(refFinding.length).toBeGreaterThan(0);
expect(refFinding[0].severity).toBe("warning");

expect(toolCalls(result).map((c) => c.name)).toContain(
"submit_style_guide",
);
});

it("does not flag a reference-style image link inside a fenced code block", async ({
run,
}) => {
const result = await run({
pullRequest: PR,
headSha: HEAD_SHA,
filename: "src/content/docs/workers/example.mdx",
addedLines: [
{
line: 7,
content: "```mdx",
},
{
line: 8,
content: "![Example][1]",
},
{
line: 9,
content: "[1]: ~/assets/images/example/example.png",
},
{
line: 10,
content: "```",
},
],
});

const findings = (result.output as { findings?: Finding[] })?.findings;
expect(findings).toBeDefined();

const imgFindings = (findings ?? []).filter(
(f) =>
f.severity === "warning" &&
(f.rule?.toLowerCase().includes("img") ||
f.rule?.toLowerCase().includes("image") ||
f.rule?.toLowerCase().includes("reference") ||
f.evidence?.includes("[1]")),
);
expect(imgFindings).toHaveLength(0);

expect(toolCalls(result).map((c) => c.name)).toContain(
"submit_style_guide",
);
});

it("passes on correct Markdown image syntax with ~/assets/images/", async ({
run,
}) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ You can find all details on how to [configure][3] a client here.
Click on the editing pane of GraphiQL and add this base query, replacing
`zone-id` with your Cloudflare zone ID:

![Adding a base query in the GraphiQL pane][4]
![Adding a base query in the GraphiQL pane](~/assets/images/analytics/graphiql-base-query.png)

:::note[Note]

Expand All @@ -42,7 +42,7 @@ cursor in the query, in this case on the line below `zones`, and start entering
a value to engage the feature. For example, when you type `firewall`, a popup
menu displays the datasets that return firewall information:

![GraphiQL word completion assistant to query building][5]
![GraphiQL word completion assistant to query building](~/assets/images/analytics/graphiql-word-completion.png)

The text at the bottom of the list displays a short description of the data that
the node returns.
Expand All @@ -56,13 +56,13 @@ Hover your mouse over a field to display a tooltip that describes the dataset.
In this example, hovering over the `firewallEventsAdaptive` node displays this
description:

![Hovering the mouse over a field to display its description][6]
![Hovering the mouse over a field to display its description](~/assets/images/analytics/graphiql-set-up-base-query.png)

To display information about the dataset, including required parameters, select
the dataset name (blue text). The **Documentation Explorer** opens and displays
details about the dataset:

![Documentation Explorer window displaying dataset details][7]
![Documentation Explorer window displaying dataset details](~/assets/images/analytics/graphiql-parameters.png)

Note that the `filter` and `limit` arguments are required, as indicated by the
exclamation mark (`!`) after their type definitions (gold text). In this
Expand All @@ -73,24 +73,24 @@ To browse a list of supported filter fields, select the filter type definition
(gold text) in the Documentation Explorer. In this example, the type is
`ZoneFirewallEventsAdaptiveFilter_InputObject`:

![Browsing GraphiQL filter fields][8]
![Browsing GraphiQL filter fields](~/assets/images/analytics/graphiql-filter-fields.png)

This example query shows the required `filter` and `limit` arguments for
`firewallEventsAdaptive` (as well as for the rest of GraphQL nodes):

![Example of GraphiQL query arguments][9]
![Example of GraphiQL query arguments](~/assets/images/analytics/graphiql-filter-values.png)

## Define the fields used by your query

To browse the fields you can use with your query, hover your cursor over the
dataset name in your query, and in the tooltip that displays, select the data
type definition (gold text):

![Hovering the mouse over a dataset to display available fields][10]
![Hovering the mouse over a dataset to display available fields](~/assets/images/analytics/graphiql-set-up-base-query.png)

**The Documentation Explorer** opens and displays a list of fields:

![Documentation Explorer window displaying list of fields][11]
![Documentation Explorer window displaying list of fields](~/assets/images/analytics/graphiql-return-fields.png)

To add the data fields that you want to read, type an opening brace (`{`) after
the closing parenthesis for the parameters, then start typing the name of a
Expand All @@ -99,13 +99,13 @@ field that you want to fetch. Use word completion to choose a field.
This example query returns the `action`, `datetime`, `clientRequestHTTPHost`,
and `userAgent` fields:

![Example query with return fields][12]
![Example query with return fields](~/assets/images/analytics/graphiql-query-return-field-values.png)

Once you have entered all the fields you want to query, select the **Play**
button to submit the query. The response pane will contain the data fetched from
the configured GraphQL API endpoint:

![GraphiQL response pane][13]
![GraphiQL response pane](~/assets/images/analytics/create-query-fw-data-set-play.png)

## Variable substitution

Expand All @@ -125,32 +125,10 @@ a JSON object that defines your variables.

This example query uses the `zoneTag` query variable to represent the zone ID:

![Example of GraphiQL query variables][14]
![Example of GraphiQL query variables](~/assets/images/analytics/graphiql-query-variables.png)

[1]: /analytics/graphql-api/getting-started/querying-basics/

[2]: https://github.com/graphql/graphiql/tree/main/packages/graphiql#readme

[3]: /analytics/graphql-api/getting-started/authentication/graphql-client-headers/

[4]: ~/assets/images/analytics/graphiql-base-query.png

[5]: ~/assets/images/analytics/graphiql-word-completion.png

[6]: ~/assets/images/analytics/graphiql-set-up-base-query.png

[7]: ~/assets/images/analytics/graphiql-parameters.png

[8]: ~/assets/images/analytics/graphiql-filter-fields.png

[9]: ~/assets/images/analytics/graphiql-filter-values.png

[10]: ~/assets/images/analytics/graphiql-set-up-base-query.png

[11]: ~/assets/images/analytics/graphiql-return-fields.png

[12]: ~/assets/images/analytics/graphiql-query-return-field-values.png

[13]: ~/assets/images/analytics/create-query-fw-data-set-play.png

[14]: ~/assets/images/analytics/graphiql-query-variables.png
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ instructions to explore the schema.
To open the GraphiQL Documentation Explorer, select the **Docs** link in the
header of the response pane:

![Clicking GraphiQL Docs link to open Documentation Explorer][5]
![Clicking GraphiQL Docs link to open Documentation Explorer](~/assets/images/analytics/graphiql-docs-link.png)

The **Documentation Explorer** opens and displays a list of available objects:

![GraphiQL Doc Explorer pane][6]
![GraphiQL Doc Explorer pane](~/assets/images/analytics/graphiql-doc-explorer.png)

Objects in the **Documentation Explorer** use this syntax:

Expand All @@ -47,7 +47,7 @@ Objects in the **Documentation Explorer** use this syntax:
When you first open the **Documentation Explorer** pane, the `mutation` and
`query` root types display:

![Documentation Explorer displaying mutation and query nodes][7]
![Documentation Explorer displaying mutation and query nodes](~/assets/images/analytics/graphiql-doc-explorer-query-mutations.png)

In this example, `query` is the name of a root, and `Query` is the type
definition.
Expand All @@ -61,7 +61,7 @@ For example, select the **Query** type definition. The **Documentation Explorer*
displays the fields that `Query` provides. In this example, the fields are
`cost` and `viewer`:

![Documentation Explorer displaying cost and viewer fields][8]
![Documentation Explorer displaying cost and viewer fields](~/assets/images/analytics/graphiql-doc-explorer-view-cost.png)

To explore the schema, select the names of objects and definitions. You can also
use the search input (magnifying glass icon) and breadcrumb links in the header.
Expand All @@ -72,7 +72,7 @@ Click the type definition of the `viewer` field (gold text) to list its
sub-fields. The `viewer` field provides sub-fields that allow you to query
`accounts` or `zones` data:

![Displaying viewer fields][9]
![Displaying viewer fields](~/assets/images/analytics/graphiql-doc-explorer-viewer-fields.png)

The `accounts` and `zones` nodes take arguments to specify which dataset to
query.
Expand All @@ -86,24 +86,24 @@ argument. To view the fields available to filter, select
To view a list of the datasets available to query, select the **zone** type
definition (gold text):

![Clicking zone type definition][10]
![Clicking zone type definition](~/assets/images/analytics/graphiql-doc-explorer-zones.png)

A list of datasets displays in the **Fields** section, each with list of valid
arguments and a brief description. Arguments that end with an exclamation mark
(`!`) are required.

![Fields section displaying datasets available][11]
![Fields section displaying datasets available](~/assets/images/analytics/graphiql-doc-explorer-zone-fields.png)

Use the search input (magnifying glass icon) to find specific datasets:

![Searching a dataset in the Documentation Explorer][12]
![Searching a dataset in the Documentation Explorer](~/assets/images/analytics/graphiql-doc-explorer-find-firewall.png)

To select a dataset, select its name.

The definition for the dataset displays. This example shows the
`firewallEventsAdaptive` dataset:

![Example of a dataset definition][13]
![Example of a dataset definition](~/assets/images/analytics/graphiql-doc-explorer-firewallevents-definition.png)

## Find the fields available for a dataset

Expand All @@ -113,11 +113,11 @@ definition (gold text).
For example, select the **ZoneFirewallEventsAdaptive** type definition to view
the fields available for the `firewallEventsAdaptive` dataset:

![Clicking type definition to visualize fields available for a dataset][14]
![Clicking type definition to visualize fields available for a dataset](~/assets/images/analytics/graphiql-doc-explorer-firewall-type-definition.png)

The list of fields displays:

![Displaying available fields for a dataset][15]
![Displaying available fields for a dataset](~/assets/images/analytics/graphiql-doc-explorer-firewall-fields.png)

For more information on using GraphiQL, please visit this [guide][16].

Expand All @@ -129,26 +129,4 @@ For more information on using GraphiQL, please visit this [guide][16].

[4]: /analytics/graphql-api/getting-started/authentication/graphql-client-headers/

[5]: ~/assets/images/analytics/graphiql-docs-link.png

[6]: ~/assets/images/analytics/graphiql-doc-explorer.png

[7]: ~/assets/images/analytics/graphiql-doc-explorer-query-mutations.png

[8]: ~/assets/images/analytics/graphiql-doc-explorer-view-cost.png

[9]: ~/assets/images/analytics/graphiql-doc-explorer-viewer-fields.png

[10]: ~/assets/images/analytics/graphiql-doc-explorer-zones.png

[11]: ~/assets/images/analytics/graphiql-doc-explorer-zone-fields.png

[12]: ~/assets/images/analytics/graphiql-doc-explorer-find-firewall.png

[13]: ~/assets/images/analytics/graphiql-doc-explorer-firewallevents-definition.png

[14]: ~/assets/images/analytics/graphiql-doc-explorer-firewall-type-definition.png

[15]: ~/assets/images/analytics/graphiql-doc-explorer-firewall-fields.png

[16]: /analytics/graphql-api/getting-started/compose-graphql-query/