diff --git a/packages/preview/percencode/0.1.1/CHANGELOG.md b/packages/preview/percencode/0.1.1/CHANGELOG.md new file mode 100644 index 0000000000..518a1078f7 --- /dev/null +++ b/packages/preview/percencode/0.1.1/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +## [0.1.1](https://github.com/Servostar/typst-percencode/compare/v0.1.0...v0.1.1) (2026-03-08) + + +### Bug Fixes + +* percent encoded chars needing exactly two hex digits ([#4](https://github.com/Servostar/typst-percencode/issues/4)) ([cf6d531](https://github.com/Servostar/typst-percencode/commit/cf6d531a936c03fdb7de437b74016960f37dade3)) + +## [0.1.0](https://github.com/Servostar/typst-percencode/compare/v0.0.0...v0.1.0) (2025-05-19) + + +### Features + +* implement percent encoding in Typst ([69d7226](https://github.com/Servostar/typst-percencode/commit/69d722642b239aac70d9cf26955f7ddd03f55060)) diff --git a/packages/preview/percencode/0.1.1/LICENSE b/packages/preview/percencode/0.1.1/LICENSE new file mode 100644 index 0000000000..9fc9f2f60b --- /dev/null +++ b/packages/preview/percencode/0.1.1/LICENSE @@ -0,0 +1,18 @@ +Copyright © 2025 + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/packages/preview/percencode/0.1.1/README.md b/packages/preview/percencode/0.1.1/README.md new file mode 100644 index 0000000000..9ff3d3f979 --- /dev/null +++ b/packages/preview/percencode/0.1.1/README.md @@ -0,0 +1,69 @@ +# Percent Encoding + +![GitHub License](https://img.shields.io/github/license/Servostar/typst-percencode) +![GitHub Release](https://img.shields.io/github/v/release/Servostar/typst-percencode) +[![GitHub](https://img.shields.io/badge/github-%23121011.svg?logo=github&logoColor=white)](https://github.com/Servostar/typst-percencode) + +This Typst library offers function for encoding and decoding percent escape sequences. +These are typically used to encode unsafe or non-ASCII characters in URLs. +Supported by this library is only Typst's native character encoding and defacto web standard: UTF-8. + +Read the [manual](https://github.com/Servostar/typst-percencode/releases/download/v0.1.0/manual.pdf) for further information. + +## Usage + +You can directly import the package from Typst universe: + +```typst +#import "@preview/percencode:0.1.0": * +``` + +## Example + +### Sanitize URLs + +The method `url-encode` can be used to escape unsafe characters (as in RFC 2396) in URL strings. + +Example: + +``` +https://example.com/how much is 23€ wörth? +``` + +Results in: + +``` +https://example.com/how%20much%20is%2023%E2%82%AC%20w%C3%B6rth? +``` + +### Encoding + +Encode an entire string: + +```typst +#percent-encode("Hello, World!") +``` + +Results in: + +``` +%48%65%6C%6C%6F%2C%20%57%6F%72%6C%64%21 +``` + +### Decoding + +Decode an entire string: + +```typst +#percent-decode("%48%65%6C%6C%6F%2C%20%57%6F%72%6C%64%21") +``` + +Results in: + +``` +Hello, World! +``` + +--- + +(c) 2025 Sven Vogel. Some right reserved. \ No newline at end of file diff --git a/packages/preview/percencode/0.1.1/docs/manual.typ b/packages/preview/percencode/0.1.1/docs/manual.typ new file mode 100644 index 0000000000..31a7832f90 --- /dev/null +++ b/packages/preview/percencode/0.1.1/docs/manual.typ @@ -0,0 +1,51 @@ + +#import "../src/lib.typ" as percencode + +#import "@preview/tidy:0.4.3" + +#let version = toml("../typst.toml").package.version + +#align(center)[ + + #stack( + spacing: 14pt, + text(2.7em, `percencode`), + [_utility library for URL en- and decoding_], + ) + + #v(15pt) + + #percencode.percent-encode("Percent Encoding") #sym.dash Percent Encoding + + #v(15pt) + + A #link("https://typst.app/")[Typst] package for URL encoding and decoding. + + #link("https://github.com:Servostar/typst-percencode.git")[`github.com:Servostar/typst-percencode.git`] + + *Version #version* +] + += Documentation + +This library offers function for encoding and decoding percent escape sequences. +These are typically used to encode unsafe or non-ASCII characters in URLs. +Supported by this library is only Typst's native character encoding and defacto web standard: UTF-8. + +#v(12pt) + +#import "../src/encode.typ" as encode +#let docs = tidy.parse-module( + read("../src/encode.typ"), + name: "Percent Encoding", + scope: (percencode: encode) +) +#tidy.show-module(docs, style: tidy.styles.default) + +#import "../src/decode.typ" as decode +#let docs = tidy.parse-module( + read("../src/decode.typ"), + name: "Percent Decoding", + scope: (percencode: decode) +) +#tidy.show-module(docs, style: tidy.styles.default) diff --git a/packages/preview/percencode/0.1.1/src/decode.typ b/packages/preview/percencode/0.1.1/src/decode.typ new file mode 100644 index 0000000000..bafa93548c --- /dev/null +++ b/packages/preview/percencode/0.1.1/src/decode.typ @@ -0,0 +1,28 @@ + +/// Decods a string previously percent encoded. +/// Every sequence of %XY where XY are hexadecimal letters +/// will be decoded to UTF-8. +/// +/// *Example* +/// +/// ```example +/// #percencode.percent-decode("%4F%62%66%75%73%63%61%74%65%64%21") +/// ``` +/// +/// -> str +#let percent-decode( + /// Percent encoded string to decode. + /// + /// -> str + message) = { + let decode-percent-sequence(sequence) = { + sequence.text.split("%").filter(cp => cp != "").map(hex => eval("0x" + hex)) + } + + message.replace( + regex(`(%[a-fA-F0-9]{2})+`.text), + // Dirty workaround as I couldn*t find an offical way of + // converting a hex string to an integer programatically. + matches => str(bytes(decode-percent-sequence(matches))), + ) +} diff --git a/packages/preview/percencode/0.1.1/src/encode.typ b/packages/preview/percencode/0.1.1/src/encode.typ new file mode 100644 index 0000000000..8b399b9ada --- /dev/null +++ b/packages/preview/percencode/0.1.1/src/encode.typ @@ -0,0 +1,63 @@ + +/// Encode the given string with percent encoding +/// escaping all UTF-8 characters. +/// Based on RFC 3986 section 2.1. +/// Encoding works by converting the UTF-8 representation of +/// a grapheme cluster (single piece of printable character) +/// for each byte to a string of upper case formatted hexadecimal. +/// +/// *NOTE:* This function will encode every character in the string! +/// +/// *Example* +/// +/// ```example +/// #percencode.percent-encode("Hello, World!") +/// ``` +/// +/// -> str +#let percent-encode( + /// String to encode in percent escape sequence. + /// + /// -> str + message, + /// Pattern of grapheme clusters not to escape. + /// + /// -> str | regex + exclude: none, +) = { + let str_pad(s) = if s.len() < 2 { "0" + s } else { s } + return message + .clusters() + .map(cluster => { + if exclude != none and cluster.contains(exclude) { + cluster + } else { + // Convert grapheme cluster to bytes representing the unicode point. + // Then drop zero bytes, only the least significant non-zero bytes are of use. + // At last, convert each byte to uppercase hex and prepend a '%'. + array(bytes(cluster)).map(byte => "%" + str_pad(upper(str(byte, base: 16)))).join("") + } + }) + .join() +} + +/// Escapes all characters except: +/// ``` +/// A–Z a–z 0–9 - _ . ! ~ * ' ( ) ; / ? : @ & = + $ , # +/// ``` +/// conforming to RFC 2396. +/// This function is meant to be used to encode entire URLs. +/// +/// ```example +/// #percencode.url-encode("https://example.com/how much is 23€ wörth?") +/// ``` +/// +/// -> str +#let url-encode( + /// URL string to encode + /// + /// -> str + url, +) = { + percent-encode(url, exclude: regex(`[a-zA-Z0-9\-_.!~*'();/?:@&=+$,#]`.text)) +} diff --git a/packages/preview/percencode/0.1.1/src/lib.typ b/packages/preview/percencode/0.1.1/src/lib.typ new file mode 100644 index 0000000000..bb942c24f4 --- /dev/null +++ b/packages/preview/percencode/0.1.1/src/lib.typ @@ -0,0 +1,2 @@ +#import "encode.typ": url-encode, percent-encode +#import "decode.typ": percent-decode diff --git a/packages/preview/percencode/0.1.1/typst.toml b/packages/preview/percencode/0.1.1/typst.toml new file mode 100644 index 0000000000..60f2f0c8a3 --- /dev/null +++ b/packages/preview/percencode/0.1.1/typst.toml @@ -0,0 +1,10 @@ +[package] +name = "percencode" +version = "0.1.1" +entrypoint = "src/lib.typ" +authors = ["Sven Vogel"] +license = "MIT" +description = "Work with percent-encoding used by web browsers to encode URLs." +repository = "https://github.com/Servostar/typst-percencode" +keywords = ["url", "encode", "decode", "escape", "percent"] +categories = ["scripting", "utility"]