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
6 changes: 1 addition & 5 deletions apps/site/pages/en/blog/npm/2013-outage-postmortem.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ We know the availability and overall health of The npm Registry is paramount to

The root cause of these downtime was insufficient resources: both hardware and human. This is a full post-mortem where we will be look at how npmjs.org works, what went wrong, how we changed the previous architecture of The npm Registry to fix it, as well next steps we are taking to prevent this from happening again.

All of the next steps require additional expenditure from Nodejitsu: both servers and labor. This is why along with this post-mortem we are announcing our [crowdfunding campaign: scalenpm.org](https://scalenpm.org)! Our goal is to raise enough funds so that Nodejitsu can continue to run The npm Registry as a free service for _you, the community._

Please take a minute now to donate at [https://scalenpm.org](https://scalenpm.org)!
All of the next steps require additional expenditure from Nodejitsu: both servers and labor. This is why along with this post-mortem we are announcing our crowdfunding campaign! Our goal is to raise enough funds so that Nodejitsu can continue to run The npm Registry as a free service for _you, the community._

## How does npmjs.org work?

Expand Down Expand Up @@ -73,8 +71,6 @@ The npm Registry has had a 10x year. In November 2012 there were 13.5 million do

_**But we need your help!**_ All of these necessary improvements require more servers, more time from Nodejitsu staff and an overall increase to what we spend maintaining the public npm registry as a free service for the Node.js community.

Please take a minute now to donate at [https://scalenpm.org](https://scalenpm.org)!

[browserify]: http://browserify.org/
[dotc]: https://github.com/substack/dotc
[npm-rubygems]: http://andrew.ghost.io/emulating-node-js-modules-in-ruby/
Expand Down
2 changes: 1 addition & 1 deletion packages/ui-components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@node-core/ui-components",
"version": "1.5.5",
"version": "1.5.6",
"type": "module",
"exports": {
"./*": [
Expand Down
39 changes: 39 additions & 0 deletions packages/ui-components/src/Common/TableOfContents/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@reference "../../styles/index.css";

.details {
@apply my-2
block
rounded-md
bg-neutral-200
lg:hidden
dark:bg-neutral-900;

.summary {
@apply px-4
py-2;
}

.list {
@apply space-y-1
px-4
pb-2;
}

.link {
@apply text-sm
font-semibold
text-neutral-900
underline
hover:text-neutral-700
dark:text-white
dark:hover:text-neutral-500;
}

.depthThree {
@apply pl-2;
}

.depthFour {
@apply pl-4;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import TableOfContents from '#ui/Common/TableOfContents';

import type { Meta as MetaObj, StoryObj } from '@storybook/react-webpack5';

type Story = StoryObj<typeof TableOfContents>;
type Meta = MetaObj<typeof TableOfContents>;

export const Default: Story = {};

export const CustomDepth: Story = {
args: {
minDepth: 1,
maxDepth: 6,
},
};

export default {
component: TableOfContents,
args: {
ariaLabel: 'Table of Contents',
summaryTitle: 'On this page',
headings: [
{
value: 'OpenSSL update assessment, and Node.js project plans',
depth: 1,
data: { id: 'heading-1' },
},
{
value: 'Summary',
depth: 2,
data: { id: 'summary' },
},
{
value: 'Analysis',
depth: 2,
data: { id: 'analysis' },
},
{
value: 'The c_rehash script allows command injection (CVE-2022-2068)',
depth: 3,
data: { id: 'the_c_rehash' },
},
{
value: 'Contact and future updates',
depth: 3,
data: { id: 'contact_and_future_updates' },
},
{
value: 'Email',
depth: 4,
data: { id: 'email' },
},
{
value: 'Slack',
depth: 4,
data: { id: 'slack' },
},
{
value: '#node-website',
depth: 5, // h5s do not get shown
data: { id: 'node-website' },
},
],
},
} as Meta;
55 changes: 55 additions & 0 deletions packages/ui-components/src/Common/TableOfContents/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import classNames from 'classnames';

import { LinkLike } from '#ui/types';

import type { Heading } from '@vcarl/remark-headings';
import type { ComponentProps, FC } from 'react';

import styles from './index.module.css';

const depthClasses: Record<number, string> = {
3: styles.depthThree,
4: styles.depthFour,
};

type TableOfContentsProps = ComponentProps<'details'> & {
headings: Array<Heading>;
summaryTitle: string;
minDepth?: number;
maxDepth?: number;
as?: LinkLike;
};

const TableOfContents: FC<TableOfContentsProps> = ({
headings,
summaryTitle,
minDepth = 2,
className,
maxDepth = 4,
as: Component = 'a',
...props
}) => {
const filteredHeadings = headings.filter(
({ depth }) => depth >= minDepth && depth <= maxDepth
);

return (
<details className={classNames(styles.details, className)} {...props}>
<summary className={styles.summary}>{summaryTitle}</summary>
<ul className={styles.list}>
{filteredHeadings.map((head, index) => (
<li key={head.data?.id ?? index}>
<Component
href={head.data?.id && `#${head.data.id}`}
className={classNames(styles.link, depthClasses[head.depth])}
>
{head.value}
</Component>
</li>
))}
</ul>
</details>
);
};

export default TableOfContents;
Loading