fix: video loading from markdown

This commit is contained in:
Corbin Crutchley
2021-11-28 12:58:00 -08:00
parent 19683840ce
commit 12b6b346b1
9 changed files with 266 additions and 18 deletions

View File

@@ -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.

View File

@@ -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}

View File

@@ -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

View File

@@ -59,7 +59,7 @@ Well, its been a few years since Ive refreshed my math skills, so they mig
Lets open VSCode and start implementing the function. Lets 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 hadnt even had a chance to add the parameters to the “isPrime” function before Copilot had already made a suggestion! Wow! I hadnt even had a chance to add the parameters to the “isPrime” function before Copilot had already made a suggestion!

View File

@@ -96,7 +96,7 @@ This means that designers, alongside developers, can force the bounds of a `Text
This is something Ive 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 Ive 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>
*Memoires TextViews are all customized using these APIs.* *Memoires 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 cant 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 cant 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. Lets 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. Lets 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
View File

@@ -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",

View File

@@ -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",

View File

@@ -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.

View File

@@ -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()