Skip to content

Commit

Permalink
Merge pull request #68 from qmd-lab/feature-code-highlighting
Browse files Browse the repository at this point in the history
Feature highlighting
  • Loading branch information
andrewpbray authored Aug 6, 2024
2 parents a072936 + ae3e6ef commit b8618c5
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 6 deletions.
20 changes: 20 additions & 0 deletions _extensions/closeread/closeread.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion _extensions/closeread/closeread.css.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

76 changes: 74 additions & 2 deletions _extensions/closeread/closeread.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,80 @@ function updateStickies(allStickies, focusedStickyName, trigger) {

}


function highlightSpans(focusedSticky, triggerEl) {

// remove any previous highlighting
focusedSticky.querySelectorAll("span[id]").forEach(d => d.classList.remove("cr-hl"));
focusedSticky.classList.remove("cr-hl-within");

// get hightlighted spans from trigger
let highlightIds = triggerEl.getAttribute("data-highlight");

// exit function if there's no highlighting
if (highlightIds === null) {
return;
}

// turn a range of line numbers into a series
isRange = /\b(\d+)\s*-\s*(\d+)\b/;
if (isRange.test(highlightIds)) {
const match = highlightIds.match(isRange);

if (match) {
const start = parseInt(match[1], 10);
const end = parseInt(match[2], 10);
const numbers = [];

for (let i = start; i <= end; i++) {
numbers.push(i);
}

highlightIds = numbers.join(',');
} else {
return '';
}
}

// dim enclosing block
focusedSticky.classList.add("cr-hl-within");

// add highlight class to appropriate spans
highlightIds.split(',').forEach(highlightId => {
const trimmedId = highlightId.trim();
let spanSelector = "";

// determine the right spanSelector
// for line numbers
if (!isNaN(trimmedId)) {

// that are in line blocks
if (focusedSticky.querySelector('.line-block') !== null) {
spanSelector = `span[id^="lb"][id*="-${trimmedId}"]`;
}
// or in code cells
if (focusedSticky.querySelector('.cell') !== null) {
spanSelector = `span[id^="cb"][id*="-${trimmedId}"]`;
}

// and for span ids
} else {
spanSelector = `span[id="${trimmedId}"]`;
}

const highlightSpan = focusedSticky.querySelector(spanSelector);

if (highlightSpan !== null) {
highlightSpan.classList.add("cr-hl");
} else {
// Handle the case where the ID does not correspond to a span
console.warn(`While highlighting, could not find span with corresponding to an ID of '${trimmedId}'. Please ensure the ID is correct.`);
}
});

}


function highlightans(focusedSticky, triggerEl) {
// remove any previous highlighting from sticky
focusedSticky.querySelectorAll("span[id]").forEach(d => d.classList.remove("cr-hl"));
focusedSticky.classList.remove("cr-hl-within");
Expand All @@ -187,7 +259,7 @@ function highlightSpans(focusedSticky, triggerEl) {

// add highlight class to appropriate spans
highlightIds.split(',').forEach(highlightId => {
const trimmedId = highlightId.trim(); // Ensure no whitespace issues
const trimmedId = highlightId.trim();
const highlightSpan = focusedSticky.querySelector(`#${trimmedId}`);
if (highlightSpan !== null) {
highlightSpan.classList.add("cr-hl");
Expand Down
26 changes: 25 additions & 1 deletion _extensions/closeread/closeread.lua
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ end


--======================--
-- Lineblock Attributes --
-- Lineblock Processing --
--======================--

-- Append attributes to any cr line blocks
Expand Down Expand Up @@ -342,6 +342,27 @@ function extractClasses(el)
return classes
end

-- Wraps each line of a lineblock in a span with a particular id so that
-- the js can add highlight classes to particular lines
lineblock_ind = 0
function add_spans(lineblock)
lineblock_ind = lineblock_ind + 1

new_lb_content = pandoc.List({})
line_ind = 0
for _,inlines in ipairs(lineblock.content) do
line_ind = line_ind + 1
span_id = "lb" .. tostring(lineblock_ind) .. "-" .. tostring(line_ind)
double_wrapped_line = pandoc.Inlines(pandoc.Span(inlines, pandoc.Attr(span_id, {}, {})))
table.insert(new_lb_content, double_wrapped_line)
end

lineblock.content = new_lb_content

return lineblock
end



--===================--
-- Focus-on Shortcut --
Expand Down Expand Up @@ -441,6 +462,9 @@ return {
{
LineBlock = add_attributes
},
{
LineBlock = add_spans
},
{
Para = process_trigger_shortcut
},
Expand Down
42 changes: 41 additions & 1 deletion _extensions/closeread/closeread.scss
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,54 @@
font-size .8s ease-in-out;
}

// show active elements (this class is applied by scrollama
// show active stickies
.cr-active {
opacity: 1;

// -- Code Blocks -- //
// if the code cell contains highlighted code, dim it
&.cr-hl-within .sourceCode span[id^="cb"] {
opacity: .3;

transition:
opacity linear 0.3s;

// while keeping the highlighted lines bright
&.cr-hl{
opacity: 1;

transition:
opacity linear 0.3s;
}
}

// -- Line Blocks -- //
// if the line block contains highlighted lines, lighten text
&.cr-hl-within div.line-block span[id^="lb"]{
color: rgba(0, 0, 0, 0.4);

transition: color .7s linear;

// while keeping the highlighted lines black
&.cr-hl{
color: rgba(0, 0, 0, 1);

transition: color .7s linear;
}

// as well as any spans
span.cr-hl{
color: rgba(0, 0, 0, 1);

transition: color .7s linear;
}
}
}
}
}
}


/* mobile sizing (bootstrap: xs) is always overlay-center */
//@media (max-width: 575.98px) {
@media (max-width: 575.98px) {
Expand Down
1 change: 1 addition & 0 deletions docs/gallery/demos/minard-zoom/index.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ format:
closeread-html:
css: cr-tufte.css
remove-header-space: true
code-tools: true
---

# Mindard's Map
Expand Down
4 changes: 3 additions & 1 deletion docs/gallery/demos/ojs-map/index.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
title: "Spinning Globe"
image: "globe.png"
description: "Smoothly transition interactive OJS graphics."
format: closeread-html
format:
closeread-html:
code-tools: true
---

Closeread makes scrolling progress available to users as [Observable JavasScript](https://quarto.org/docs/interactive/ojs) variables, so you can create closeread sections with interactive graphics that change as you scroll.
Expand Down
13 changes: 13 additions & 0 deletions docs/guide/index.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ When this paragraph scrolls into view it will reveal my sticky. @cr-mysticky

The reference can be placed anywhere in the paragraph, but it should be separated from other content by spaces.

# Trigger Effects

## Highlighting

You can highlight parts of the code and text of your sticky using the following syntax.

1. `highlight="1,3"`: highlight lines 1 and 3
2. `highlight="1-3"`: highlight lines 1, 2, and 3
3. `highlight="cr-span1"`: highlight the span with id `cr-span1`
4. `highlight="cr-span1,cr-span2"`: highlight the spans with ids `cr-span1` and `cr-span2`

Line highlighting (1 and 2) works on code cells and line blocks while span highlighting (3 and 4) only works on Line Blocks.

# Layouts

The relative positioning of the narrative column and the sticky column determine the *layout*. You can set the layout of a section using the `layout` attribute on the block that defines the section.
Expand Down

0 comments on commit b8618c5

Please sign in to comment.