Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove solid-js from the search extension #86

Merged
merged 4 commits into from
May 12, 2024
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
9 changes: 8 additions & 1 deletion examples/web-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ import { LitElement, html } from 'lit'
class InkMde extends LitElement {
firstUpdated() {
ink(this.renderRoot.querySelector('#editor')!, {
doc: '# Hello, World!',
// eslint-disable-next-line @typescript-eslint/quotes
doc: "#examples\n\n# A Quick Guide to the Web Crypto API\n\nThe documentation on [MDN](https://developer.mozilla.org/en-US/) is robust, but it requires a lot of jumping around to individual method APIs. I hope this article is helpful for anyone out there looking for guidance.\n\n### Generating a Key\n\nTo start things off, we need to generate a symmetric key.\n\n```js\n// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey\nconst generateKey = async () => {\n return window.crypto.subtle.generateKey({\n name: 'AES-GCM',\n length: 256,\n }, true, ['encrypt', 'decrypt'])\n}\n```\n\n### Encoding Data\n\nBefore we can encrypt data, we first have to encode it into a byte stream. We can achieve this pretty simply with the `TextEncoder` class. This little utility will be used by our `encrypt` function later.\n\n```js\n// https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder\nconst encode = (data) => {\n const encoder = new TextEncoder()\n \n return encoder.encode(data)\n}\n```\n\n### Generating an Initialization Vector (IV)\n\nSimply put, an IV is what introduces true randomness into our encryption strategy. When using the same key to encrypt multiple sets of data, it is possible to derive relationships between the encrypted chunks of the cipher and therefore expose some or all of the original message. IVs ensure that repeating character sequences in the input data produce varying byte sequences in the resulting cipher. It is perfectly safe to store IVs in plain text alongside our encrypted message, and we will need to do this to decrypt our message later.\n\n```js\n// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues\nconst generateIv = () => {\n // https://developer.mozilla.org/en-US/docs/Web/API/AesGcmParams\n return window.crypto.getRandomValues(new Uint8Array(12))\n}\n```\n\nWe never want to use the same IV with a given key, so it's best to incorporate automatic IV generation into our encryption strategy as we will do later.\n\n### Encrypting Data\n\nNow that we have all of our utilities in place, we can implement our `encrypt` function! As mentioned above, we will need it to return both the cipher _and_ the IV so that we can decrypt the cipher later.\n\n```js\n// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt\nconst encrypt = async (data, key) => {\n const encoded = encode(data)\n const iv = generateIv()\n const cipher = await window.crypto.subtle.encrypt({\n name: 'AES-GCM',\n iv: iv,\n }, key, encoded)\n \n return {\n cipher,\n iv,\n }\n}\n```\n\n## Transmission and Storage\n\nMost practical applications of encryption involve the transmission or storage of said encrypted data. When data is encrypted using SubtleCrypto, the resulting cipher and IV are represented as raw binary data buffers. This is not an ideal format for transmission or storage, so we will tackle packing and unpacking next.\n\n### Packing Data\n\nSince data is often transmitted in JSON and stored in databases, it makes sense to pack our data in a format that is portable. We are going to convert our binary data buffers into base64-encoded strings. Depending on your use case, the base64 encoding is absolutely optional, but I find it helps make the data as portable as you could possibly need.\n\n```js \n// https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String\nconst pack = (buffer) => {\n return window.btoa(\n String.fromCharCode.apply(null, new Uint8Array(buffer))\n )\n}\n```\n\n### Unpacking Data\n\nOnce our packed data has been transmitted, stored, and later retrieved, we just need to reverse the process. We will convert our base64-encoded strings back into raw binary buffers.\n\n```js\n// https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String\nconst unpack = (packed) => {\n const string = window.atob(packed)\n const buffer = new ArrayBuffer(string.length)\n const bufferView = new Uint8Array(buffer)\n\n for (let i = 0; i < string.length; i++) {\n bufferView[i] = string.charCodeAt(i)\n }\n\n return buffer\n}\n```\n\n## Decryption\n\nWe're in the home stretch! The last step of the process is decrypting our data to see those sweet, sweet secrets. As with unpacking, we just need to reverse the encryption process.\n\n### Decoding Data\n\nAfter decrypting, we will need to decode our resulting byte stream back into its original form. We can achieve this with the `TextDecoder` class. This utility will be used by our `decrypt` function later.\n\n```js\n// https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder\nconst decode = (bytestream) => {\n const decoder = new TextDecoder()\n \n return decoder.decode(bytestream)\n}\n```\n\n### Decrypting Data\n\nNow we just need to implement the `decrypt` function. As mentioned before, we will need to supply not just the key but also the IV that was used in the encryption step.\n\n```js\n// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/decrypt\nconst decrypt = async (cipher, key, iv) => {\n const encoded = await window.crypto.subtle.decrypt({\n name: 'AES-GCM',\n iv: iv,\n }, key, cipher)\n \n return decode(encoded)\n}\n```\n\n## Putting it into Practice\n\nLet's write an app! Now that all of our utilities are built, we just need to use them. We will encrypt, pack, and transmit our data to a secure endpoint. Then, we will retrieve, unpack, and decrypt the original message.\n\n```js\nconst app = async () => {\n // encrypt message\n const first = 'Hello, World!'\n const key = await generateKey()\n const { cipher, iv } = await encrypt(first, key)\n \n // pack and transmit\n await fetch('/secure-api', {\n method: 'POST',\n body: JSON.stringify({\n cipher: pack(cipher),\n iv: pack(iv),\n }),\n })\n \n // retrieve\n const response = await fetch('/secure-api').then(res => res.json())\n\n // unpack and decrypt message\n const final = await decrypt(unpack(response.cipher), key, unpack(response.iv))\n console.log(final) // logs 'Hello, World!'\n}\n```\n\nThat's all there is to it! We have successfully implemented client-side encryption.\n\nAs a final note, I just want to share [octo](https://github.com/voraciousdev/octo), a note-taking app for developers, one more time. It's free, it's open source, and I would absolutely love it if you checked it out. Thanks, everyone, and happy coding. ✌️",
hooks: {
afterUpdate: (doc) => {
// eslint-disable-next-line no-console
console.log(JSON.stringify(doc))
},
},
})
}

Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "ink-mde",
"type": "module",
"version": "0.32.0",
"packageManager": "pnpm@8.4.0",
"packageManager": "pnpm@9.1.0+sha256.22e36fba7f4880ecf749a5ca128b8435da085ecd49575e7fb9e64d6bf4fad394",
"description": "A beautiful, modern, customizable Markdown editor powered by CodeMirror 6 and TypeScript.",
"author": "David R. Myers <[email protected]>",
"license": "MIT",
Expand Down Expand Up @@ -145,7 +145,6 @@
"@lezer/highlight": "^1.2.0",
"@lezer/markdown": "^1.3.0",
"@replit/codemirror-vim": "^6.2.1",
"ink-mde": "workspace:*",
"katex": "^0.16.9",
"solid-js": "^1.8.7",
"style-mod": "^4.1.2"
Expand Down
2 changes: 1 addition & 1 deletion plugins/katex/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'
import { EditorView } from '@codemirror/view'
import { plugin, pluginTypes } from 'ink-mde'
import { buildBlockWidgetDecoration, buildLineDecoration, buildWidget, nodeDecorator } from '/lib/codemirror-kit'
import { plugin, pluginTypes } from '/src/index'
import { grammar, mathInline, mathInlineMark, mathInlineMarkClose, mathInlineMarkOpen } from './grammar'

export const katex = () => {
Expand Down
Loading
Loading