Skip to content

Add canvas functions to ranges rebase - #181

Open
marlo-longley wants to merge 4 commits into
IIIF-Commons:mainfrom
marlo-longley:add-canvas-functions-to-ranges-rebase
Open

Add canvas functions to ranges rebase#181
marlo-longley wants to merge 4 commits into
IIIF-Commons:mainfrom
marlo-longley:add-canvas-functions-to-ranges-rebase

Conversation

@marlo-longley

Copy link
Copy Markdown

This rebases #79

- Create getCanvases, getCanvasById, getCanvasByIndex functions for the range type
sequence to range as well
- Add test for getCanvasById range
... index to each canvas in range
... ranges when getting canvases
@codesandbox

codesandbox Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@demiankatz demiankatz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @marlo-longley -- I didn't fully review all of the code (some of the new logic in Range.ts is pretty complex, and it will take me more time than I have available today to thoroughly study it), but please see below for a few comments and suggestions that I hope will be helpful!

Comment thread src/Manifest.ts
Comment on lines +177 to +178
(item["type"] && item["type"].toLowerCase() === "canvas") ||
(item["type"] && item["type"].toLowerCase() === "specificresource")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe slightly more concise/efficient?

Suggested change
(item["type"] && item["type"].toLowerCase() === "canvas") ||
(item["type"] && item["type"].toLowerCase() === "specificresource")
(item["type"] && ["canvas", "specificresource"].includes(item["type"].toLowerCase()))

Comment thread src/Manifest.ts

const id: string = item.id || item["@id"];
const id: string = item.id || item["@id"] || item["source"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to treat a specificResource as a canvas, and to accept id and source interchangeably like this? Or should we do different things based on type for tighter validation? (I confess that I know very little about the use case here, so I'm just asking in general terms).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specific resource might be a canvas with a selector: https://iiif.io/api/cookbook/recipe/0025-newspaper-article-index/

{
  "type": "SpecificResource",
  "source": {
    "id": "https://iiif.io/api/cookbook/recipe/0025-newspaper-article-index/canvas/p2",
    "type": "Canvas"
  },
  "selector": {
    "type": "FragmentSelector",
    "value": "xywh=553,1157,470,1103"
  }
}

But worth noting that source can be a string or a record with id/type

Comment thread src/Range.ts
} from "@iiif/vocabulary/dist-commonjs";

export class Range extends ManifestResource {
private _canvases: Canvas[] | null = null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not ideal to have _canvases and canvases as two distinct things. I think the "most correct" thing would be to rename canvases to canvasIds`, but that would be a breaking change, so we probably shouldn't do it for now. I wonder if there's something else we can do to make this less potentially confusing, though.

Comment thread src/Range.ts
getTopRange(range) {
let parentRange = range.parentRange;
if (parentRange) {
this.getTopRange(parentRange);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a return here? Do we need to worry about malformed data causing an infinite loop?

Comment thread src/Range.ts
Comment on lines +163 to +204
// Alternative solution can be this
/* getTopLevelCanvases(): Canvas[] {
if(this._canvases){
return this._canvases;
}

if (this.items.length) {
let canvasItems: Canvas[] = [];
for (let i = 0; i < this.items.length; i++) {
if (this.items[i].isCanvas()) {
canvasItems.push(<Canvas>this.items[i]);
}
}
return this._canvases = canvasItems;
}

let items = this.__jsonld.items || this.__jsonld.elements;

if (items) {
for (let i = 0; i < items.length; i++) {
if (items[i].type.includes("Canvas")) {
const c = items[i];
const canvas: Canvas = new Canvas(c, this.options);
canvas.index = i;
this.items.push(canvas);
}
}
} else if (this.__jsonld) {
for (let i = 0; i < this.__jsonld.length; i++) {
if (items[i].type.includes("Canvas")) {
const c = this.__jsonld[i];
const canvas: Canvas = new Canvas(c, this.options);
canvas.index = i;
this.items.push(canvas);
}
}
}

return this._canvases = <Canvas[]>this.items;
}
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want to put all of this commented-out code in the finished product. Do we need to weigh options and make choices?

Comment thread src/Sequence.ts
}

const items = this.__jsonld.canvases || this.__jsonld.elements;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's worth undoing this whitespace-only change to avoid a superfluous file change in the PR.

@marlo-longley

Copy link
Copy Markdown
Author

@demiankatz thanks for looking!
Since I didn't write this code, just rebased it, my understanding isn't super deep, it will probably take me some time to be able to understand and make changes. I will do my best to work on this soon, but I feel no ownership/attachment if anyone else wants to make changes.

@demiankatz

Copy link
Copy Markdown
Contributor

Sounds like we're all in the same boat, @marlo-longley! :-)

Comment thread src/Range.ts

private _parseTreeNode(node: TreeNode, range: Range): void {
node.label = <string>range.getLabel().getValue(this.options.locale);
node.label = < string > range.getLabel().getValue(this.options.locale);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few formatting issues like this, although valid we should be consistent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants