CodeVetter · Repo Unpack · Behavior traces
d3/d3
Three flows matter: importing the library, building and deploying the site, and rendering a doc example. Import resolution stops at the barrel. The build flow is prepublishOnly, then prebuild.sh, then VitePress. Example charts call scale, axis, and selection helpers in a fixed order inside Vue mounted hooks, and the two Mocha tests walk package.json and the docs tree respectively.
- Consumer import trace: the bundler resolves "d3" to package.json exports.default ./src/index.js. Evaluating that module evaluates each export * from "d3-<pkg>" in source order from d3-array through d3-zoom. Named imports such as {select, selectAll} or {mean, median} from "d3-array" are the documented alternatives; they still originate in the dependency, not in this repo.
- Bundle trace: npm's prepublishOnly runs rm -rf dist && rollup -c. Rollup loads rollup.config.js, which readFileSyncs ./LICENSE, filters /^Copyright\s+/, and builds the banner with meta.homepage and meta.version. Input bundle.js exports version from package.json and re-exports src/index.js. nodeResolve plus json plugins run. onwarn drops CIRCULAR_DEPENDENCY. The default export array then writes UMD, ESM, and minified UMD, the last with terser and reserved InternMap and InternSet.
- Deploy trace: on push to main, deploy.yml checks out d3, checks out d3/d3.github.com at build/d3.github.com, setup-node 20, yarn --frozen-lockfile, yarn prepublishOnly (produces dist), yarn docs:build. docs:build runs prebuild.sh (copies into docs/public, including dist/d3.js as d3.v7.js) and then vitepress build docs. configure-pages, upload-pages-artifact of docs/.vitepress/dist, and deploy-pages follow.
- Blank-chart trace in ExampleBlankChart.mounted: construct width 640, height 400, and margins; d3.scaleUtc().domain([2023-01-01, 2024-01-01]).range([marginLeft, width-marginRight]); d3.scaleLinear().domain([0,100]).range([height-marginBottom, marginTop]); d3.create("svg") then attr width and height; append a translated g and .call(d3.axisBottom(x)); append a translated g and .call(d3.axisLeft(y)); append svg.node() to this.$el. The same call order is copied in the getting-started ESM, UMD, and local HTML samples.
- World map trace: mounted checks land, memoizes landPromises[resolution] as d3.json(jsDelivr world-atlas URL).then(topojson.feature), then deferRender(this.$el, () => render). render awaits feature, builds d3.geoPath(projection), selects the svg, binds pointerenter and pointermove when rotate is set, and on animation frame calls projection.rotate and updates outline, graticule, and feature path d attributes. unmounted calls the disconnect function returned by deferRender.
- deferRender order: if the node's rect is already in the viewport, call render immediately; otherwise observe with IntersectionObserver rootMargin 100px and also schedule requestIdleCallback when it exists. Either path disconnects the observer and cancels the idle callback before or as render runs. PlotRender's defer branch repeats this pattern and then el.append(Plot[method](options)).
- Export-parity test trace: test/d3-test.js readFileSyncs ../package.json, JSON.parses it, and for each key of dependencies dynamically import()s that package. For every property other than version it asserts propertyName in the namespace imported from ../src/index.js.
- Docs link test trace: readMarkdownFiles walks docs from "/", skips names starting with ".", and yields *.md paths. readMarkdownSource strips <!-- ... --> comments. getAnchors always includes "", then slugifies /^#+ / headers and collects explicit {#id} anchors. getLinks parses markdown links, skips protocol URLs, and resolves the rest with new URL against https://example.com/. The assertion fails if the target does not end in .md or the hash is absent from that file's anchors.
- Homepage gallery trace: VitePress calls gallery.data.js load() during build, which pulls the Observable gallery module and returns preview rows. ExamplesGrid imports {data} from that loader, shuffles with a UTC-day LCG, onMounted observes document.body, recomputes xn/yn, and renders anchors. VersionAndStars separately reads stargazers.data.ts and __APP_VERSION__.
- Sidebar-diagram trace on what-is-d3: useData() yields themeConfig.sidebar; a nested visit() pushes {path, link} for every item; computeTreeWidth runs d3.stratify().path then d3.tree().nodeSize([1,1]) and returns the x extent. PlotRender receives Plot.tree(paths, {path, textStroke, href channel, treeSort: null}) with height equal to that width times 12.
- UsMap trace: mounted memoizes one d3.json of counties-10m.json, then topojson.feature for nation and topojson.mesh for states and counties. The county mesh predicate keeps shared borders only when truncated state ids match: (a.id / 1000 | 0) === (b.id / 1000 | 0). updated() calls render again. Paths are selected by [name='countymesh'], [name='statemesh'], and [name='nation'].