diff --git a/packages/web/docusaurus.config.ts b/packages/web/docusaurus.config.ts index 1c3ac964..89f88a22 100644 --- a/packages/web/docusaurus.config.ts +++ b/packages/web/docusaurus.config.ts @@ -128,8 +128,8 @@ const config: Config = { }, { to: '/status', - label: "⚠️ INCOMPLETE DRAFT ⚠️", - className: "draft-warning", + label: "Status: Draft", + className: "status-indicator", position: "right" }, { diff --git a/packages/web/spec/data/overview.mdx b/packages/web/spec/data/overview.mdx index 5c80d557..3c06afd4 100644 --- a/packages/web/spec/data/overview.mdx +++ b/packages/web/spec/data/overview.mdx @@ -2,6 +2,8 @@ sidebar_position: 1 --- +import StatusBanner from "@site/src/components/StatusBanner"; + # Overview :::tip[Summary] @@ -15,6 +17,10 @@ a consistent way of representing these types. ::: +## Status + + + ## Reading these schemas The **ethdebug/format/data** namespace is not a schema itself, but rather diff --git a/packages/web/spec/info/overview.mdx b/packages/web/spec/info/overview.mdx index 8b7dada5..33fadc09 100644 --- a/packages/web/spec/info/overview.mdx +++ b/packages/web/spec/info/overview.mdx @@ -2,6 +2,8 @@ sidebar_position: 1 --- +import StatusBanner from "@site/src/components/StatusBanner"; + # Overview :::tip[Summary] @@ -37,13 +39,16 @@ This format defines the primary **ethdebug/format/info** schema. JSON values adhering to this schema contain debugging information about a single invocation of a compiler. +## Status + + ## Reading this schema -The **ethdebug/format/info** schema is a standalone schema and does not define -a corresponding namespace. +The **ethdebug/format/info** schema is a root schema that also defines the +**ethdebug/format/info/resources** subschema. -This schema (like all schemas in this format) are specified as +These schemas (like all schemas in this format) are specified as [JSON Schema](https://json-schema.org), draft 2020-12. Please refer to one or more of the following resources in this section, or diff --git a/packages/web/spec/materials/overview.mdx b/packages/web/spec/materials/overview.mdx index 858091a8..a098cba2 100644 --- a/packages/web/spec/materials/overview.mdx +++ b/packages/web/spec/materials/overview.mdx @@ -2,6 +2,8 @@ sidebar_position: 1 --- +import StatusBanner from "@site/src/components/StatusBanner"; + # Overview :::tip[Summary] @@ -20,6 +22,10 @@ sources, e.g. This format defines a namespace of schemas for representing external resources relevant to smart contract debugging. +## Status + + + ## Reading these schemas The **ethdebug/format/materials** namespace is not a schema itself, but rather diff --git a/packages/web/spec/pointer/overview.mdx b/packages/web/spec/pointer/overview.mdx index d8ff1e78..2a67fd63 100644 --- a/packages/web/spec/pointer/overview.mdx +++ b/packages/web/spec/pointer/overview.mdx @@ -2,6 +2,8 @@ sidebar_position: 1 --- +import StatusBanner from "@site/src/components/StatusBanner"; + # Overview :::tip[Summary] @@ -37,6 +39,10 @@ must be read from which location(s). Values in this schema may address a single continuous region of bytes or an aggregation of non-continuous related regions. +## Status + + + ## Reading this schema The **ethdebug/format/pointer** schema is a root schema that composes other diff --git a/packages/web/spec/program/overview.mdx b/packages/web/spec/program/overview.mdx index 4f2adf48..d6365a7a 100644 --- a/packages/web/spec/program/overview.mdx +++ b/packages/web/spec/program/overview.mdx @@ -2,14 +2,9 @@ sidebar_position: 1 --- -# Overview - -:::warning +import StatusBanner from "@site/src/components/StatusBanner"; -This schema and its subschemas remain largely incomplete. Please stay tuned as -work continues here. - -::: +# Overview :::tip[Summary] @@ -58,6 +53,10 @@ machine state at the time of the instruction back into high-level language concepts. This allows debuggers to provide a meaningful representation of program state at any point during execution. +## Status + + + ## Reading this schema The **ethdebug/format/program** schema is a root schema that composes other diff --git a/packages/web/spec/type/overview.mdx b/packages/web/spec/type/overview.mdx index ccaf3957..f737ea3b 100644 --- a/packages/web/spec/type/overview.mdx +++ b/packages/web/spec/type/overview.mdx @@ -6,6 +6,7 @@ import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; import { describeSchema } from "@ethdebug/format"; import CodeBlock from "@theme/CodeBlock"; +import StatusBanner from "@site/src/components/StatusBanner"; # Overview @@ -54,6 +55,10 @@ JSON values that adhere to this schema may (for example) represent a particular fields, a particular `mapping` type from a certain key type to a certain value type, and so on. +## Status + + + ## Reading this schema The **ethdebug/format/type** schema is a root schema that conditionally defers diff --git a/packages/web/src/components/StatusBadge.module.css b/packages/web/src/components/StatusBadge.module.css new file mode 100644 index 00000000..56a388f3 --- /dev/null +++ b/packages/web/src/components/StatusBadge.module.css @@ -0,0 +1,45 @@ +.badge { + display: inline-flex; + align-items: center; + font-weight: 500; + border-radius: 4px; + color: white; + white-space: nowrap; +} + +.link { + text-decoration: none; +} + +.link:hover .badge { + opacity: 0.9; +} + +/* Sizes */ +.small { + padding: 2px 6px; + font-size: 0.7rem; +} + +.medium { + padding: 4px 10px; + font-size: 0.8rem; +} + +.large { + padding: 6px 14px; + font-size: 0.9rem; +} + +/* Status colors */ +.in-design { + background-color: #6366f1; +} + +.implementable { + background-color: #d97706; +} + +.reference-available { + background-color: #059669; +} diff --git a/packages/web/src/components/StatusBadge.tsx b/packages/web/src/components/StatusBadge.tsx new file mode 100644 index 00000000..64831967 --- /dev/null +++ b/packages/web/src/components/StatusBadge.tsx @@ -0,0 +1,40 @@ +import React from "react"; +import Link from "@docusaurus/Link"; +import { + statusLevels, + type StatusLevel, +} from "@site/src/status/status-config"; +import styles from "./StatusBadge.module.css"; + +export interface StatusBadgeProps { + status: StatusLevel; + size?: "small" | "medium" | "large"; + linkToStatus?: boolean; +} + +export default function StatusBadge({ + status, + size = "medium", + linkToStatus = true, +}: StatusBadgeProps): JSX.Element { + const info = statusLevels[status]; + + const badge = ( + + {info.label} + + ); + + if (linkToStatus) { + return ( + + {badge} + + ); + } + + return badge; +} diff --git a/packages/web/src/components/StatusBanner.module.css b/packages/web/src/components/StatusBanner.module.css new file mode 100644 index 00000000..4c6cb08a --- /dev/null +++ b/packages/web/src/components/StatusBanner.module.css @@ -0,0 +1,75 @@ +.banner { + padding: 1rem 1.25rem; + border-radius: 8px; + margin-bottom: 1.5rem; + border-left: 4px solid; +} + +.banner.in-design { + background-color: rgba(99, 102, 241, 0.1); + border-left-color: #6366f1; +} + +.banner.implementable { + background-color: rgba(217, 119, 6, 0.1); + border-left-color: #d97706; +} + +.banner.reference-available { + background-color: rgba(5, 150, 105, 0.1); + border-left-color: #059669; +} + +.header { + margin-bottom: 0.75rem; +} + +.summary { + margin: 0 0 0.75rem 0; + font-size: 0.95rem; + line-height: 1.5; +} + +.caveats { + margin: 0.75rem 0; + font-size: 0.9rem; +} + +.caveats ul { + margin: 0.25rem 0 0 1.25rem; + padding: 0; +} + +.caveats li { + margin: 0.25rem 0; +} + +.note { + margin: 0.75rem 0; + font-size: 0.85rem; + font-style: italic; + opacity: 0.85; +} + +.reference { + margin: 0.5rem 0 0 0; + font-size: 0.9rem; +} + +.learnMore { + margin: 0.5rem 0 0 0; + font-size: 0.85rem; +} + +/* Dark mode adjustments */ +[data-theme="dark"] .banner.in-design { + background-color: rgba(99, 102, 241, 0.15); +} + +[data-theme="dark"] .banner.implementable { + background-color: rgba(217, 119, 6, 0.15); +} + +[data-theme="dark"] .banner.reference-available { + background-color: rgba(5, 150, 105, 0.15); +} diff --git a/packages/web/src/components/StatusBanner.tsx b/packages/web/src/components/StatusBanner.tsx new file mode 100644 index 00000000..b747938f --- /dev/null +++ b/packages/web/src/components/StatusBanner.tsx @@ -0,0 +1,49 @@ +import React from "react"; +import Link from "@docusaurus/Link"; +import { + schemaStatus, + statusLevels, +} from "@site/src/status/status-config"; +import StatusBadge from "./StatusBadge"; +import styles from "./StatusBanner.module.css"; + +export interface StatusBannerProps { + schema: keyof typeof schemaStatus; +} + +export default function StatusBanner({ + schema, +}: StatusBannerProps): JSX.Element { + const info = schemaStatus[schema]; + const levelInfo = statusLevels[info.level]; + + return ( +
+
+ +
+

{info.summary}

+ {info.caveats.length > 0 && ( +
+ Known limitations: +
    + {info.caveats.map((caveat, index) => ( +
  • {caveat}
  • + ))} +
+
+ )} +

{levelInfo.adoptersNote}

+ {info.referenceUrl && ( +

+ + View reference implementation guide → + +

+ )} +

+ Learn more about status levels → +

+
+ ); +} diff --git a/packages/web/src/components/StatusLevelExplainer.module.css b/packages/web/src/components/StatusLevelExplainer.module.css new file mode 100644 index 00000000..26c5111f --- /dev/null +++ b/packages/web/src/components/StatusLevelExplainer.module.css @@ -0,0 +1,70 @@ +.container { + display: flex; + flex-direction: column; + gap: 1rem; + margin: 1.5rem 0; +} + +.level { + display: flex; + gap: 1rem; + padding: 1rem; + border-radius: 8px; + border-left: 4px solid; +} + +.level.in-design { + background-color: rgba(99, 102, 241, 0.08); + border-left-color: #6366f1; +} + +.level.implementable { + background-color: rgba(217, 119, 6, 0.08); + border-left-color: #d97706; +} + +.level.reference-available { + background-color: rgba(5, 150, 105, 0.08); + border-left-color: #059669; +} + +.badge { + flex-shrink: 0; +} + +.content { + flex: 1; +} + +.description { + margin: 0 0 0.5rem 0; + font-size: 0.95rem; + line-height: 1.5; +} + +.adoptersNote { + margin: 0; + font-size: 0.85rem; + opacity: 0.85; +} + +/* Dark mode */ +[data-theme="dark"] .level.in-design { + background-color: rgba(99, 102, 241, 0.12); +} + +[data-theme="dark"] .level.implementable { + background-color: rgba(217, 119, 6, 0.12); +} + +[data-theme="dark"] .level.reference-available { + background-color: rgba(5, 150, 105, 0.12); +} + +/* Responsive */ +@media (max-width: 600px) { + .level { + flex-direction: column; + gap: 0.5rem; + } +} diff --git a/packages/web/src/components/StatusLevelExplainer.tsx b/packages/web/src/components/StatusLevelExplainer.tsx new file mode 100644 index 00000000..787de38e --- /dev/null +++ b/packages/web/src/components/StatusLevelExplainer.tsx @@ -0,0 +1,36 @@ +import React from "react"; +import { + statusLevels, + type StatusLevel, +} from "@site/src/status/status-config"; +import StatusBadge from "./StatusBadge"; +import styles from "./StatusLevelExplainer.module.css"; + +const levelOrder: StatusLevel[] = [ + "in-design", + "implementable", + "reference-available", +]; + +export default function StatusLevelExplainer(): JSX.Element { + return ( +
+ {levelOrder.map((level) => { + const info = statusLevels[level]; + return ( +
+
+ +
+
+

{info.description}

+

+ For implementers: {info.adoptersNote} +

+
+
+ ); + })} +
+ ); +} diff --git a/packages/web/src/components/StatusTable.module.css b/packages/web/src/components/StatusTable.module.css new file mode 100644 index 00000000..f64c856a --- /dev/null +++ b/packages/web/src/components/StatusTable.module.css @@ -0,0 +1,56 @@ +.container { + margin: 1.5rem 0; + overflow-x: auto; +} + +.table { + width: 100%; + border-collapse: collapse; +} + +.table th, +.table td { + padding: 0.75rem 1rem; + text-align: left; + border-bottom: 1px solid var(--ifm-table-border-color); +} + +.table th { + font-weight: 600; + background-color: var(--ifm-table-head-background); +} + +.table tbody tr:hover { + background-color: var(--ifm-table-stripe-background); +} + +.schemaName { + font-family: var(--ifm-font-family-monospace); + font-size: 0.9rem; +} + +.notes { + font-size: 0.9rem; +} + +.caveats { + margin: 0; + padding-left: 1.25rem; +} + +.caveats li { + margin: 0.25rem 0; +} + +.stable { + color: var(--ifm-color-success); + font-style: italic; +} + +/* Responsive */ +@media (max-width: 768px) { + .table th:nth-child(3), + .table td:nth-child(3) { + display: none; + } +} diff --git a/packages/web/src/components/StatusTable.tsx b/packages/web/src/components/StatusTable.tsx new file mode 100644 index 00000000..920de2ef --- /dev/null +++ b/packages/web/src/components/StatusTable.tsx @@ -0,0 +1,71 @@ +import React from "react"; +import Link from "@docusaurus/Link"; +import { schemaStatus } from "@site/src/status/status-config"; +import StatusBadge from "./StatusBadge"; +import styles from "./StatusTable.module.css"; + +const schemaOrder = [ + "pointer", + "type", + "program", + "data", + "materials", + "info", +] as const; + +const schemaNames: Record = { + pointer: "ethdebug/format/pointer", + type: "ethdebug/format/type", + program: "ethdebug/format/program", + data: "ethdebug/format/data", + materials: "ethdebug/format/materials", + info: "ethdebug/format/info", +}; + +export default function StatusTable(): JSX.Element { + return ( +
+ + + + + + + + + + {schemaOrder.map((key) => { + const info = schemaStatus[key]; + return ( + + + + + + ); + })} + +
SchemaStatusNotes
+ + {schemaNames[key]} + + + + + {info.caveats.length > 0 ? ( +
    + {info.caveats.map((caveat, index) => ( +
  • {caveat}
  • + ))} +
+ ) : ( + Stable + )} +
+
+ ); +} diff --git a/packages/web/src/css/custom.css b/packages/web/src/css/custom.css index ed7727ac..dde7d43f 100644 --- a/packages/web/src/css/custom.css +++ b/packages/web/src/css/custom.css @@ -34,9 +34,25 @@ overflow: auto; } -.navbar .draft-warning { - font-weight: bold; - text-decoration: underline; +.navbar .status-indicator { + display: inline-flex; + align-items: center; + padding: 4px 10px; + border-radius: 4px; + background-color: #d97706; + color: white !important; + font-size: 0.85rem; + font-weight: 500; + text-decoration: none !important; +} + +.navbar .status-indicator:hover { + background-color: #b45309; +} + +[data-theme="dark"] .navbar .status-indicator { + background-color: #f59e0b; + color: #1e1e1e !important; } /* Styling for Playground */ diff --git a/packages/web/src/pages/status.mdx b/packages/web/src/pages/status.mdx index ec4b8461..84afb3fb 100644 --- a/packages/web/src/pages/status.mdx +++ b/packages/web/src/pages/status.mdx @@ -1,13 +1,54 @@ -# Draft status +# Specification Status -:::warning +import StatusLevelExplainer from "@site/src/components/StatusLevelExplainer"; +import StatusTable from "@site/src/components/StatusTable"; -The **ethdebug/format** specification and this site are incomplete drafts. -These efforts are an active work in progress and everything here is subject to -change significantly. +The **ethdebug/format** specification is actively evolving. Different parts +of the specification are at different stages of maturity, and we want to be +transparent about what tooling implementers can rely on today. -Please watch the [GitHub repository](https://github.com/ethdebug/format) or -join our [Matrix.chat](https://matrix.to/#/#ethdebug:matrix.org) to follow -along and contribute. +## Status Levels -::: +We use three status levels to indicate the maturity of each schema section: + + + +## Current status by schema + + + +## Guidance for tooling implementers + +All schemas have TypeScript type definitions available in +[`@ethdebug/format`](https://www.npmjs.com/package/@ethdebug/format), useful +for both debugger and compiler implementations. + +### Ready to implement + +The **pointer** and **type** schemas are mature enough for implementation: + +- **[Pointer schema](/spec/pointer/overview)**: Has a working debugger-side + reference implementation (`@ethdebug/pointers`) with comprehensive + documentation. Start here if you want to build pointer dereferencing into + your debugger. + +- **[Type schema](/spec/type/overview)**: Stable design covering all Solidity + types. + +### Early adopters welcome + +The **[program schema](/spec/program/overview)** is under active development. +The core structure (programs, instructions, contexts) is defined and +foundational, but context types for function calls, returns, and reverts are +still being designed. + +If you're interested in helping shape this part of the format, we'd love your +input! However, implementations should expect breaking changes as the design +evolves. + +## Stay informed + +- Watch the [GitHub repository](https://github.com/ethdebug/format) for updates +- Join our [Matrix.chat](https://matrix.to/#/#ethdebug:matrix.org) for + discussions +- Our working group meets bi-weekly on Thursdays at 17:00 Berlin time diff --git a/packages/web/src/status/status-config.ts b/packages/web/src/status/status-config.ts new file mode 100644 index 00000000..0900ffa4 --- /dev/null +++ b/packages/web/src/status/status-config.ts @@ -0,0 +1,139 @@ +/** + * Centralized configuration for schema status information. + * + * This is the single source of truth for maturity levels, caveats, and + * status details across the ethdebug/format specification. + */ + +export type StatusLevel = + | "in-design" + | "implementable" + | "reference-available"; + +export interface StatusLevelInfo { + label: string; + color: string; + description: string; + adoptersNote: string; +} + +export const statusLevels: Record = { + "in-design": { + label: "In Design", + color: "#6366f1", // Indigo + description: + "Actively being developed. Expect significant changes to structure " + + "and semantics.", + adoptersNote: + "Early feedback welcome, but implementations should expect breaking " + + "changes.", + }, + "implementable": { + label: "Implementable", + color: "#d97706", // Amber + description: + "Stable enough to build against. Minor changes possible but core " + + "design is settled.", + adoptersNote: + "Tooling can implement against this schema with reasonable confidence.", + }, + "reference-available": { + label: "Reference Available", + color: "#059669", // Green + description: + "Stable schema with a working reference implementation available " + + "(debugger-side and/or compiler-side).", + adoptersNote: + "Reference implementation demonstrates correct behavior. Check details " + + "for which side (debugger/compiler) has implementations.", + }, +}; + +export interface SchemaStatusInfo { + level: StatusLevel; + summary: string; + caveats: string[]; + detailsPath: string; + referenceUrl?: string; +} + +export const schemaStatus: Record = { + pointer: { + level: "reference-available", + summary: + "Comprehensive schema for describing data locations in EVM state. " + + "Debugger-side reference implementation available in @ethdebug/pointers.", + caveats: [ + "Pointer templates cannot rename their output region names, limiting " + + "composability for complex scenarios.", + "No compiler-side reference implementation yet.", + ], + detailsPath: "/spec/pointer/overview#status", + referenceUrl: "/docs/implementation-guides/pointers", + }, + type: { + level: "implementable", + summary: + "Complete coverage of Solidity types (elementary and complex).", + caveats: [ + "No support for generic types (e.g., parameterized types).", + ], + detailsPath: "/spec/type/overview#status", + }, + program: { + level: "in-design", + summary: + "Schema for describing high-level program structure and instruction " + + "contexts. Core structure is foundational, but context system is " + + "actively evolving.", + caveats: [ + "Context types for function calls, returns, and reverts are still " + + "being designed.", + "Broader structural changes may occur to accommodate new concerns.", + ], + detailsPath: "/spec/program/overview#status", + }, + data: { + level: "implementable", + summary: + "Foundational schemas for common data representations (hex strings, " + + "unsigned integers, values).", + caveats: [], + detailsPath: "/spec/data/overview#status", + }, + materials: { + level: "implementable", + summary: + "Schemas for compilation metadata, source files, and source ranges.", + caveats: [], + detailsPath: "/spec/materials/overview#status", + }, + info: { + level: "implementable", + summary: + "Intentionally minimal schema for representing compilation-related " + + "debug information.", + caveats: [], + detailsPath: "/spec/info/overview#status", + }, +}; + +/** + * Get the overall project status level (the lowest maturity across all + * primary schemas). + */ +export function getOverallStatus(): StatusLevel { + const primarySchemas = ["pointer", "type", "program"]; + const levels: StatusLevel[] = primarySchemas.map( + (key) => schemaStatus[key].level + ); + + // Return the least mature level + if (levels.includes("in-design")) { + return "in-design"; + } + if (levels.includes("implementable")) { + return "implementable"; + } + return "reference-available"; +} diff --git a/packages/web/src/theme/MDXComponents.tsx b/packages/web/src/theme/MDXComponents.tsx index 3adeae13..a69570c0 100644 --- a/packages/web/src/theme/MDXComponents.tsx +++ b/packages/web/src/theme/MDXComponents.tsx @@ -3,11 +3,13 @@ import isInternalUrl from '@docusaurus/isInternalUrl'; import MDXComponents from '@theme-original/MDXComponents'; import MDXA from "@theme-original/MDXComponents/A"; import type { Props as LinkProps } from "@docusaurus/Link"; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; // Import the FontAwesomeIcon component. -import { library } from '@fortawesome/fontawesome-svg-core'; // Import the library component. -import { fab } from '@fortawesome/free-brands-svg-icons'; // Import all brands icons. -import { fas } from '@fortawesome/free-solid-svg-icons'; // Import all solid icons. +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { library } from '@fortawesome/fontawesome-svg-core'; +import { fab } from '@fortawesome/free-brands-svg-icons'; +import { fas } from '@fortawesome/free-solid-svg-icons'; import IconExternalLink from "@theme-original/Icon/ExternalLink"; +import StatusBadge from "@site/src/components/StatusBadge"; +import StatusBanner from "@site/src/components/StatusBanner"; library.add(fab, fas); // Add all icons to the library so you can use them without importing them individually. @@ -24,5 +26,7 @@ export default { // Re-use the default mapping ...MDXComponents, a: A, - Icon: FontAwesomeIcon, // Make the FontAwesomeIcon component available in MDX as . + Icon: FontAwesomeIcon, + StatusBadge, + StatusBanner, };