Skip to content

Commit

Permalink
Merge pull request #35 from coatless-quarto/quarto-extension
Browse files Browse the repository at this point in the history
feat: countdown as a Quarto shortcode extension!
  • Loading branch information
gadenbuie committed Feb 5, 2024
2 parents 9ee6b7f + 34ec998 commit f06b4ad
Show file tree
Hide file tree
Showing 14 changed files with 1,146 additions and 10 deletions.
35 changes: 35 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Config options: https://github.com/rocker-org/devcontainer-templates/tree/main/src/r-ver
{
"name": "R (rocker/r-ver base)",
"image": "ghcr.io/rocker-org/devcontainer/r-ver:4.3",
// Add software
"features": {
// Required to test with knitr
// R package config: https://github.com/rocker-org/devcontainer-features/blob/main/src/r-rig/README.md
"ghcr.io/rocker-org/devcontainer-features/r-rig:1": {
"version": "none",
"installRMarkdown": true,
"installJupyterlab": true,
"installRadian": true
},
// You may wish to switch prerelease to latest for stable development
// Quarto configuration : https://github.com/rocker-org/devcontainer-features/blob/main/src/quarto-cli/README.md
"ghcr.io/rocker-org/devcontainer-features/quarto-cli:1": {
"version": "prerelease"
}
},
"customizations": {
"vscode": {
"settings": {
"r.rterm.linux": "/usr/local/bin/radian",
"r.bracketedPaste": true,
"r.plot.useHttpgd": true,
"[r]": {
"editor.wordSeparators": "`~!@#%$^&*()-=+[{]}\\|;:'\",<>/?"
}
},
// Enable a development set of extensions for Lua and Quarto
"extensions": ["quarto.quarto", "sumneko.lua", "GitHub.copilot"]
}
}
}
2 changes: 2 additions & 0 deletions .github/workflows/R-CMD-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches: [main, master]
pull_request:
branches: [main, master]
workflow_dispatch: {}

name: R-CMD-check

Expand Down Expand Up @@ -45,6 +46,7 @@ jobs:
needs: check
working-directory: r


- uses: r-lib/actions/check-r-package@v2
with:
upload-snapshots: true
Expand Down
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
.DS_Store

# Directories that start with _
_*/
!_snaps/
_dev/

## https://github.com/github/gitignore/blob/master/R.gitignore
# History files
Expand Down Expand Up @@ -74,3 +73,6 @@ Icon
Network Trash Folder
Temporary Items
.apdisk

/.luarc.json
*.luarc.json
2 changes: 0 additions & 2 deletions LICENSE

This file was deleted.

2 changes: 1 addition & 1 deletion lib/countdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ class CountdownTimer {

playSound () {
let url = this.play_sound
if (!url) return
if (!url || url === "false") return
if (typeof url === 'boolean') {
const src = this.src_location
? this.src_location.replace('/countdown.js', '')
Expand Down
3 changes: 3 additions & 0 deletions quarto/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.html
*.pdf
*_files/
95 changes: 91 additions & 4 deletions quarto/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# quarto-countdown: A Quarto Extension for Countdown
# quarto-countdown: Countdown Timers for Quarto RevealJS slides

The `countdown` extension allows you to incorporate countdown like timers on Quarto HTML Documents and RevealJS slides.
The `quarto-countdown` extension for [Quarto](https://quarto.org) allows you to incorporate countdown timers on [Quarto RevealJS slides](https://quarto.org/docs/presentations/revealjs/).

This extension can be used without installing R or the `{countdown}` R Package.
This extension doesn't require the installation of _R_ or the `{countdown}` _R_ Package.

## Installation

Expand All @@ -20,13 +20,100 @@ This command will download and install the extension under the `_extensions` sub

## Usage

To embed a countdown clock, use the `{{< countdown >}}` shortcode. For example:
To embed a countdown clock, use the `{{< countdown >}}` shortcode. For example, a countdown clock can be created by writing anywhere:

```default
{{< countdown >}}
```

For a longer or shorter countdown, specify the `minutes` and `seconds` options:

```default
{{< countdown minutes=5 seconds=30 >}}
```

Or use a time string formatted in `"MM:SS"`

```default
{{< countdown "5:30" >}}
```

There are many more customizations to choose from. See the next section for more details.

### Customizations

The extension offers extensive customization options, akin to the features provided by the R package version of `countdown`. These customizations span both functionality and style. They can be configured either at the document level or for each individual timer.

#### In-line options

The `countdown` timer shortcode has a variety of customizations that can be set. The customizations can be split between functionality and style.

The functionality options are:

| Option | Default Value | Description |
| ------------------- | ------------------------------- | ------------------------------------------------------------------------- |
| `minutes` | `1` | Number of minutes with a total cap of 100 minutes |
| `seconds` | `0` | Number of seconds |
| `id` | A generated, unique ID | ID attribute of the HTML element. |
| `class` | "countdown" | Class attribute of the HTML element. |
| `warn_when` | `0` | Number of seconds before the countdown displays a warning. |
| `update_every` | `1` | Frequency at which the countdown should be updated, in seconds. |
| `play_sound` | `"false"` | Boolean indicating whether to play a sound during the countdown. |
| `blink_colon` | `"false"` | Boolean indicating whether the colon in the countdown should blink. |
| `start_immediately` | `"false"` | Boolean indicating whether the countdown should start immediately. |

The style options are:

| Style Option | Default Value | Description |
| ------------- | ---------------------------- | ------------------------------------------------------------------------- |
| `top` | `""` (empty) | Top position of the HTML element. |
| `right` | `"0"` | Right position of the HTML element. |
| `bottom` | `"0"` | Bottom position of the HTML element. |
| `left` | `""` (empty) | Left position of the HTML element. |
| `margin` | `"0.6em"` | Margin around the HTML element. |
| `padding` | `"10px 15px"` | Padding within the HTML element. |
| `font-size` | `"3rem"` | Font size of the HTML element. |
| `line-height` | `"1"` | Line height of the HTML element. |
| `style` | Computed based on attributes | String constructed based on style-related attributes of the HTML element. |

#### Document-level Options

Document-level options can be specified in the document's header using a YAML key-value format:

```yaml
---
title: "Example document-level settings"
countdown:
option: value
---
```

The following options are implemented:

| Option | Default Value | Description |
| --------------------------- | ------------------------------------------ | ------------------------------------------------- |
| `font_size` | `"3rem"` | Font size for the countdown element |
| `margin` | `"0.6em"` | Margin around the countdown element |
| `padding` | `"10px 15px"` | Padding within the countdown element |
| `box_shadow` | `"0px 4px 10px 0px rgba(50, 50, 50, 0.4)"` | Shadow applied to the countdown element |
| `border_width` | `"0.1875rem"` | Border width of the countdown element |
| `border_radius` | `"0.9rem"` | Border radius of the countdown element |
| `line_height` | `"1"` | Line height of the countdown element |
| `color_border` | `"#ddd"` | Border color of the countdown element |
| `color_background` | `"inherit"` | Background color of the countdown element |
| `color_text` | `"inherit"` | Text color of the countdown element |
| `color_running_background` | `"#43AC6A"` | Background color when the countdown is running |
| `color_running_border` | `"#2A9B59FF"` | Border color when the countdown is running |
| `color_running_text` | `"inherit"` | Text color when the countdown is running |
| `color_finished_background` | `"#F04124"` | Background color when the countdown is finished |
| `color_finished_border` | `"#DE3000FF"` | Border color when the countdown is finished |
| `color_finished_text` | `"inherit"` | Text color when the countdown is finished |
| `color_warning_background` | `"#E6C229"` | Background color when the countdown has a warning |
| `color_warning_border` | `"#CEAC04FF"` | Border color when the countdown has a warning |
| `color_warning_text` | `"inherit"` | Text color when the countdown has a warning |
| `selector` | `"root"` | Selector for the countdown element |


## Example

You can see a minimal example of the extension in action here: [example.qmd](example.qmd).
Expand Down
8 changes: 8 additions & 0 deletions quarto/_extensions/countdown/_extension.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
title: countdown
author: Garrick Aden-Buie and James Joseph Balamuta
version: 0.0.0-dev.1
quarto-required: ">=1.4.0"
contributes:
shortcodes:
- countdown.lua

175 changes: 175 additions & 0 deletions quarto/_extensions/countdown/assets/countdown.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
.countdown {
--_margin: 0.6em;
--_running-color: var(--countdown-color-running-text, rgba(0, 0, 0, 0.8));
--_running-background: var(--countdown-color-running-background, #43AC6A);
--_running-border-color: var(--countdown-color-running-border, rgba(0, 0, 0, 0.1));
--_finished-color: var(--countdown-color-finished-text, rgba(0, 0, 0, 0.7));
--_finished-background: var(--countdown-color-finished-background, #F04124);
--_finished-border-color: var(--countdown-color-finished-border, rgba(0, 0, 0, 0.1));

position: absolute;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
background: var(--countdown-color-background, inherit);
font-size: var(--countdown-font-size, 3rem);
line-height: var(--countdown-line-height, 1);
border-color: var(--countdown-color-border, #ddd);
border-width: var(--countdown-border-width, 0.1875rem);
border-style: solid;
border-radius: var(--countdown-border-radius, 0.9rem);
box-shadow: var(--countdown-box-shadow, 0px 4px 10px 0px rgba(50, 50, 50, 0.4));
margin: var(--countdown-margin, var(--_margin, 0.6em));
padding: var(--countdown-padding, 0.625rem 0.9rem);
text-align: center;
z-index: 10;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

.countdown.inline {
position: relative;
width: max-content;
max-width: 100%;
}

.countdown .countdown-time {
background: none;
font-size: 100%;
padding: 0;
color: currentColor;
}

.countdown-digits {
color: var(--countdown-color-text);
}

.countdown.running {
border-color: var(--_running-border-color);
background-color: var(--_running-background);
}

.countdown.running .countdown-digits {
color: var(--_running-color);
}

.countdown.finished {
border-color: var(--_finished-border-color);
background-color: var(--_finished-background);
}

.countdown.finished .countdown-digits {
color: var(--_finished-color);
}

.countdown.running.warning {
border-color: var(--countdown-color-warning-border, rgba(0, 0, 0, 0.1));
background-color: var(--countdown-color-warning-background, #E6C229);
}

.countdown.running.warning .countdown-digits {
color: var(--countdown-color-warning-text, rgba(0, 0, 0, 0.7));
}

.countdown.running.blink-colon .countdown-digits.colon {
opacity: 0.1;
}

/* ------ Controls ------ */
.countdown:not(.running) .countdown-controls,
.countdown.no-controls .countdown-controls {
display: none;
}

.countdown-controls {
position: absolute;
top: -0.5rem;
right: -0.5rem;
left: -0.5rem;
display: flex;
justify-content: space-between;
margin: 0;
padding: 0;
}

.countdown-controls>button {
position: relative;
font-size: 1.5rem;
width: 1rem;
height: 1rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: monospace;
padding: 10px;
margin: 0;
background: inherit;
border: 2px solid;
border-radius: 100%;
transition: 50ms transform ease-in-out, 150ms opacity ease-in;
box-shadow: 0px 2px 5px 0px rgba(50, 50, 50, 0.4);
-webkit-box-shadow: 0px 2px 5px 0px rgba(50, 50, 50, 0.4);
--_button-bump: 0;
opacity: var(--_opacity, 0);
transform: translate(0, var(--_button-bump));
}

/* increase hit area of the +/- buttons */
.countdown .countdown-controls > button::after {
content: "";
height: 200%;
width: 200%;
position: absolute;
border-radius: 50%;
}

.countdown .countdown-controls>button:last-child {
color: var(--_running-color);
background-color: var(--_running-background);
border-color: var(--_running-border-color);
}

.countdown .countdown-controls>button:first-child {
color: var(--_finished-color);
background-color: var(--_finished-background);
border-color: var(--_finished-border-color);
}

.countdown.running:hover, .countdown.running:focus-within {
--_opacity: 1;
}

.countdown.running:hover .countdown-controls>button,
.countdown.running:focus-within .countdown-controls>button {
--_button-bump: -3px;
}

.countdown.running:hover .countdown-controls>button:active,
.countdown.running:focus-within .countdown-controls>button:active {
--_button-bump: 0;
}

/* ---- Quarto Reveal.js ---- */
.reveal .countdown {
--_margin: 0;
}

/* ----- Fullscreen ----- */
.countdown.countdown-fullscreen {
z-index: 0;
}

.countdown-fullscreen.running .countdown-controls {
top: 1rem;
left: 0;
right: 0;
justify-content: center;
}

.countdown-fullscreen.running .countdown-controls>button+button {
margin-left: 1rem;
}
Loading

0 comments on commit f06b4ad

Please sign in to comment.