Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display images in markdown with support for lakefs:// URIs #5449

Merged
merged 10 commits into from
Mar 14, 2023

Conversation

eladlachmi
Copy link
Contributor

Resolves #5366

This PR adds support for lakefs:// URIs in markdown images and resolving them to pre-signed URLs for display in the browser. This works for all markdown files, not README.md exclusively. The initial markup (incl. lakefs:// URIs) is immediately displayed and is replaced once pre-signed URLs are generated. This means the process doesn't hold up the rendering of the repository view and also doesn't affect markdown files that don't include images with lakefs:// URIs.

This PR also replaces jest with vitest for easier integration with Vite.

@eladlachmi eladlachmi added include-changelog PR description should be included in next release changelog team/cloud-native Team cloud native labels Mar 12, 2023
@eladlachmi eladlachmi self-assigned this Mar 12, 2023
Copy link
Contributor

@itaiad200 itaiad200 left a comment

Choose a reason for hiding this comment

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

Very cool! couple of questions/comments.

for (const image of images) {
const [repo, branch, ...path] = image.url.split("/").slice(2);
const promise = objects
.getPresignedUrl(repo, branch, path.join("/"))
Copy link
Contributor

Choose a reason for hiding this comment

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

What if presigned URLs is not enabled for the installation?

Copy link
Contributor

Choose a reason for hiding this comment

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

Like you can still read the images even if presign urls are not available, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@itaiad200 This assumes pre-signed URLs are enabled. If not, I could add an alternative to download the file and convert it to a base64 data URL. Do you think that's needed?

Copy link
Contributor

Choose a reason for hiding this comment

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

How can it assumes presigned is enabled if some installations (local, mem) don't support that at all and in other (Azure) it depends on the configuration?
We have a way to check a installation/repo for presigned support (as it's part of the settings). We can add the images support for repos without presigned urls later, as long as we handle these repos nicely for now, i.e. don't try to embed images for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see... I did not consider that... 🤔
I'll see if I can construct data URLs to support installations without presigned URLs.
We also need to know if presigned URLs are available on the client
Maybe it's time to add a "supported features" or "configuration" endpoint so the client is aware of what's available/supported/enabled/disabled/etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Replaced presigned URLs with "regular" URLs. This also simplifies several other things.

const imageUriReplacer: Plugin<[], Root> = () => async (tree) => {
const images: Array<Node & { url: string }> = [];
visit(tree, "image", (node: Node & { url: string }) => {
if (node.url.startsWith("lakefs://")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What about relative paths? I think that's the more common case. Our readme for example:

    <img src="docs/assets/img/logo_large.png"/>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll add relative URL support, but I must make some assumptions.
When the URL starts with lakefs://, the format is lakefs://{repo}/{branch}/...{path}
Regarding relative URLs, I'll assume it's relative to the current repo and branch. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added relative URL support + relevant tests

Copy link
Contributor

@itaiad200 itaiad200 Mar 13, 2023

Choose a reason for hiding this comment

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

I think your assumptions are spot on.

Copy link
Contributor

Choose a reason for hiding this comment

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

Just ref instead of branch 🙈

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍🏻


const imageUriReplacer: Plugin<[], Root> = () => async (tree) => {
const images: Array<Node & { url: string }> = [];
visit(tree, "image", (node: Node & { url: string }) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't img a valid image label too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In markdown, an image node is ![alt](URL). Not sure if this AST matches HTML <img /> tags as well. I'll need to check.

Copy link
Contributor Author

@eladlachmi eladlachmi Mar 12, 2023

Choose a reason for hiding this comment

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

@itaiad200 It looks like it does not match HTML within MD. This means I'd need to parse HTML nodes manually, and I would rather not since it could lead to many edge cases, which this AST was supposed to spare us.

I think it's legit to say that we support MD image tags for automated resolution, at least for now.
WDYT?

webui/src/lib/api/index.js Outdated Show resolved Hide resolved
@eladlachmi eladlachmi requested a review from itaiad200 March 12, 2023 18:07
Copy link
Contributor

@itaiad200 itaiad200 left a comment

Choose a reason for hiding this comment

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

Getting closer 💪 See my comments...

});

describe("imageUriReplacer", async () => {
let mockObjects: any;
Copy link
Contributor

Choose a reason for hiding this comment

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

Notice the warning here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I'm aware. Since it's a spec file and figuring out the TS support of vitest mocks was taking an unproportionate amount of time, I left it this way (at least for now)

Copy link
Contributor

Choose a reason for hiding this comment

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

I honestly don't know what that means and I understand it has 0 impact on anything important. If I remember this linter behavior, it will now present this warning for any PR (even non-UI related) until it's fixed, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed it, so no more warning

const imageUriReplacer: Plugin<[], Root> = () => async (tree) => {
const images: Array<Node & { url: string }> = [];
visit(tree, "image", (node: Node & { url: string }) => {
if (node.url.startsWith("lakefs://")) {
Copy link
Contributor

@itaiad200 itaiad200 Mar 13, 2023

Choose a reason for hiding this comment

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

I think your assumptions are spot on.

for (const image of images) {
const [repo, branch, ...path] = image.url.split("/").slice(2);
const promise = objects
.getPresignedUrl(repo, branch, path.join("/"))
Copy link
Contributor

Choose a reason for hiding this comment

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

How can it assumes presigned is enabled if some installations (local, mem) don't support that at all and in other (Azure) it depends on the configuration?
We have a way to check a installation/repo for presigned support (as it's part of the settings). We can add the images support for repos without presigned urls later, as long as we handle these repos nicely for now, i.e. don't try to embed images for now.

if (node.url.startsWith("/")) {
node.url = node.url.slice(1);
}
node.url = `lakefs://${options.repo}/${options.branch}/${node.url}`;
Copy link
Contributor

Choose a reason for hiding this comment

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

I think options.ref is better. It can also be a commit or a tag.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@eladlachmi eladlachmi requested a review from itaiad200 March 13, 2023 08:35
@eladlachmi eladlachmi force-pushed the 5366-display-images-in-markdown branch from f35a593 to 7514033 Compare March 13, 2023 13:45
Copy link
Contributor

@itaiad200 itaiad200 left a comment

Choose a reason for hiding this comment

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

Yay!

@eladlachmi eladlachmi merged commit 34c243b into master Mar 14, 2023
@eladlachmi eladlachmi deleted the 5366-display-images-in-markdown branch March 14, 2023 08:38
"remark-gfm": "^3.0.1",
"remark-html": "^15.0.1",
"unist": "^8.0.11",
Copy link
Collaborator

Choose a reason for hiding this comment

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

@eladlachmi this line fails npm install for me. Couldn't find it on NPM manually either.

Additionally, I think this PR also introduces a package-lock.json file at the root of the repository (i.e. not under webui/) by mistake..

Jonathan-Rosenberg pushed a commit that referenced this pull request Mar 15, 2023
* Display images in markdown with support for lakefs:// URIs
nopcoder pushed a commit that referenced this pull request Mar 20, 2023
* Display images in markdown with support for lakefs:// URIs
Jonathan-Rosenberg added a commit that referenced this pull request Mar 22, 2023
* Display images in markdown with support for lakefs:// URIs (#5449)

* Display images in markdown with support for lakefs:// URIs

* change dockerfile to include delta diff

* change Dockerfile to include the Delta Lake diff plugin

* fix docker-compose files

* add a stage with both lakefs and plugins and separate it from a lakefs-only stage

* PR fixes

* Delta Lake Diff: Enable feature (#5508)

* fix hover issue when hovering over a tree-entry-row

* enable Delta Lake diff feature

* remove experimental delta diff button

* PR fixes

* change docker image publish target to lakefs-plugins

* fix bug hunt bugs (#5534)

* remove empty line

* Delta Lake: Update Dockerfile base images to Alpine (#5546)

* change the Dockerfile back to Alpine and build the Delta plugin dynamically

* remove alpine-sdk from dockerfile

* add alpine-sdk

* add comment about the 'RUSTFLAGS=-Ctarget-feature=-crt-static' flag

* change back from bullseye to alpine

---------

Co-authored-by: eladlachmi <110764839+eladlachmi@users.noreply.github.com>
Jonathan-Rosenberg added a commit that referenced this pull request Mar 22, 2023
* change default behavior of plugin loading to scan in the default plugins directory for known plugins

* get delta lake diff plugin from default path if available

* add homedir.Expand call to custom plugin path

* remove empty line

Co-authored-by: Barak Amar <barak.amar@treeverse.io>

* change version from a pointer to an int

* Delta Lake Diff: Dockerfile (#5496)

* Display images in markdown with support for lakefs:// URIs (#5449)

* Display images in markdown with support for lakefs:// URIs

* change dockerfile to include delta diff

* change Dockerfile to include the Delta Lake diff plugin

* fix docker-compose files

* add a stage with both lakefs and plugins and separate it from a lakefs-only stage

* PR fixes

* Delta Lake Diff: Enable feature (#5508)

* fix hover issue when hovering over a tree-entry-row

* enable Delta Lake diff feature

* remove experimental delta diff button

* PR fixes

* change docker image publish target to lakefs-plugins

* fix bug hunt bugs (#5534)

* remove empty line

* Delta Lake: Update Dockerfile base images to Alpine (#5546)

* change the Dockerfile back to Alpine and build the Delta plugin dynamically

* remove alpine-sdk from dockerfile

* add alpine-sdk

* add comment about the 'RUSTFLAGS=-Ctarget-feature=-crt-static' flag

* change back from bullseye to alpine

---------

Co-authored-by: eladlachmi <110764839+eladlachmi@users.noreply.github.com>

---------

Co-authored-by: Barak Amar <barak.amar@treeverse.io>
Co-authored-by: eladlachmi <110764839+eladlachmi@users.noreply.github.com>
Jonathan-Rosenberg added a commit that referenced this pull request Mar 22, 2023
* add makefile target to build delta diff plugin

* test goreleaser  with rust

* remove cache step

* add activate on push to this branch

* change working-directory

* remove working-directory

* remove target from args

* add protoc for mac and name steps

* add version to protoc action

* switch from Arduino

* use correct version

* change back to arduino

* change version to 3.x

* add protoc to unix and windows

* change version to 3.x

* change to release, upload artifact

* downloading artifacts

* add needs to releaser

* add build

* move --release to arguments

* fix artifact location

* fix naming

* add cache

* add .exe suffix to windows build target

* add id to the download artifact step

* add registry and index to cache

* add renaming of artifacts

* move download-artifacts to the goreleaser job

* change cache support to use custom action

* run goreleaser without truly releasing

* fix goreleaser

* change delta artifact location

* fix releaser yaml

* change releaser to be production ready

* change from 3 jobs definitions to a single job definition with a more complex matrix

* fix makefile

* Delta Lake Diff: Change default plugin loading (#5495)

* change default behavior of plugin loading to scan in the default plugins directory for known plugins

* get delta lake diff plugin from default path if available

* add homedir.Expand call to custom plugin path

* remove empty line

Co-authored-by: Barak Amar <barak.amar@treeverse.io>

* change version from a pointer to an int

* Delta Lake Diff: Dockerfile (#5496)

* Display images in markdown with support for lakefs:// URIs (#5449)

* Display images in markdown with support for lakefs:// URIs

* change dockerfile to include delta diff

* change Dockerfile to include the Delta Lake diff plugin

* fix docker-compose files

* add a stage with both lakefs and plugins and separate it from a lakefs-only stage

* PR fixes

* Delta Lake Diff: Enable feature (#5508)

* fix hover issue when hovering over a tree-entry-row

* enable Delta Lake diff feature

* remove experimental delta diff button

* PR fixes

* change docker image publish target to lakefs-plugins

* fix bug hunt bugs (#5534)

* remove empty line

* Delta Lake: Update Dockerfile base images to Alpine (#5546)

* change the Dockerfile back to Alpine and build the Delta plugin dynamically

* remove alpine-sdk from dockerfile

* add alpine-sdk

* add comment about the 'RUSTFLAGS=-Ctarget-feature=-crt-static' flag

* change back from bullseye to alpine

---------

Co-authored-by: eladlachmi <110764839+eladlachmi@users.noreply.github.com>

---------

Co-authored-by: Barak Amar <barak.amar@treeverse.io>
Co-authored-by: eladlachmi <110764839+eladlachmi@users.noreply.github.com>

---------

Co-authored-by: Barak Amar <barak.amar@treeverse.io>
Co-authored-by: eladlachmi <110764839+eladlachmi@users.noreply.github.com>
nopcoder added a commit that referenced this pull request Apr 17, 2023
* add makefile target to build delta diff plugin

* test goreleaser  with rust

* remove cache step

* add activate on push to this branch

* change working-directory

* remove working-directory

* remove target from args

* add protoc for mac and name steps

* add version to protoc action

* switch from Arduino

* use correct version

* change back to arduino

* change version to 3.x

* add protoc to unix and windows

* change version to 3.x

* change to release, upload artifact

* downloading artifacts

* add needs to releaser

* add build

* move --release to arguments

* fix artifact location

* fix naming

* add cache

* add .exe suffix to windows build target

* add id to the download artifact step

* add registry and index to cache

* add renaming of artifacts

* move download-artifacts to the goreleaser job

* change cache support to use custom action

* run goreleaser without truly releasing

* fix goreleaser

* change delta artifact location

* fix releaser yaml

* change releaser to be production ready

* change from 3 jobs definitions to a single job definition with a more complex matrix

* fix makefile

* Delta Lake Diff: Change default plugin loading (#5495)

* change default behavior of plugin loading to scan in the default plugins directory for known plugins

* get delta lake diff plugin from default path if available

* add homedir.Expand call to custom plugin path

* remove empty line

Co-authored-by: Barak Amar <barak.amar@treeverse.io>

* change version from a pointer to an int

* Delta Lake Diff: Dockerfile (#5496)

* Display images in markdown with support for lakefs:// URIs (#5449)

* Display images in markdown with support for lakefs:// URIs

* change dockerfile to include delta diff

* change Dockerfile to include the Delta Lake diff plugin

* fix docker-compose files

* add a stage with both lakefs and plugins and separate it from a lakefs-only stage

* PR fixes

* Delta Lake Diff: Enable feature (#5508)

* fix hover issue when hovering over a tree-entry-row

* enable Delta Lake diff feature

* remove experimental delta diff button

* PR fixes

* change docker image publish target to lakefs-plugins

* fix bug hunt bugs (#5534)

* remove empty line

* Delta Lake: Update Dockerfile base images to Alpine (#5546)

* change the Dockerfile back to Alpine and build the Delta plugin dynamically

* remove alpine-sdk from dockerfile

* add alpine-sdk

* add comment about the 'RUSTFLAGS=-Ctarget-feature=-crt-static' flag

* change back from bullseye to alpine

---------

Co-authored-by: eladlachmi <110764839+eladlachmi@users.noreply.github.com>

---------

Co-authored-by: Barak Amar <barak.amar@treeverse.io>
Co-authored-by: eladlachmi <110764839+eladlachmi@users.noreply.github.com>

---------

Co-authored-by: Barak Amar <barak.amar@treeverse.io>
Co-authored-by: eladlachmi <110764839+eladlachmi@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
include-changelog PR description should be included in next release changelog team/cloud-native Team cloud native
Projects
None yet
Development

Successfully merging this pull request may close these issues.

display images in README.md
3 participants