Skip to content

Commit 4022f97

Browse files
authored
Use custom ID format that works better with MDX 2 (#4105)
* Fix two unicode whitespaces which are invalid * Use custom ID format that works better with MDX 2 * Fix sebastian * remark-slug as dev dep
1 parent 7254849 commit 4022f97

File tree

169 files changed

+1476
-1337
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

169 files changed

+1476
-1337
lines changed

beta/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
"remark-external-links": "^7.0.0",
7777
"remark-html": "^12.0.0",
7878
"remark-images": "^2.0.0",
79+
"remark-slug": "^7.0.0",
7980
"remark-unwrap-images": "^2.0.0",
8081
"retext": "^7.0.1",
8182
"retext-smartypants": "^4.0.0",
@@ -93,4 +94,4 @@
9394
"budgetPercentIncreaseRed": 10,
9495
"showDetails": true
9596
}
96-
}
97+
}

beta/plugins/remark-header-custom-ids.js

+26-8
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,34 @@ module.exports = ({
3030
slugs.reset();
3131
return function transformer(tree) {
3232
visit(tree, 'heading', (node) => {
33-
// Support custom-id syntax.
34-
const rawHeader = toString(node);
35-
const match = /^.+(\s*\{#([\p{L}0-9\-_]+?)\}\s*)$/u.exec(rawHeader);
36-
const id = match ? match[2] : slugs.slug(rawHeader, maintainCase);
37-
if (match) {
38-
// Remove the custom ID part from the text node.
39-
const lastNode = node.children[node.children.length - 1];
40-
lastNode.value = lastNode.value.replace(match[1], '');
33+
const children = node.children;
34+
let tail = children[children.length - 1];
35+
36+
// A bit weird: this is to support MDX 2 comments in expressions,
37+
// while we’re still on MDX 1, which doesn’t support them.
38+
if (!tail || tail.type !== 'text' || tail.value !== '/}') {
39+
return
4140
}
4241

42+
tail = children[children.length - 2]
43+
44+
if (!tail && tail.type !== 'emphasis') {
45+
return
46+
}
47+
48+
const id = toString(tail)
49+
50+
tail = children[children.length - 3]
51+
52+
if (!tail || tail.type !== 'text' || !tail.value.endsWith('{/')) {
53+
return
54+
}
55+
56+
// Remove the emphasis and trailing `/}`
57+
children.splice(children.length - 2, 2)
58+
// Remove the `{/`
59+
tail.value = tail.value.replace(/[ \t]*\{\/$/, '')
60+
4361
const data = patch(node, 'data', {});
4462

4563
patch(data, 'id', id);

beta/scripts/generateHeadingIDs.js

+47-18
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@
22
* Copyright (c) Facebook, Inc. and its affiliates.
33
*/
44

5+
// To do: Make this ESM.
6+
// To do: properly check heading numbers (headings with the same text get
7+
// numbered, this script doesn’t check that).
8+
9+
const assert = require('assert');
510
const fs = require('fs');
611
const GithubSlugger = require('github-slugger');
712

13+
let modules
14+
815
function walk(dir) {
916
let results = [];
1017
const list = fs.readdirSync(dir);
@@ -31,15 +38,25 @@ function addHeaderID(line, slugger) {
3138
if (!line.startsWith('#')) {
3239
return line;
3340
}
34-
// check if it already has an id
35-
if (/\{#[^}]+\}/.test(line)) {
36-
return line;
41+
42+
const match = /^(#+\s+)(.+?)(\s*\{(?:\/\*|#)([^\}\*\/]+)(?:\*\/)?\}\s*)?$/.exec(line);
43+
const before = match[1] + match[2]
44+
const proc = modules.unified().use(modules.remarkParse).use(modules.remarkSlug)
45+
const tree = proc.runSync(proc.parse(before))
46+
const head = tree.children[0]
47+
assert(head && head.type === 'heading', 'expected `' + before + '` to be a heading, is it using a normal space after `#`?')
48+
const autoId = head.data.id
49+
const existingId = match[4]
50+
const id = existingId || autoId
51+
// Ignore numbers:
52+
const cleanExisting = existingId ? existingId.replace(/-\d+$/, '') : undefined
53+
const cleanAuto = autoId.replace(/-\d+$/, '')
54+
55+
if (cleanExisting && cleanExisting !== cleanAuto) {
56+
console.log('Note: heading `%s` has a different ID (`%s`) than what GH generates for it: `%s`:', before, existingId, autoId)
3757
}
38-
const headingText = line.slice(line.indexOf(' ')).trim();
39-
const headingLevel = line.slice(0, line.indexOf(' '));
40-
return `${headingLevel} ${headingText} {#${slugger.slug(
41-
stripLinks(headingText)
42-
)}}`;
58+
59+
return match[1] + match[2] + ' {/*' + id + '*/}';
4360
}
4461

4562
function addHeaderIDs(lines) {
@@ -66,14 +83,26 @@ function addHeaderIDs(lines) {
6683

6784
const [path] = process.argv.slice(2);
6885

69-
const files = walk(path);
70-
files.forEach((file) => {
71-
if (!(file.endsWith('.md') || file.endsWith('.mdx'))) {
72-
return;
73-
}
86+
main()
87+
88+
async function main() {
89+
const [unifiedMod, remarkParseMod, remarkSlugMod] = await Promise.all([import('unified'), import('remark-parse'), import('remark-slug')])
90+
const unified = unifiedMod.default
91+
const remarkParse = remarkParseMod.default
92+
const remarkSlug = remarkSlugMod.default
93+
modules = {unified, remarkParse, remarkSlug}
7494

75-
const content = fs.readFileSync(file, 'utf8');
76-
const lines = content.split('\n');
77-
const updatedLines = addHeaderIDs(lines);
78-
fs.writeFileSync(file, updatedLines.join('\n'));
79-
});
95+
const files = walk(path);
96+
97+
files.forEach((file) => {
98+
if (!(file.endsWith('.md') || file.endsWith('.mdx'))) {
99+
return;
100+
}
101+
102+
const content = fs.readFileSync(file, 'utf8');
103+
const lines = content.split('\n');
104+
const updatedLines = addHeaderIDs(lines);
105+
fs.writeFileSync(file, updatedLines.join('\n'));
106+
});
107+
108+
}

beta/src/pages/blog/2013/06/05/why-react.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ author: [petehunt]
66
There are a lot of JavaScript MVC frameworks out there. Why did we build React
77
and why would you want to use it?
88

9-
## React isn't an MVC framework. {#react-isnt-an-mvc-framework}
9+
## React isn't an MVC framework. {/*react-isnt-an-mvc-framework*/}
1010

1111
React is a library for building composable user interfaces. It encourages
1212
the creation of reusable UI components which present data that changes over
1313
time.
1414

15-
## React doesn't use templates. {#react-doesnt-use-templates}
15+
## React doesn't use templates. {/*react-doesnt-use-templates*/}
1616

1717
Traditionally, web application UIs are built using templates or HTML directives.
1818
These templates dictate the full set of abstractions that you are allowed to use
@@ -33,7 +33,7 @@ to render views, which we see as an advantage over templates for a few reasons:
3333
We've also created [JSX](/docs/jsx-in-depth.html), an optional syntax
3434
extension, in case you prefer the readability of HTML to raw JavaScript.
3535

36-
## Reactive updates are dead simple. {#reactive-updates-are-dead-simple}
36+
## Reactive updates are dead simple. {/*reactive-updates-are-dead-simple*/}
3737

3838
React really shines when your data changes over time.
3939

@@ -63,7 +63,7 @@ Because this re-render is so fast (around 1ms for TodoMVC), the developer
6363
doesn't need to explicitly specify data bindings. We've found this approach
6464
makes it easier to build apps.
6565

66-
## HTML is just the beginning. {#html-is-just-the-beginning}
66+
## HTML is just the beginning. {/*html-is-just-the-beginning*/}
6767

6868
Because React has its own lightweight representation of the document, we can do
6969
some pretty cool things with it:

beta/src/pages/blog/2013/06/12/community-roundup.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ author: [vjeux]
55

66
React was open sourced two weeks ago and it's time for a little round-up of what has been going on.
77

8-
## Khan Academy Question Editor {#khan-academy-question-editor}
8+
## Khan Academy Question Editor {/*khan-academy-question-editor*/}
99

1010
It looks like [Sophie Alpert](http://sophiebits.com/) is the first person outside of Facebook and Instagram to push React code to production. We are very grateful for her contributions in form of pull requests, bug reports and presence on IRC ([#reactjs on Freenode](irc://chat.freenode.net/reactjs)). Sophie wrote about her experience using React:
1111

@@ -17,7 +17,7 @@ It looks like [Sophie Alpert](http://sophiebits.com/) is the first person outsid
1717
>
1818
> [Read the full post...](http://sophiebits.com/2013/06/09/using-react-to-speed-up-khan-academy.html)
1919
20-
## Pimp my Backbone.View (by replacing it with React) {#pimp-my-backboneview-by-replacing-it-with-react}
20+
## Pimp my Backbone.View (by replacing it with React) {/*pimp-my-backboneview-by-replacing-it-with-react*/}
2121

2222
[Paul Seiffert](https://blog.mayflower.de/) wrote a blog post that explains how to integrate React into Backbone applications.
2323

@@ -29,15 +29,15 @@ It looks like [Sophie Alpert](http://sophiebits.com/) is the first person outsid
2929
>
3030
> [Read the full post...](https://blog.mayflower.de/3937-Backbone-React.html)
3131
32-
## Using facebook's React with require.js {#using-facebooks-react-with-requirejs}
32+
## Using facebook's React with require.js {/*using-facebooks-react-with-requirejs*/}
3333

3434
[Mario Mueller](http://blog.xenji.com/) wrote a menu component in React and was able to easily integrate it with require.js, EventEmitter2 and bower.
3535

3636
> I recently stumbled upon facebook's React library, which is a JavaScript library for building reusable frontend components. Even if this lib is only at version 0.3.x it behaves very stable, it is fast and is fun to code. I'm a big fan of require.js, so I tried to use React within the require.js eco system. It was not as hard as expected and here are some examples and some thoughts about it.
3737
>
3838
> [Read the full post...](http://blog.xenji.com/2013/06/facebooks-react-require-js.html)
3939
40-
## Origins of React {#origins-of-react}
40+
## Origins of React {/*origins-of-react*/}
4141

4242
[Pete Hunt](http://www.petehunt.net/blog/) explained what differentiates React from other JavaScript libraries in [a previous blog post](/blog/2013/06/05/why-react.html). [Lee Byron](http://leebyron.com/) gives another perspective on Quora:
4343

beta/src/pages/blog/2013/06/19/community-roundup-2.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ author: [vjeux]
55

66
Since the launch we have received a lot of feedback and are actively working on React 0.4. In the meantime, here are the highlights of this week.
77

8-
## Some quick thoughts on React {#some-quick-thoughts-on-react}
8+
## Some quick thoughts on React {/*some-quick-thoughts-on-react*/}
99

1010
[Andrew Greig](http://www.andrewgreig.com/) made a blog post that gives a high level description of what React is.
1111

@@ -19,7 +19,7 @@ Since the launch we have received a lot of feedback and are actively working on
1919
>
2020
> [Read the full post...](http://www.andrewgreig.com/637/)
2121
22-
## React and Socket.IO Chat Application {#react-and-socketio-chat-application}
22+
## React and Socket.IO Chat Application {/*react-and-socketio-chat-application*/}
2323

2424
[Danial Khosravi](https://danialk.github.io/) made a real-time chat application that interacts with the back-end using Socket.IO.
2525

@@ -29,7 +29,7 @@ Since the launch we have received a lot of feedback and are actively working on
2929
>
3030
> [Read the full post...](https://danialk.github.io/blog/2013/06/16/reactjs-and-socket-dot-io-chat-application/)
3131
32-
## React and Other Frameworks {#react-and-other-frameworks}
32+
## React and Other Frameworks {/*react-and-other-frameworks*/}
3333

3434
[Pete Hunt](http://www.petehunt.net/blog/) wrote an answer on Quora comparing React and Angular directives. At the end, he explains how you can make an Angular directive that is in fact being rendered with React.
3535

@@ -41,7 +41,7 @@ Since the launch we have received a lot of feedback and are actively working on
4141
4242
In the same vein, [Markov Twain](https://twitter.com/markov_twain/status/345702941845499906) re-implemented the examples on the front-page [with Ember](http://jsbin.com/azihiw/2/edit) and [Vlad Yazhbin](https://twitter.com/vla) re-implemented the tutorial [with Angular](http://jsfiddle.net/vla/Cdrse/).
4343

44-
## Web Components: React & x-tags {#web-components-react--x-tags}
44+
## Web Components: React & x-tags {/*web-components-react--x-tags*/}
4545

4646
Mozilla and Google are actively working on Web Components. [Vjeux](http://blog.vjeux.com/) wrote a proof of concept that shows how to implement them using React.
4747

@@ -51,7 +51,7 @@ Mozilla and Google are actively working on Web Components. [Vjeux](http://blog.v
5151
>
5252
> [Read the full post...](http://blog.vjeux.com/2013/javascript/custom-components-react-x-tags.html)
5353
54-
## React TodoMVC Example {#react-todomvc-example}
54+
## React TodoMVC Example {/*react-todomvc-example*/}
5555

5656
[TodoMVC.com](http://todomvc.com/) is a website that collects various implementations of the same basic Todo app. [Pete Hunt](http://www.petehunt.net/blog/) wrote an idiomatic React version.
5757

@@ -63,7 +63,7 @@ Mozilla and Google are actively working on Web Components. [Vjeux](http://blog.v
6363
>
6464
> [Read the source code...](https://github.com/tastejs/todomvc/tree/gh-pages/labs/architecture-examples/react)
6565
66-
## JSX is not HTML {#jsx-is-not-html}
66+
## JSX is not HTML {/*jsx-is-not-html*/}
6767

6868
Many of you pointed out differences between JSX and HTML. In order to clear up some confusion, we have added some documentation that covers the four main differences:
6969

beta/src/pages/blog/2013/06/21/react-v0-3-3.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ author: [zpao]
55

66
We have a ton of great stuff coming in v0.4, but in the meantime we're releasing v0.3.3. This release addresses some small issues people were having and simplifies our tools to make them easier to use.
77

8-
## react-tools {#react-tools}
8+
## react-tools {/*react-tools*/}
99

1010
- Upgrade Commoner so `require` statements are no longer relativized when passing through the transformer. This was a feature needed when building React, but doesn't translate well for other consumers of `bin/jsx`.
1111
- Upgraded our dependencies on Commoner and Recast so they use a different directory for their cache.
1212
- Freeze our esprima dependency.
1313

14-
## React {#react}
14+
## React {/*react*/}
1515

1616
- Allow reusing the same DOM node to render different components. e.g. `React.renderComponent(<div/>, domNode); React.renderComponent(<span/>, domNode);` will work now.
1717

18-
## JSXTransformer {#jsxtransformer}
18+
## JSXTransformer {/*jsxtransformer*/}
1919

2020
- Improved the in-browser transformer so that transformed scripts will execute in the expected scope. The allows components to be defined and used from separate files.

beta/src/pages/blog/2013/06/27/community-roundup-3.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ author: [vjeux]
55

66
The highlight of this week is that an interaction-heavy app has been ported to React. React components are solving issues they had with nested views.
77

8-
## Moving From Backbone To React {#moving-from-backbone-to-react}
8+
## Moving From Backbone To React {/*moving-from-backbone-to-react*/}
99

1010
[Clay Allsopp](https://twitter.com/clayallsopp) successfully ported [Propeller](http://usepropeller.com/blog/posts/from-backbone-to-react/), a fairly big, interaction-heavy JavaScript app, to React.
1111

@@ -17,7 +17,7 @@ The highlight of this week is that an interaction-heavy app has been ported to R
1717
>
1818
> [Read the full post...](http://usepropeller.com/blog/posts/from-backbone-to-react/)
1919
20-
## Grunt Task for JSX {#grunt-task-for-jsx}
20+
## Grunt Task for JSX {/*grunt-task-for-jsx*/}
2121

2222
[Eric Clemmons](https://ericclemmons.github.io/) wrote a task for [Grunt](http://gruntjs.com/) that applies the JSX transformation to your JavaScript files. It also works with [Browserify](http://browserify.org/) if you want all your files to be concatenated and minified together.
2323

@@ -45,7 +45,7 @@ The highlight of this week is that an interaction-heavy app has been ported to R
4545
>
4646
> [Check out the project ...](https://github.com/ericclemmons/grunt-react)
4747
48-
## Backbone/Handlebars Nested Views {#backbonehandlebars-nested-views}
48+
## Backbone/Handlebars Nested Views {/*backbonehandlebars-nested-views*/}
4949
5050
[Joel Burget](http://joelburget.com/) wrote a blog post talking about the way we would write React-like components in Backbone and Handlebars.
5151
@@ -57,13 +57,13 @@ The highlight of this week is that an interaction-heavy app has been ported to R
5757
>
5858
> [Read the full post...](http://joelburget.com/react/)
5959
60-
## JSRomandie Meetup {#jsromandie-meetup}
60+
## JSRomandie Meetup {/*jsromandie-meetup*/}
6161
6262
[Renault John Lecoultre](https://twitter.com/renajohn/) from [BugBuster](http://www.bugbuster.com) did a React introduction talk at a JS meetup called [JS Romandie](https://twitter.com/jsromandie) last week.
6363
6464
<script async class="speakerdeck-embed" data-id="888a9d50c01b01300df36658d0894ac1" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
6565
66-
## CoffeeScript integration {#coffeescript-integration}
66+
## CoffeeScript integration {/*coffeescript-integration*/}
6767
6868
[Vjeux](http://blog.vjeux.com/) used the fact that JSX is just a syntactic sugar on-top of regular JS to rewrite the React front-page examples in CoffeeScript.
6969
@@ -81,7 +81,7 @@ The highlight of this week is that an interaction-heavy app has been ported to R
8181
>
8282
> [Read the full post...](http://blog.vjeux.com/2013/javascript/react-coffeescript.html)
8383
84-
## Tutorial in Plain JavaScript {#tutorial-in-plain-javascript}
84+
## Tutorial in Plain JavaScript {/*tutorial-in-plain-javascript*/}
8585
8686
We've seen a lot of people comparing React with various frameworks. [Ricardo Tomasi](http://ricardo.cc/) decided to re-implement the tutorial without any framework, just plain JavaScript.
8787

beta/src/pages/blog/2013/07/02/react-v0-4-autobind-by-default.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ author: [zpao]
66
React v0.4 is very close to completion. As we finish it off, we'd like to share with you some of the major changes we've made since v0.3. This is the first of several posts we'll be making over the next week.
77

88

9-
## What is React.autoBind? {#what-is-reactautobind}
9+
## What is React.autoBind? {/*what-is-reactautobind*/}
1010

1111
If you take a look at most of our current examples, you'll see us using `React.autoBind` for event handlers. This is used in place of `Function.prototype.bind`. Remember that in JS, [function calls are late-bound](https://bonsaiden.github.io/JavaScript-Garden/#function.this). That means that if you simply pass a function around, the `this` used inside won't necessarily be the `this` you expect. `Function.prototype.bind` creates a new, properly bound, function so that when called, `this` is exactly what you expect it to be.
1212

@@ -33,7 +33,7 @@ React.createClass({
3333
```
3434

3535

36-
## What's Changing in v0.4? {#whats-changing-in-v04}
36+
## What's Changing in v0.4? {/*whats-changing-in-v04*/}
3737

3838
After using `React.autoBind` for a few weeks, we realized that there were very few times that we didn't want that behavior. So we made it the default! Now all methods defined within `React.createClass` will already be bound to the correct instance.
3939

beta/src/pages/blog/2013/07/03/community-roundup-4.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ author: [vjeux]
55

66
React reconciliation process appears to be very well suited to implement a text editor with a live preview as people at Khan Academy show us.
77

8-
## Khan Academy {#khan-academy}
8+
## Khan Academy {/*khan-academy*/}
99

1010
[Ben Kamens](http://bjk5.com/) explains how [Sophie Alpert](http://sophiebits.com/) and [Joel Burget](http://joelburget.com/) are promoting React inside of [Khan Academy](https://www.khanacademy.org/). They now have three projects in the works using React.
1111

@@ -21,7 +21,7 @@ The best part is the demo of how React reconciliation process makes live editing
2121
2222
[![](/images/blog/monkeys.gif)](http://bjk5.com/post/53742233351/getting-your-team-to-adopt-new-technology)
2323

24-
## React Snippets {#react-snippets}
24+
## React Snippets {/*react-snippets*/}
2525

2626
Over the past several weeks, members of our team, [Pete Hunt](http://www.petehunt.net/) and [Paul O'Shannessy](http://zpao.com/), answered many questions that were asked in the [React group](https://groups.google.com/forum/#!forum/reactjs). They give a good overview of how to integrate React with other libraries and APIs through the use of [Mixins](/docs/reusable-components.html) and [Lifecycle Methods](/docs/working-with-the-browser.html).
2727

@@ -44,13 +44,13 @@ Over the past several weeks, members of our team, [Pete Hunt](http://www.petehun
4444
>
4545
> - [JSFiddle](http://jsfiddle.net/LQxy7/): Your React component simply render empty divs, and then in componentDidMount() you call React.renderComponent() on each of those divs to set up a new root React tree. Be sure to explicitly unmountAndReleaseReactRootNode() for each component in componentWillUnmount().
4646
47-
## Introduction to React Screencast {#introduction-to-react-screencast}
47+
## Introduction to React Screencast {/*introduction-to-react-screencast*/}
4848

4949
[Pete Hunt](http://www.petehunt.net/) recorded himself implementing a simple `<Blink>` tag in React.
5050

5151
<figure><iframe src="https://player.vimeo.com/video/67248575" width="100%" height="340" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></figure>
5252

53-
## Snake in React {#snake-in-react}
53+
## Snake in React {/*snake-in-react*/}
5454

5555
[Tom Occhino](http://tomocchino.com/) implemented Snake in 150 lines with React.
5656

0 commit comments

Comments
 (0)