Introducing Shaku - a family of tools that help write tech articles

My frustration on Markdown

Since 2 years ago, I have been writing about how React works internally in the series of React Internals Deep Dive, yet I constanly feel frustrated about the writing experience.

My posts are written in Markdown, which is a quite good choice except that:

  1. Markdown generated posts lack interactivity
  2. it is hard to explain code snippet, especially for longer ones

For technical posts, interactivity is very important to provide readers with good learning experience. Looking at great posts from nan.fyi or web.dev, we can see that great posts should have following components.

  1. interactive demo
  2. code editor
  3. typography components
  4. quizzes
  5. diagrams

And there doesn’t seem to be existing solutions to my needs, so I decided to create some by myself.

Introducing Shaku - a family of tools that help write tech articles

(Shaku)- elucidate, explain

I’m building a bunch of modules based on my writing experience from jser.dev, it might be a UI component, markdown parser plugin or anything that might be useful, all will be put under the umbrella of “Shaku”

shaku-code-annotate - annotate code snippets in markdown

Let’s take a look the first tool from Shaku - shaku-code-annotate, to understand what I mean by “help write tech articles”.

Suppose I need to explain code about binary search authored by others, so I add following snippet to markdown.

markdown
```js
/**
* search the index of target, or the position to insert
* @param {number[]} arr
* @param {number} target
*/
function binarySearch(arr, target) {
let i = 0
let j = arr.length
while (i <= j) {
// choose the center every time and move cursor
// to one of the halves
const mid = Math.floor((i + j) / 2)
if (arr[mid] === target) {
return mid
} else if (arr[mid] < target) {
i = mid + 1
} else {
j = mid - 1
}
}
return i
}
```
markdown
```js
/**
* search the index of target, or the position to insert
* @param {number[]} arr
* @param {number} target
*/
function binarySearch(arr, target) {
let i = 0
let j = arr.length
while (i <= j) {
// choose the center every time and move cursor
// to one of the halves
const mid = Math.floor((i + j) / 2)
if (arr[mid] === target) {
return mid
} else if (arr[mid] < target) {
i = mid + 1
} else {
j = mid - 1
}
}
return i
}
```

Problem is that I want to emphasize that the while condition is i <= j, not i < j, because me myself often get it wrong.

I could add some more comments to the line of code, but the original code already has 2 lines of comments, which makes it hard to tell the context if I just put them there, like below.

js
function binarySearch(arr, target) {
let i = 0
let j = arr.length
while (i <= j) {
// ^
// [attention that it is <= here, not <]
// [it makes sure one more of round of comparison when i and j meets]
// choose the center every time and move cursor
// to one of the halves
const mid = Math.floor((i + j) / 2)
if (arr[mid] === target) {
return mid
} else if (arr[mid] < target) {
i = mid + 1
} else {
j = mid - 1
}
}
return i
}
js
function binarySearch(arr, target) {
let i = 0
let j = arr.length
while (i <= j) {
// ^
// [attention that it is <= here, not <]
// [it makes sure one more of round of comparison when i and j meets]
// choose the center every time and move cursor
// to one of the halves
const mid = Math.floor((i + j) / 2)
if (arr[mid] === target) {
return mid
} else if (arr[mid] < target) {
i = mid + 1
} else {
j = mid - 1
}
}
return i
}

The core issue is that I want to annotate the code in the context of the post, not the context of the code, which cannot be addressed with just a simple code snippet.

Now with shaku-code-annotate, we are able to annotate code in a new context, out of the code itself.

To start, we need to first add the right plugin. This website is built with astro, it uses remark to parse Markdown, so I added remark-shaku-code-annotate. We only need to add annotate to the code block meta to kick it off

diff
-```js
+```js annotate
function binarySearch(arr, target) {
let i = 0
let j = arr.length
...
}
```
diff
-```js
+```js annotate
function binarySearch(arr, target) {
let i = 0
let j = arr.length
...
}
```

For the binary search example, we are able to see it rendered like this.

function binarySearch(arr, target) {
let i = 0
let j = arr.length
while (i <= j) {

attention that it is <= here, not <

it makes sure one more of round of comparison when i and j meets

// choose the center every time and move cursor
// to one of the halves
const mid = Math.floor((i + j) / 2)
if (arr[mid] === target) {
return mid
} else if (arr[mid] < target) {
i = mid + 1
} else {
j = mid - 1
}
}
return i
}
function binarySearch(arr, target) {
let i = 0
let j = arr.length
while (i <= j) {

attention that it is <= here, not <

it makes sure one more of round of comparison when i and j meets

// choose the center every time and move cursor
// to one of the halves
const mid = Math.floor((i + j) / 2)
if (arr[mid] === target) {
return mid
} else if (arr[mid] < target) {
i = mid + 1
} else {
j = mid - 1
}
}
return i
}

Isn’t it cool? Below is an example showing a lot more options, including underlines and highlights.

const blog = "https://jser.dev"

JSer.dev is the homepage for JSer.

Check it out!

// This is normal comments from source code.
const blog = "https://jser.dev"
~~~~~~~~

JSer.dev is the homepage for JSer.

Check it out!

const blog = "jser.dev"
--------

Check it out!

const blog = "jser.dev"
........

Check it out!

const blog = "jser.dev"
........
const blog = "jser.dev"
--------
const blog = "jser.dev"
~~~~~~~~
function useSomeEffect({blog}) {
~~~~~~~~~~~~~
useEffect(() => {
// do some stuff
return () => {
location.href = 'https://jser.dev'
}

This cleanup function is super important

}, [blog])
}
const blog = "https://jser.dev"

JSer.dev is the homepage for JSer.

Check it out!

// This is normal comments from source code.
const blog = "https://jser.dev"
~~~~~~~~

JSer.dev is the homepage for JSer.

Check it out!

const blog = "jser.dev"
--------

Check it out!

const blog = "jser.dev"
........

Check it out!

const blog = "jser.dev"
........
const blog = "jser.dev"
--------
const blog = "jser.dev"
~~~~~~~~
function useSomeEffect({blog}) {
~~~~~~~~~~~~~
useEffect(() => {
// do some stuff
return () => {
location.href = 'https://jser.dev'
}

This cleanup function is super important

}, [blog])
}

visit Shaku Playground to see the source code.

This is just the first tool from the box, stay tuned and follow shaku on github.

😳 Would you like to share my post to more people ?    

❮ Prev: How does useId() work internally in React?

Next: How does useTransition() work internally in React?