Skip to content

Commit

Permalink
codly:0.1.0 (#217)
Browse files Browse the repository at this point in the history
Dherse authored Nov 6, 2023
1 parent 0e14cb7 commit dcbb9f6
Showing 9 changed files with 506 additions and 0 deletions.
21 changes: 21 additions & 0 deletions packages/preview/codly/0.1.0/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) [2023] [slashformotion]

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.
133 changes: 133 additions & 0 deletions packages/preview/codly/0.1.0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@

# Codly: simple and beautiful code blocks for Typst

Codly is a package that lets you easily create beautiful code blocks for your Typst documents.
It uses the newly added [`raw.line`](https://typst.app/docs/reference/text/raw/#definitions-line)
function to work across all languages easily. You can customize the icons, colors, and more to
suit your document's theme. By default it has zebra striping, line numbers, for ease of reading.

````typ
#let icon(codepoint) = {
box(
height: 0.8em,
baseline: 0.05em,
image(codepoint)
)
h(0.1em)
}
#show: codly-init.with()
#codly(languages: (
rust: (name: "Rust", icon: icon("brand-python.svg"), color: rgb("#CE412B")),
))
```rust
pub fn main() {
println!("Hello, world!");
}
```
````

Which renders to:

![Example](./demo.png)

You can find all of the documentation in the [example](https://github.com/Dherse/codly/tree/main/example/main.typ) file.

## Short manual

### Setup

To start using codly, you need to initialize codly using a show rule:

```typ
#show: codly-init.with()
```

Then you need to congigure codly with your parameters:

```typ
#codly(
languages: (
rust: (name: "Rust", icon: icon("\u{fa53}"), color: rgb("#CE412B")),
)
)
```

Then you just need to add a code block and it will be automatically displayed correctly:

````
```rust
pub fn main() {
println!("Hello, world!");
}
```
````

### Disabling

To locally disable codly, you can just do the following, you can then later re-enable it using the `codly` configuration function.

```typ
#disable-codly()
```

### Setting an offset

If you wish to add an offset to your code block, but without selecting a subset of lines, you can use the `codly-offset` function:

```typ
// Sets a 5 line offset
#codly-offset(5)
```

### Selecting a subset of lines

If you wish to select a subset of lines, you can use the `codly-range` function. By setting the start to 1 and the end to `none` you can select all lines from the start to the end of the code block.

```typ
#codly-range(start: 5, end: 10)
```

### Disabling line numbers

You can configure this with the `codly` function:

```typ
#codly(
width-numbers: none,
)
```

### Disabling zebra striping

You disable zebra striping by setting the `zebra-color` to white.

```typ
#codly(
zebra-color: white,
)
```

### Customize the stroke

You can customize the stroke surrounding the figure using the `stroke-width` and `stroke-color` parameters of the `codly` function:

```typ
#codly(
stroke-width: 1pt,
stroke-color: red,
)
```

### Misc

You can also disable the icon, by setting the `display-icon` parameter to `false`:

```typ
#codly(
display-icon: false,
)
```

Same with the name, whether the block is breakable, the radius, the padding, and the width of the numbers columns.
239 changes: 239 additions & 0 deletions packages/preview/codly/0.1.0/codly.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
// Lets you set a line number offset.
#let codly-offset(offset: 0) = {
state("codly-offset").update(offset)
}

// Lets you set a range of line numbers to highlight.
#let codly-range(
start: 1,
end: none,
) = {
state("codly-range").update((start, end))
}

// Disables codly.
#let disable-codly() = {
state("codly-config").update(none)
}

// Configures codly.
#let codly(
// The list of languages, allows setting a display name and an icon,
// it should be a dict of the form:
// `<language-name>: (name: <display-name>, icon: <icon-content>, color: <color>)`
languages: (:),

// Whether to display the language name.
display-name: true,

// Whether to display the language icon.
display-icon: true,

// The default color for a language not in the list.
// Only used if `display-icon` or `display-name` is `true`.
default-color: rgb("#283593"),

// Radius of a code block.
radius: 0.32em,

// Padding of a code block.
padding: 0.32em,

// The zebra color to use or `none` to disable.
zebra-color: luma(240),

// The stroke width to use to surround the code block.
// Set to `none` to disable.
stroke-width: 0.1em,

// The stroke color to use to surround the code block.
stroke-color: luma(240),

// The width of the numbers column.
// If set to `none`, the numbers column will be disabled.
width-numbers: 2em,

// Whether this code block is breakable.
breakable: true,
) = locate(loc => {
let old = state("codly-config").at(loc);
if old == none {
state("codly-config").update((
languages: languages,
display-name: display-name,
display-icon: display-icon,
default-color: default-color,
radius: radius,
padding: padding,
zebra-color: zebra-color,
stroke-width: stroke-width,
width-numbers: width-numbers,
breakable: breakable,
stroke-color: stroke-color,
))
} else {
let folded_langs = old.languages;
for (lang, def) in languages {
folded_langs.insert(lang, def)
}

state("codly-config").update((
languages: folded_langs,
display-name: display-name,
display-icon: display-icon,
default-color: default-color,
radius: radius,
padding: padding,
zebra-color: zebra-color,
stroke-width: stroke-width,
width-numbers: width-numbers,
breakable: breakable,
stroke-color: stroke-color,
))
}
})

#let codly-init(
body,
) = {
show raw.where(block: true): it => locate(loc => {
let config = state("codly-config").at(loc)
let range = state("codly-range").at(loc)
let in_range(line) = {
if range == none {
true
} else if range.at(1) == none {
line >= range.at(0)
} else {
line >= range.at(0) and line <= range.at(1)
}
}
if config == none {
return it
}
let language_block = if config.display-name == false and config.display-icon == false {
none
} else if it.lang == none {
none
} else if it.lang in config.languages {
let lang =config. languages.at(it.lang);
let content = if config.display-name == true and config.display-icon == true {
lang.icon + lang.name
} else if config.display-name == true {
lang.name
} else {
lang.icon
};

style(styles => {
let height = measure(content, styles).height
box(
radius: config.radius,
fill: lang.color.lighten(60%),
inset: config.padding,
height: height + config.padding * 2,
stroke: config.stroke-width + lang.color,
content,
)
})
} else {
if config.display-name == false {
style(styles => {
let height = measure(it.lang, styles).height
box(
radius: config.radius,
fill: config.default-color.lighten(60%),
inset: config.padding,
height: height + padding * 2,
stroke: config.stroke-width + config.default-color,
it.lang,
)
})
} else {
none
}
};

let offset = state("codly-offset").at(loc);
let start = if range == none { 1 } else { range.at(0) };
let border(i, len) = {
let end = if range == none { len } else if range.at(1) == none { len } else { range.at(1) };

let stroke-width = if config.stroke-width == none { 0pt } else { config.stroke-width };
let radii = (:)
let stroke = (x: config.stroke-color + stroke-width)

if i == start {
radii.insert("top-left", config.radius)
radii.insert("top-right", config.radius)
stroke.insert("top", config.stroke-color + stroke-width)
}

if i == end {
radii.insert("bottom-left", config.radius)
radii.insert("bottom-right", config.radius)
stroke.insert("bottom", config.stroke-color + stroke-width)
}

radii.insert("rest", 0pt)

(radius: radii, stroke: stroke)
}

let width = if config.width-numbers == none { 0pt } else { config.width-numbers }
show raw.line: it => if not in_range(it.number) {
none
} else {
block(
width: 100%,
height: 1.2em + config.padding * 2,
inset: (left: config.padding + width, top: config.padding + 0.1em, rest: config.padding),
fill: if calc.rem(it.number, 2) == 0 {
config.zebra-color
} else {
white
},
radius: border(it.number, it.count).radius,
stroke: border(it.number, it.count).stroke,
{
if it.number == start {
place(
top + right,
language_block,
dy: -config.padding * 0.66666,
dx: config.padding * 0.66666 - 0.1em,
)
}

set par(justify: false)
if config.width-numbers != none {
place(
top + left,
dx: -config.width-numbers,
[#(offset + it.number)]
)
}
it
}
)
}

let stroke = if config.stroke-width == 0pt or config.stroke-width == none {
none
} else {
config.stroke-width + config.zebra-color
};

block(
breakable: config.breakable,
clip: false,
width: 100%,
stack(dir: ttb, ..it.lines)
)

codly-offset()
codly-range(start: 1, end: none)
})

body
}
Binary file added packages/preview/codly/0.1.0/demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions packages/preview/codly/0.1.0/example/brand-python.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions packages/preview/codly/0.1.0/example/brand-rust.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/preview/codly/0.1.0/example/main.pdf
Binary file not shown.
82 changes: 82 additions & 0 deletions packages/preview/codly/0.1.0/example/main.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#import "../codly.typ": *

#show: codly-init.with()

#let icon(codepoint) = {
box(
height: 0.8em,
baseline: 0.05em,
image(codepoint)
)
h(0.1em)
}

#codly(languages: (
rust: (name: "Rust", icon: icon("brand-python.svg"), color: rgb("#CE412B")),
python: (name: "Python", icon: icon("brand-rust.svg"), color: rgb("#3572A5")),
))
```rust
pub fn main() {
println!("Hello, world!");
}
```
```python
def fibonaci(n):
if n <= 1:
return n
else:
return(fibonaci(n-1) + fibonaci(n-2))
```
We can also set a line number offset with `codly-offset(int)`:
#codly-offset(offset: 1)
```rust
println!("Hello, world!");
```
And we can also disable line numbers:
#codly(width-numbers: none)
```rust
pub fn main() {
println!("Hello, world!");
}
```
We can also select only a range of lines to show:
#codly-range(start: 5, end: 5)
```python
def fibonaci(n):
if n <= 1:
return n
else:
return(fibonaci(n-1) + fibonaci(n-2))
```
#codly(
stroke-width: 1pt,
stroke-color: red,
)
```rust
pub fn main() {
println!("Hello, world!");
}
```
#codly(
display-icon: false,
)
```rust
pub fn main() {
println!("Hello, world!");
}
```
11 changes: 11 additions & 0 deletions packages/preview/codly/0.1.0/typst.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "codly"
version = "0.1.0"
entrypoint = "codly.typ"
authors = ["Dherse"]
license = "MIT"
description = "Codly is a beautiful code presentation template."
repository = "https://github.com/Dherse/codly"
exclude = ["example/*", "demo.png" ]
compiler = "0.9.0"
keywords = [ "code", "pretty", "template", "raw" ]

0 comments on commit dcbb9f6

Please sign in to comment.