Representing hyperlinks in Pollen #27

Open
opened 4 years ago by basus · 15 comments
basus commented 4 years ago (Migrated from github.com)

I was wondering how people represent hyperlinks in Pollen. Currently I have the following tag functions for general links, and internal (same site) links:

(define (link url . text)
  `(a ((href ,url)) ,@text))

(define (internal url . text)
  (let ([url (string-append "/" url)])
    `(a ((href ,url)) ,@text)))

So I can write links as ◊link["https://link.url"]{Link Text}. It's a little suboptimal since I have to wrap the URL in quotes. I also don't handle alt text or such. Any other ideas for how to represent links?

I was wondering how people represent hyperlinks in Pollen. Currently I have the following tag functions for general links, and internal (same site) links: ```racket (define (link url . text) `(a ((href ,url)) ,@text)) (define (internal url . text) (let ([url (string-append "/" url)]) `(a ((href ,url)) ,@text))) ``` So I can write links as `◊link["https://link.url"]{Link Text}`. It's a little suboptimal since I have to wrap the URL in quotes. I also don't handle alt text or such. Any other ideas for how to represent links?
ergl commented 4 years ago (Migrated from github.com)

The only fancy thing is have an option for links that should open in a new tab:

(define (l addr #:ext [external #f] . contents)
  (define attrs (if external
                    `((href ,addr) (target "_blank") (rel "noopener") (class "external"))
                    `((href ,addr))))
  (if (empty? contents)
    `(a ,attrs ,addr)
    `(a ,attrs ,@contents)))

Ideally I'd like to avoid quoting the url part, but I haven't bothered too much with it

The only fancy thing is have an option for links that should open in a new tab: ```racket (define (l addr #:ext [external #f] . contents) (define attrs (if external `((href ,addr) (target "_blank") (rel "noopener") (class "external")) `((href ,addr)))) (if (empty? contents) `(a ,attrs ,addr) `(a ,attrs ,@contents))) ``` Ideally I'd like to avoid quoting the url part, but I haven't bothered too much with it
oldmankit commented 4 years ago (Migrated from github.com)

Extending what @ergl gives but for alt text:

(define (link url #:alt [alt #f] . text)
  (define attrs
    (if alt
       `((href ,url) (alt ,alt))
       `((href ,url) (alt ,@text)))) ; If no alt is given, use the text contents as alt

  (if (empty? text)
    `(a ,attrs ,url)
    `(a ,attrs ,@text)))

You could use this pattern for any properties you liked.

Personally speaking, when I started writing text in Pollen I thought it would be nice not to need quotation marks around the url of links because it somehow feels sub-optimal, but I got used to it very quickly. Now that I'm used to the syntax it would feel strange not to have them in there.

Extending what @ergl gives but for alt text: ```racket (define (link url #:alt [alt #f] . text) (define attrs (if alt `((href ,url) (alt ,alt)) `((href ,url) (alt ,@text)))) ; If no alt is given, use the text contents as alt (if (empty? text) `(a ,attrs ,url) `(a ,attrs ,@text))) ``` You could use this pattern for any properties you liked. Personally speaking, when I started writing text in Pollen I thought it would be nice not to need quotation marks around the url of links because it somehow feels sub-optimal, but I got used to it very quickly. Now that I'm used to the syntax it would feel strange not to have them in there.
mbutterick commented 4 years ago (Migrated from github.com)

If no alt is given, use the text contents as alt

Beware — despite the name, text is a list of X-expression elements. If it contains more than one item, or something other than a string (say, another tagged X-expression) your alt attribute will be invalid.

Since your attribute value needs to be a single string, you’d want to extract the strings within text and concatenate them, perhaps like so:

(apply string-append (findf*-txexpr (cons '@ text) string?))

> If no alt is given, use the text contents as alt Beware — despite the name, `text` is a list of X-expression elements. If it contains more than one item, or something other than a string (say, another tagged X-expression) your `alt` attribute will be invalid. Since your attribute value needs to be a single string, you’d want to extract the strings within `text` and concatenate them, perhaps like so: `(apply string-append (findf*-txexpr (cons '@ text) string?))`
otherjoel commented 4 years ago (Migrated from github.com)

In my current project, I specify all links reference-style, e.g.:

#lang pollen

If you need help, ◊link[1]{Google it}.

◊url[1]{https://google.com}

The implementation can be seen here. It’s probably more complicated than most people want, but hey, there are no quote marks around the urls. (Never thought about that before to be honest!) I just like not having inline URLs breaking up the prose.

Under this implementation, you can put the url tag for a given identifier anywhere in the document, even before it is referenced. If you create a link for an identifier that has no corresponding url, a "Missing reference: [link-id]" message will be substituted for the URL. Conversely, creating a url that is never referenced will produce no output and no warnings or errors.

In my current project, I specify all links reference-style, e.g.: ``` #lang pollen If you need help, ◊link[1]{Google it}. ◊url[1]{https://google.com} ``` The [implementation can be seen here](https://thelocalyarn.com/code/artifact?udc=1&ln=186-205&name=d9318d9822c88d35). It’s probably more complicated than most people want, but hey, there are no quote marks around the urls. (Never thought about that before to be honest!) I just like not having inline URLs breaking up the prose. Under this implementation, you can put the url tag for a given identifier anywhere in the document, even before it is referenced. If you create a link for an identifier that has no corresponding url, a "Missing reference: [link-id]" message will be substituted for the URL. Conversely, creating a url that is never referenced will produce no output and no warnings or errors.
sorawee commented 4 years ago (Migrated from github.com)

@otherjoel separating it into link and url is very clever! But personally I kinda dislike using number because it's not descriptive and consequently make it easy to get it wrong. I would personally write ◊link[google-web]{Google it} and where google-web is a Racket identifier. With this way, we get a check that our identifier is indeed defined for free! The disadvantage though is that the urls must be defined at the top. Perhaps there's a way to make url a macro that lifts itself up to the top?

@otherjoel separating it into `link` and `url` is very clever! But personally I kinda dislike using number because it's not descriptive and consequently make it easy to get it wrong. I would personally write `◊link[google-web]{Google it}` and where `google-web` is a Racket identifier. With this way, we get a check that our identifier is indeed defined for free! The disadvantage though is that the urls must be defined at the top. Perhaps there's a way to make `url` a macro that lifts itself up to the top?
odanoburu commented 4 years ago (Migrated from github.com)

I would personally write ◊link[google-web]{Google it} and where google-web is a Racket identifier.

me too! this is similar to the way most latex packages handle referencing. I would urge everyone to include something akin to the HTML "alt" attribute for accessibility (assuming your output target format can handle it properly)

With this way, we get a check that our identifier is indeed defined for free!

a side-question: what kind of error message would we get here? I've been thinking about validating/throwing errors in tag functions lately, and I wonder if it's possible to include the location of the error in the source file (i.e., the location of the tag in the source file, not of the location of the tag function in pollen.rkt). is this location information available to the tag function? if not, can it be made available?

> I would personally write ◊link[google-web]{Google it} and where google-web is a Racket identifier. me too! this is similar to the way most latex packages handle referencing. I would urge everyone to include something akin to the HTML "alt" attribute for accessibility (assuming your output target format can handle it properly) > With this way, we get a check that our identifier is indeed defined for free! a side-question: what kind of error message would we get here? I've been thinking about validating/throwing errors in tag functions lately, and I wonder if it's possible to include the location of the error in the source file (i.e., the location of the tag in the source file, not of the location of the tag function in `pollen.rkt`). is this location information available to the tag function? if not, can it be made available?
otherjoel commented 4 years ago (Migrated from github.com)

@otherjoel separating it into link and url is very clever! But personally I kinda dislike using number because it's not descriptive and consequently make it easy to get it wrong.

I thought of that too 😎 Since I run the identifier through format, you can use any stringish value including a symbol:

◊link['google]{Google it}.

◊url['google]{https://google.com}

Your idea is interesting too. For this project I really like the simplicity/flexibility tradeoff I’ve already made though :-)

> @otherjoel separating it into `link` and `url` is very clever! But personally I kinda dislike using number because it's not descriptive and consequently make it easy to get it wrong. I thought of that too 😎 Since I run the identifier through format, you can use any stringish value including a symbol: ``` ◊link['google]{Google it}. ◊url['google]{https://google.com} ``` Your idea is interesting too. For this project I really like the simplicity/flexibility tradeoff I’ve already made though :-)
otherjoel commented 4 years ago (Migrated from github.com)

I've been thinking about validating/throwing errors in tag functions lately, and I wonder if it's possible to include the location of the error in the source file (i.e., the location of the tag in the source file, not of the location of the tag function in pollen.rkt). is this location information available to the tag function? if not, can it be made available?

This reminds me of something I was going to post here. I’ll start a separate discussion for it.

> I've been thinking about validating/throwing errors in tag functions lately, and I wonder if it's possible to include the location of the error in the source file (i.e., the location of the tag in the source file, not of the location of the tag function in pollen.rkt). is this location information available to the tag function? if not, can it be made available? This reminds me of something I was going to post here. I’ll start a separate discussion for it.
sorawee commented 4 years ago (Migrated from github.com)

One of the designs I still do not totally understand is how the content is passed in variadically (and this is actually due to Scribble). This limits us to only have one content block. It would be cool if we can have multiple content blocks like LaTeX: ◊link{https://google.com}{Google it} is equivalent to (link '("https://google.com") '("Google it")).

One of the designs I still do not totally understand is how the content is passed in variadically (and this is actually due to Scribble). This limits us to only have one content block. It would be cool if we can have multiple content blocks like LaTeX: `◊link{https://google.com}{Google it}` is equivalent to `(link '("https://google.com") '("Google it"))`.
mbutterick commented 4 years ago (Migrated from github.com)

I suggested this long ago, to no avail.

I [suggested this](https://groups.google.com/d/topic/racket-users/3QcJaWQsMNI/discussion) long ago, to no avail.
basus commented 4 years ago (Migrated from github.com)

Using Racket symbols instead of URLs enables something I've wanted from CMS' for a while: defining commonly used links outside of individual posts. So instead of 'google being defined in the same file, it could be defined in separate links.rkt file somewhere and inserted by the link function.

Using Racket symbols instead of URLs enables something I've wanted from CMS' for a while: defining commonly used links outside of individual posts. So instead of `'google` being defined in the same file, it could be defined in separate `links.rkt` file somewhere and inserted by the `link` function.
otherjoel commented 4 years ago (Migrated from github.com)

So instead of 'google being defined in the same file, it could be defined in separate links.rkt file

@basus Note that 'google is a symbol (note the preceding apostrophe), that is, a literal value; like the string "google" or the number 2, it is not definable, it just is what it is. Beautiful Racket has good explainers on the difference between symbols and identifiers (names for variables).

But you’re on the right track. If you don’t mind specifying each reference before it is used, you can use identifiers in place of strings for URLs, with no changes to your existing tag functions:

◊define[google]{https://google.com}

◊link[google]{let’s go searching}

Or if you want to define common links in a separate file as you were saying:

#lang racket/base  ; links.rkt

(provide (all-defined-out))

(define google "https://google.com")
#lang racket/base ; pollen.rkt

(require "links.rkt")
(provide (all-from-out "links.rkt"))

Now your Pollen sources can use the definition of google or anything else in links.rkt without defining it first.

> So instead of 'google being defined in the same file, it could be defined in separate links.rkt file @basus Note that `'google` is a symbol (note the preceding apostrophe), that is, a literal value; like the string `"google"` or the number 2, it is not definable, it just is what it is. _Beautiful Racket_ has good explainers on the difference between [symbols](https://beautifulracket.com/explainer/stringlike-types.html#symbols) and [_identifiers_](https://beautifulracket.com/explainer/stringlike-types.html#identifiers) (names for variables). But you’re on the right track. If you don’t mind specifying each reference before it is used, you can use identifiers in place of strings for URLs, with no changes to your existing tag functions: ``` ◊define[google]{https://google.com} ◊link[google]{let’s go searching} ``` Or if you want to define common links in a separate file as you were saying: ```racket #lang racket/base ; links.rkt (provide (all-defined-out)) (define google "https://google.com") ``` ```racket #lang racket/base ; pollen.rkt (require "links.rkt") (provide (all-from-out "links.rkt")) ``` Now your Pollen sources can use the definition of `google` or anything else in `links.rkt` without defining it first.
basus commented 4 years ago (Migrated from github.com)

Ahh ok, that's interesting. I am still a Racket newbie, so not entirely clear on the various different datatypes and their representations. This might be too much overhead for most uses, but we'll see.

Ahh ok, that's interesting. I am still a Racket newbie, so not entirely clear on the various different datatypes and their representations. This might be too much overhead for most uses, but we'll see.
otherjoel commented 4 years ago (Migrated from github.com)

Can you clarify what you mean by "overhead"? Computationally, it's practically nothing.

To make things even simpler, you could leave out the links.rkt file and just define the links in pollen.rkt. Anything provided there is automatically available in your Pollen sources.

Can you clarify what you mean by "overhead"? Computationally, it's practically nothing. To make things even simpler, you could leave out the `links.rkt` file and just `define` the links in `pollen.rkt`. Anything `provide`d there is automatically available in your Pollen sources.
basus commented 4 years ago (Migrated from github.com)

I meant overhead for authors/users. I don't know if there are links I repeat often enough to make this approach worthwhile. Still cool to be able to do it though.

I meant overhead for authors/users. I don't know if there are links I repeat often enough to make this approach worthwhile. Still cool to be able to do it though.
This repo is archived. You cannot comment on issues.
No Milestone
No project
No Assignees
1 Participants
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: mbutterick/pollen-users#27
Loading…
There is no content yet.