Last active
December 14, 2023 19:12
-
-
Save jrcd-HR/92ef3407c9f5061787b7c7a095a031ea to your computer and use it in GitHub Desktop.
Upgrade play.d2lang.org URLs generated before Dec 06
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Upgrade old D2 playground URLs (<= Dec 06 2023) to new URLS (>= Dec 06 2023). | |
* | |
* usage: go run upd2url.go < file_of_old_urls > new_urls | |
* | |
* Timeline: | |
* 1. Nov 7 2023: | |
* d2 changed their URL encode and decode to avoid the use of a custom DEFLATE dictionary. | |
* https://github.com/terrastruct/d2/commit/5eead31c91fcc1f6c0ecaf28e3006758055efd8b | |
* 2. Dec 6 2023: | |
* play.d2lang.org upgraded its WASM compiled version of d2 that is run client-side. | |
* https://github.com/terrastruct/d2-playground/commit/ae1e9c3bcd9896a978f80a0d1d370fea302e85a0 | |
* | |
* If you saved any URLs to play.d2lang.com that included D2 diagrams (compressed, base64 | |
* encoded, and passed in the script= query parameter) these would no longer decode properly | |
* in the newly deployed play.d2lang.org site. If you didn't save a backup the old diagram source | |
* was lost. | |
* | |
* This program reads old URLs and prints out new URLs a line at a time. The old URLs are decoded | |
* using the old deflate dictionary and encoded to new URLs which have no custom dictionary. | |
* | |
* Justin Davis <justin_davis@baxter.com> | |
*/ | |
package main | |
import ( | |
"bufio" | |
"bytes" | |
"compress/flate" | |
"encoding/base64" | |
"fmt" | |
"io" | |
"net/url" | |
"os" | |
"strings" | |
) | |
// these must be pre-sorted | |
const keywords = ` | |
3d animated bold border-radius class classes constraint desc direction | |
double-border fill fill-pattern filled font font-color font-size | |
grid-columns grid-gap grid-rows height horizontal-gap icon italic | |
label layers left link multiple near opacity scenarios shadow shape | |
source-arrowhead steps stroke stroke-dash stroke-width style | |
target-arrowhead text-transform tooltip top underline vars | |
vertical-gap width | |
` | |
var oldRawDict []byte | |
func init() { | |
common := strings.Fields(keywords) | |
oldRawDict = []byte("->" + "<-" + "--" + "<->" + strings.Join(common, "")) | |
} | |
func UpgradeURL(old *url.URL) error { | |
vals := old.Query() | |
oldscript64 := vals.Get("script") | |
if oldscript64 == "" { | |
return fmt.Errorf("URL missing script query param", old) | |
} | |
oldscript, err := base64.URLEncoding.DecodeString(oldscript64) | |
if err != nil { | |
return err | |
} | |
bin, bout := bytes.NewBuffer(oldscript), &bytes.Buffer{} | |
zrdr := flate.NewReaderDict(bin, oldRawDict) | |
zwtr, err := flate.NewWriter(bout, flate.BestCompression) | |
if err != nil { | |
return err | |
} | |
_, err = io.Copy(zwtr, zrdr) | |
if err != nil { | |
return err | |
} | |
zwtr.Close() | |
newscript64 := base64.URLEncoding.EncodeToString(bout.Bytes()) | |
vals.Set("script", newscript64) | |
old.RawQuery = vals.Encode() | |
return nil | |
} | |
func main() { | |
scan := bufio.NewScanner(os.Stdin) | |
scan.Split(bufio.ScanLines) | |
for scan.Scan() { | |
var input *url.URL | |
var err error | |
if input, err = url.ParseRequestURI(scan.Text()); err != nil { | |
fmt.Fprintln(os.Stderr, "error: invalid URL") | |
continue | |
} | |
if err := UpgradeURL(input); err != nil { | |
fmt.Fprintln(os.Stderr, "error:", err) | |
continue | |
} | |
fmt.Println(input) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment