mirror of
https://github.com/LukeHagar/unicorn-utterances.git
synced 2025-12-07 21:07:47 +00:00
fix: video loading from markdown
This commit is contained in:
@@ -78,7 +78,7 @@ Once you've created a subfolder with the URI you'd like your article to have, mo
|
|||||||
An example of referencing a video locally is:
|
An example of referencing a video locally is:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
`video: title: "A comparison of how text spacing is applied on iOS and Android": ./ios_vs_android.mp4`
|
<video src="./ios_vs_android.mp4" title="A comparison of how text spacing is applied on iOS and Android"></video>
|
||||||
```
|
```
|
||||||
|
|
||||||
Where you include the title of the video and the video.
|
Where you include the title of the video and the video.
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ For example, one of the ways that we can send and receive data is by, well, send
|
|||||||
|
|
||||||
It doesn't wait for a full message to be sent or provide many guidelines for how to send the data, it just tells them to "come on over".
|
It doesn't wait for a full message to be sent or provide many guidelines for how to send the data, it just tells them to "come on over".
|
||||||
|
|
||||||
`video: title: "A series of cars driving across 3 lines at various speeds. This is meant to represent the data flow of binary data on a bus architecture": ./bus_animation.mp4`
|
<video src="./bus_animation.mp4" title="A series of cars driving across 3 lines at various speeds. This is meant to represent the data flow of binary data on a bus architecture"></video>
|
||||||
|
|
||||||
In this example, the bus icons are similar to binary data - either a one or a zero. They're able to _move as quickly as possible down a "lane" that is allocated for a specific stream of data to come through_. A collection of "lanes" is called a "bus" (which is where the name of the architecture comes from. I was just being silly by representing the binary data as buses in the video above). Your system, right now, is streaming through _**many**_ thousands of these busses to communicate between your CPU and I/O devices (like your keyboard or speakers) and tons of other things. They're _typically divided to send specific data through specific lanes (or busses)_, but outside of that, there's little high-level organization or concepts to think through.
|
In this example, the bus icons are similar to binary data - either a one or a zero. They're able to _move as quickly as possible down a "lane" that is allocated for a specific stream of data to come through_. A collection of "lanes" is called a "bus" (which is where the name of the architecture comes from. I was just being silly by representing the binary data as buses in the video above). Your system, right now, is streaming through _**many**_ thousands of these busses to communicate between your CPU and I/O devices (like your keyboard or speakers) and tons of other things. They're _typically divided to send specific data through specific lanes (or busses)_, but outside of that, there's little high-level organization or concepts to think through.
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ While the "body" of your packet would contain the data you want the other party
|
|||||||
|
|
||||||
As a result, you might have a middleware packet handler that reads only the header of the packet in order to decide where to send the packet in question - much like the mail service you use will read the outside of the envelope to see where to send your letter
|
As a result, you might have a middleware packet handler that reads only the header of the packet in order to decide where to send the packet in question - much like the mail service you use will read the outside of the envelope to see where to send your letter
|
||||||
|
|
||||||
`video: title: "An example of a small packet being sent to a small file server and a larger packet being sent to the large file server based on the data in the packet header": ./header_routing.mp4`
|
<video src="./header_routing.mp4" title="An example of a small packet being sent to a small file server and a larger packet being sent to the large file server based on the data in the packet header"></video>
|
||||||
|
|
||||||
# [It Takes A Village](https://en.wikipedia.org/wiki/It_takes_a_village) To Send A Letter {#osi-layers}
|
# [It Takes A Village](https://en.wikipedia.org/wiki/It_takes_a_village) To Send A Letter {#osi-layers}
|
||||||
|
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ React.useEffect(() => {
|
|||||||
|
|
||||||
It supports dark mode switching, as many API levels as React Native does, and much more!
|
It supports dark mode switching, as many API levels as React Native does, and much more!
|
||||||
|
|
||||||
`video: title: "A working dark switch with transparent navbar": ./android_10.mp4`
|
<video src="./android_10.mp4" title="A working dark switch with transparent navbar"></video>
|
||||||
|
|
||||||
# Conclusion
|
# Conclusion
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ Well, it’s been a few years since I’ve refreshed my math skills, so they mig
|
|||||||
|
|
||||||
Let’s open VSCode and start implementing the function.
|
Let’s open VSCode and start implementing the function.
|
||||||
|
|
||||||
`video: title: "GitHub Copilot generating a complete implementation of 'isPrime' from nothing more than the function name": ./gh_copilot_is_prime.mp4`
|
<video src="./gh_copilot_is_prime.mp4" title="GitHub Copilot generating a complete implementation of 'isPrime' from nothing more than the function name"></video>
|
||||||
|
|
||||||
Wow! I hadn’t even had a chance to add the parameters to the “isPrime” function before Copilot had already made a suggestion!
|
Wow! I hadn’t even had a chance to add the parameters to the “isPrime” function before Copilot had already made a suggestion!
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ This means that designers, alongside developers, can force the bounds of a `Text
|
|||||||
|
|
||||||
This is something I’ve personally tested in an app I designed. [**Memoire**, a note-taking app](http://tiny.cc/getmemoire) for Android, is a 1:1 recreation of its mockups — for every single screen. This was made possible due to these APIs — *and because [**@sasikanth**](https://twitter.com/its\_sasikanth) is not confrontational* — since text is what almost always makes baseline alignment and hard grids impossible to implement in production.
|
This is something I’ve personally tested in an app I designed. [**Memoire**, a note-taking app](http://tiny.cc/getmemoire) for Android, is a 1:1 recreation of its mockups — for every single screen. This was made possible due to these APIs — *and because [**@sasikanth**](https://twitter.com/its\_sasikanth) is not confrontational* — since text is what almost always makes baseline alignment and hard grids impossible to implement in production.
|
||||||
|
|
||||||
`video: title: "Near-perfect duplication of guidelines against Memoire's mockups and actual app": ./memoire_bounds_and_baselines.mp4`
|
<video src="./memoire_bounds_and_baselines.mp4" title="Near-perfect duplication of guidelines against Memoire's mockups and actual app"></video>
|
||||||
|
|
||||||
*Memoire’s TextViews are all customized using these APIs.*
|
*Memoire’s TextViews are all customized using these APIs.*
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ As you might imagine, **if we want to keep our text aligned to a baseline grid,
|
|||||||
|--|--|
|
|--|--|
|
||||||
|Applying `firstBaseline` and `lastBaseline` in styles allows you to know exactly what the distance between baselines is, without having to set them one by one to ensure they properly align to a `4dp` grid. | Without applying `firstBaseline` and `lastBaseline` in styles, you can’t detect what the default values are, so you are forced to apply these one by one to every `TextView` to ensure they align to a `4dp` grid. |
|
|Applying `firstBaseline` and `lastBaseline` in styles allows you to know exactly what the distance between baselines is, without having to set them one by one to ensure they properly align to a `4dp` grid. | Without applying `firstBaseline` and `lastBaseline` in styles, you can’t detect what the default values are, so you are forced to apply these one by one to every `TextView` to ensure they align to a `4dp` grid. |
|
||||||
|
|
||||||
`video: title: "A comparison of how text spacing is applied on iOS and Android": ./ios_vs_android.mp4`
|
<video src="./ios_vs_android.mp4" title="A comparison of how text spacing is applied on iOS and Android"></video>
|
||||||
|
|
||||||
The solution is to apply them in your `styles.xml` so that, when themed, the `TextView` is given the right text size, height, font, and baseline properties.
|
The solution is to apply them in your `styles.xml` so that, when themed, the `TextView` is given the right text size, height, font, and baseline properties.
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ The solution is to apply them in your `styles.xml` so that, when themed, the `Te
|
|||||||
|
|
||||||
The overrides will take precedence to whatever value you set in your **`styles.xml`**, requiring you to hunt down occurrences until you can find a layout that was broken due to the change. Let’s look at an example:
|
The overrides will take precedence to whatever value you set in your **`styles.xml`**, requiring you to hunt down occurrences until you can find a layout that was broken due to the change. Let’s look at an example:
|
||||||
|
|
||||||
`video: title: "Allowing margin changes instead will let the text grow to it's expected sie without having issues with the baseline not being centered": ./dont_override.mp4`
|
<video src="./dont_override.mp4" title="Allowing margin changes instead will let the text grow to it's expected sie without having issues with the baseline not being centered"></video>
|
||||||
|
|
||||||
Implementing margins instead of overriding values also matches the way layouts work within Android Studio and design tools like Sketch and Figma. It also ensures that your layouts can scale well to different font sizes.
|
Implementing margins instead of overriding values also matches the way layouts work within Android Studio and design tools like Sketch and Figma. It also ensures that your layouts can scale well to different font sizes.
|
||||||
|
|
||||||
|
|||||||
225
package-lock.json
generated
225
package-lock.json
generated
@@ -703,6 +703,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001283.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001283.tgz",
|
||||||
"integrity": "sha512-9RoKo841j1GQFSJz/nCXOj0sD7tHBtlowjYlrqIUS812x9/emfBLBt6IyMz1zIaYc/eRL8Cs6HPUVi2Hzq4sIg=="
|
"integrity": "sha512-9RoKo841j1GQFSJz/nCXOj0sD7tHBtlowjYlrqIUS812x9/emfBLBt6IyMz1zIaYc/eRL8Cs6HPUVi2Hzq4sIg=="
|
||||||
},
|
},
|
||||||
|
"ccount": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="
|
||||||
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||||
@@ -1829,6 +1834,11 @@
|
|||||||
"semver": "^6.0.0"
|
"semver": "^6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"markdown-table": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-CBbaYXKSGnE1uLRpKA1SWgIRb2PQrpkllNWpZtZe6VojOJ4ysqiq7/2glYcmKsOYN09QgH/HEBX5hIshAeiK6A=="
|
||||||
|
},
|
||||||
"md5.js": {
|
"md5.js": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||||
@@ -1839,6 +1849,37 @@
|
|||||||
"safe-buffer": "^5.1.2"
|
"safe-buffer": "^5.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mdast-util-find-and-replace": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-1w1jbqAd13oU78QPBf5223+xB+37ecNtQ1JElq2feWols5oEYAl+SgNDnOZipe7NfLemoEt362yUS15/wip4mw==",
|
||||||
|
"requires": {
|
||||||
|
"escape-string-regexp": "^5.0.0",
|
||||||
|
"unist-util-is": "^5.0.0",
|
||||||
|
"unist-util-visit-parents": "^4.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"escape-string-regexp": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="
|
||||||
|
},
|
||||||
|
"unist-util-is": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ=="
|
||||||
|
},
|
||||||
|
"unist-util-visit-parents": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==",
|
||||||
|
"requires": {
|
||||||
|
"@types/unist": "^2.0.0",
|
||||||
|
"unist-util-is": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"mdast-util-from-markdown": {
|
"mdast-util-from-markdown": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.0.4.tgz",
|
||||||
@@ -1913,6 +1954,93 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mdast-util-gfm": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-wMwejlTN3EQADPFuvxe8lmGsay3+f6gSJKdAHR6KBJzpcxvsjJSILB9K6u6G7eQLC7iOTyVIHYGui9uBc9r1Tg==",
|
||||||
|
"requires": {
|
||||||
|
"mdast-util-gfm-autolink-literal": "^1.0.0",
|
||||||
|
"mdast-util-gfm-footnote": "^1.0.0",
|
||||||
|
"mdast-util-gfm-strikethrough": "^1.0.0",
|
||||||
|
"mdast-util-gfm-table": "^1.0.0",
|
||||||
|
"mdast-util-gfm-task-list-item": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mdast-util-gfm-autolink-literal": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg==",
|
||||||
|
"requires": {
|
||||||
|
"@types/mdast": "^3.0.0",
|
||||||
|
"ccount": "^2.0.0",
|
||||||
|
"mdast-util-find-and-replace": "^2.0.0",
|
||||||
|
"micromark-util-character": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mdast-util-gfm-footnote": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-qeg9YoS2YYP6OBmMyUFxKXb6BLwAsbGidIxgwDAXHIMYZQhIwe52L9BSJs+zP29Jp5nSERPkmG3tSwAN23/ZbQ==",
|
||||||
|
"requires": {
|
||||||
|
"@types/mdast": "^3.0.0",
|
||||||
|
"mdast-util-to-markdown": "^1.0.0",
|
||||||
|
"micromark-util-normalize-identifier": "^1.0.0",
|
||||||
|
"unist-util-visit": "^4.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"unist-util-is": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ=="
|
||||||
|
},
|
||||||
|
"unist-util-visit": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-n7lyhFKJfVZ9MnKtqbsqkQEk5P1KShj0+//V7mAcoI6bpbUjh3C/OG8HVD+pBihfh6Ovl01m8dkcv9HNqYajmQ==",
|
||||||
|
"requires": {
|
||||||
|
"@types/unist": "^2.0.0",
|
||||||
|
"unist-util-is": "^5.0.0",
|
||||||
|
"unist-util-visit-parents": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unist-util-visit-parents": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-y+QVLcY5eR/YVpqDsLf/xh9R3Q2Y4HxkZTp7ViLDU6WtJCEcPmRzW1gpdWDCDIqIlhuPDXOgttqPlykrHYDekg==",
|
||||||
|
"requires": {
|
||||||
|
"@types/unist": "^2.0.0",
|
||||||
|
"unist-util-is": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mdast-util-gfm-strikethrough": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-gM9ipBUdRxYa6Yq1Hd8Otg6jEn/dRxFZ1F9ZX4QHosHOexLGqNZO2dh0A+YFbUEd10RcKjnjb4jOfJJzoXXUew==",
|
||||||
|
"requires": {
|
||||||
|
"@types/mdast": "^3.0.3",
|
||||||
|
"mdast-util-to-markdown": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mdast-util-gfm-table": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-NByKuaSg5+M6r9DZBPXFUmhMHGFf9u+WE76EeStN01ghi8hpnydiWBXr+qj0XCRWI7SAMNtEjGvip6zci9axQA==",
|
||||||
|
"requires": {
|
||||||
|
"markdown-table": "^3.0.0",
|
||||||
|
"mdast-util-to-markdown": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mdast-util-gfm-task-list-item": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-dwkzOTjQe8JCCHVE3Cb0pLHTYLudf7t9WCAnb20jI8/dW+VHjgWhjtIUVA3oigNkssgjEwX+i+3XesUdCnXGyA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/mdast": "^3.0.3",
|
||||||
|
"mdast-util-to-markdown": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"mdast-util-to-hast": {
|
"mdast-util-to-hast": {
|
||||||
"version": "12.0.0",
|
"version": "12.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.0.0.tgz",
|
||||||
@@ -2232,6 +2360,92 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"micromark-extension-gfm": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-yYPlZ48Ss8fRFSmlQP/QXt3/M6tEvawEVFO+jDPnFA3mGeVgzIyaeHgrIV/9AMFAjQhctKA47Bk8xBhcuaL74Q==",
|
||||||
|
"requires": {
|
||||||
|
"micromark-extension-gfm-autolink-literal": "^1.0.0",
|
||||||
|
"micromark-extension-gfm-footnote": "^1.0.0",
|
||||||
|
"micromark-extension-gfm-strikethrough": "^1.0.0",
|
||||||
|
"micromark-extension-gfm-table": "^1.0.0",
|
||||||
|
"micromark-extension-gfm-tagfilter": "^1.0.0",
|
||||||
|
"micromark-extension-gfm-task-list-item": "^1.0.0",
|
||||||
|
"micromark-util-combine-extensions": "^1.0.0",
|
||||||
|
"micromark-util-types": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"micromark-extension-gfm-autolink-literal": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-z2Asd0v4iV/QoI1l23J1qB6G8IqVWTKmwdlP45YQfdGW47ZzpddyzSxZ78YmlucOLqIbS5H98ekKf9GunFfnLA==",
|
||||||
|
"requires": {
|
||||||
|
"micromark-util-character": "^1.0.0",
|
||||||
|
"micromark-util-sanitize-uri": "^1.0.0",
|
||||||
|
"micromark-util-symbol": "^1.0.0",
|
||||||
|
"micromark-util-types": "^1.0.0",
|
||||||
|
"uvu": "^0.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"micromark-extension-gfm-footnote": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-C6o+B7w1wDM4JjDJeHCTszFYF1q46imElNY6mfXsBfw4E91M9TvEEEt3sy0FbJmGVzdt1pqFVRYWT9ZZ0FjFuA==",
|
||||||
|
"requires": {
|
||||||
|
"micromark-core-commonmark": "^1.0.0",
|
||||||
|
"micromark-factory-space": "^1.0.0",
|
||||||
|
"micromark-util-character": "^1.0.0",
|
||||||
|
"micromark-util-normalize-identifier": "^1.0.0",
|
||||||
|
"micromark-util-sanitize-uri": "^1.0.0",
|
||||||
|
"micromark-util-symbol": "^1.0.0",
|
||||||
|
"uvu": "^0.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"micromark-extension-gfm-strikethrough": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-PJKhBNyrNIo694ZQCE/FBBQOQSb6YC0Wi5Sv0OCah5XunnNaYbtak9CSv9/eq4YeFMMyd1jX84IRwUSE+7ioLA==",
|
||||||
|
"requires": {
|
||||||
|
"micromark-util-chunked": "^1.0.0",
|
||||||
|
"micromark-util-classify-character": "^1.0.0",
|
||||||
|
"micromark-util-resolve-all": "^1.0.0",
|
||||||
|
"micromark-util-symbol": "^1.0.0",
|
||||||
|
"micromark-util-types": "^1.0.0",
|
||||||
|
"uvu": "^0.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"micromark-extension-gfm-table": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-IK2yzl7ycXeFFvZ8qiH4j5am529ihjOFD7NMo8Nhyq+VGwgWe4+qeI925RRrJuEzX3KyQ+1vzY8BIIvqlgOJhw==",
|
||||||
|
"requires": {
|
||||||
|
"micromark-factory-space": "^1.0.0",
|
||||||
|
"micromark-util-character": "^1.0.0",
|
||||||
|
"micromark-util-symbol": "^1.0.0",
|
||||||
|
"micromark-util-types": "^1.0.0",
|
||||||
|
"uvu": "^0.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"micromark-extension-gfm-tagfilter": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-GGUZhzQrOdHR8RHU2ru6K+4LMlj+pBdNuXRtw5prOflDOk2hHqDB0xEgej1AHJ2VETeycX7tzQh2EmaTUOmSKg==",
|
||||||
|
"requires": {
|
||||||
|
"micromark-util-types": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"micromark-extension-gfm-task-list-item": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-8AZib9xxPtppTKig/d00i9uKi96kVgoqin7+TRtGprDb8uTUrN1ZfJ38ga8yUdmu7EDQxr2xH8ltZdbCcmdshg==",
|
||||||
|
"requires": {
|
||||||
|
"micromark-factory-space": "^1.0.0",
|
||||||
|
"micromark-util-character": "^1.0.0",
|
||||||
|
"micromark-util-symbol": "^1.0.0",
|
||||||
|
"micromark-util-types": "^1.0.0",
|
||||||
|
"uvu": "^0.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"micromark-factory-destination": {
|
"micromark-factory-destination": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz",
|
||||||
@@ -3112,6 +3326,17 @@
|
|||||||
"unist-util-visit": "^2.0.3"
|
"unist-util-visit": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"remark-gfm": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==",
|
||||||
|
"requires": {
|
||||||
|
"@types/mdast": "^3.0.0",
|
||||||
|
"mdast-util-gfm": "^2.0.0",
|
||||||
|
"micromark-extension-gfm": "^2.0.0",
|
||||||
|
"unified": "^10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"remark-parse": {
|
"remark-parse": {
|
||||||
"version": "10.0.0",
|
"version": "10.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.0.tgz",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
"rehype-react": "^7.0.3",
|
"rehype-react": "^7.0.3",
|
||||||
"rehype-stringify": "^9.0.2",
|
"rehype-stringify": "^9.0.2",
|
||||||
"remark-behead": "^2.3.3",
|
"remark-behead": "^2.3.3",
|
||||||
|
"remark-gfm": "^3.0.1",
|
||||||
"remark-parse": "^10.0.0",
|
"remark-parse": "^10.0.0",
|
||||||
"remark-rehype": "^10.0.1",
|
"remark-rehype": "^10.0.1",
|
||||||
"remark-stringify": "^10.0.1",
|
"remark-stringify": "^10.0.1",
|
||||||
|
|||||||
@@ -14,25 +14,32 @@ interface useMarkdownRendererProps {
|
|||||||
markdownHTML: string
|
markdownHTML: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isRelativePath = (str: string) => {
|
||||||
|
return str.startsWith('./') || /^\w/.exec(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getFullRelativePath = (slug: string, srcStr: string) => {
|
||||||
|
if (srcStr.startsWith('./')) srcStr = srcStr.slice(2);
|
||||||
|
return isRelativePath(srcStr) ?
|
||||||
|
// URLJoin doesn't seem to handle the `./` well
|
||||||
|
urljoin('/posts', slug, srcStr)
|
||||||
|
: srcStr
|
||||||
|
}
|
||||||
|
|
||||||
const getComponents = ({
|
const getComponents = ({
|
||||||
slug
|
slug
|
||||||
}: useMarkdownRendererProps) => ({
|
}: useMarkdownRendererProps) => ({
|
||||||
img: (imgProps: unknown) => {
|
img: (imgProps: unknown) => {
|
||||||
const {src, ...props2} = imgProps as ImageProps;
|
const {src, ...props2} = imgProps as ImageProps;
|
||||||
const srcStr = src as string; // ImageProps isn't _quite_ right for our usg here
|
let srcStr = getFullRelativePath(slug, src as string); // ImageProps isn't _quite_ right for our usg here
|
||||||
const imagePath =
|
|
||||||
srcStr.startsWith('./') ?
|
|
||||||
// URLJoin doesn't seem to handle the `./` well
|
|
||||||
urljoin('/posts', slug, srcStr.slice(2, srcStr.length))
|
|
||||||
: srcStr
|
|
||||||
|
|
||||||
// only "fill" is supported when height and width are not specified
|
// only "fill" is supported when height and width are not specified
|
||||||
const beResponsive = !!(props2.height && props2.width);
|
const beResponsive = !!(props2.height && props2.width);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Zoom>
|
<Zoom>
|
||||||
<Image
|
<Image
|
||||||
src={imagePath}
|
src={srcStr}
|
||||||
{...props2}
|
{...props2}
|
||||||
layout={beResponsive ? "intrinsic" : "fill"}
|
layout={beResponsive ? "intrinsic" : "fill"}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
@@ -40,6 +47,19 @@ const getComponents = ({
|
|||||||
</Zoom>
|
</Zoom>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
video: (props: React.VideoHTMLAttributes<HTMLVideoElement>) => {
|
||||||
|
const {src, ...rest} = props;
|
||||||
|
const srcStr = getFullRelativePath(slug, src || '');
|
||||||
|
return <video
|
||||||
|
muted={true}
|
||||||
|
autoPlay={true}
|
||||||
|
controls={true}
|
||||||
|
loop={true}
|
||||||
|
width="100%"
|
||||||
|
height="auto"
|
||||||
|
{...rest}
|
||||||
|
src={srcStr}/>
|
||||||
|
},
|
||||||
// Temp fix to remove HTML, BODY, and HEAD nodes from render. Not sure why,
|
// Temp fix to remove HTML, BODY, and HEAD nodes from render. Not sure why,
|
||||||
// but it's being added to the markdown rendering in the `useMarkdownRenderer`
|
// but it's being added to the markdown rendering in the `useMarkdownRenderer`
|
||||||
// step.
|
// step.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import remarkParse from "remark-parse";
|
|||||||
import remarkStringify from "remark-stringify";
|
import remarkStringify from "remark-stringify";
|
||||||
import remarkToRehype from 'remark-rehype';
|
import remarkToRehype from 'remark-rehype';
|
||||||
import rehypeStringify from "rehype-stringify";
|
import rehypeStringify from "rehype-stringify";
|
||||||
|
import remarkGfm from 'remark-gfm'
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import {postsDirectory} from "../api";
|
import {postsDirectory} from "../api";
|
||||||
import rehypeImageSize from 'rehype-img-size';
|
import rehypeImageSize from 'rehype-img-size';
|
||||||
@@ -15,18 +16,19 @@ export default async function markdownToHtml(slug: string, markdown: string) {
|
|||||||
const imageDir = path.resolve(postsDirectory, slug);
|
const imageDir = path.resolve(postsDirectory, slug);
|
||||||
const result = await unified()
|
const result = await unified()
|
||||||
.use(remarkParse)
|
.use(remarkParse)
|
||||||
|
.use(remarkGfm)
|
||||||
/* start remark plugins here */
|
/* start remark plugins here */
|
||||||
.use(behead, { after: 0, depth: 1 })
|
.use(behead, { after: 0, depth: 1 })
|
||||||
/* end remark plugins here */
|
/* end remark plugins here */
|
||||||
.use(remarkStringify)
|
.use(remarkStringify)
|
||||||
.use(remarkToRehype)
|
.use(remarkToRehype, {allowDangerousHtml: true})
|
||||||
/* start rehype plugins here */
|
/* start rehype plugins here */
|
||||||
// TODO: https://github.com/ksoichiro/rehype-img-size/issues/4
|
// TODO: https://github.com/ksoichiro/rehype-img-size/issues/4
|
||||||
.use(rehypeImageSize, {
|
.use(rehypeImageSize, {
|
||||||
dir: imageDir,
|
dir: imageDir,
|
||||||
})
|
})
|
||||||
/* end rehype plugins here */
|
/* end rehype plugins here */
|
||||||
.use(rehypeStringify)
|
.use(rehypeStringify, {allowDangerousHtml: true})
|
||||||
.process(markdown);
|
.process(markdown);
|
||||||
|
|
||||||
return result.toString()
|
return result.toString()
|
||||||
|
|||||||
Reference in New Issue
Block a user