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

Whitespace control #29

Open
kornelski opened this issue Jun 25, 2018 · 5 comments
Open

Whitespace control #29

kornelski opened this issue Jun 25, 2018 · 5 comments

Comments

@kornelski
Copy link
Contributor

kornelski commented Jun 25, 2018

I have a couple of places in HTML where I want to prevent any extra whitespace in the generated output:

  • When generating multiple inline or inline-block elements that shouldn't have gaps created by spaces.
  • When inserting commas or periods after elements, since a space before punctuation marks is generally inappropriate typographically.

Currently I'm just writing templates without spaces in them, but this isn't very convenient, since it requires use of long lines, and careful avoidance of any spaces.

@if let Some(url) = url.author(a) {
    <a href="@url"><span>@a.name()</span></a>@if !last {,} else {.}
}
<span class="version">@d.dep.req()</span>@for f in d.dep.req_features() {<span class="with-feature"><wbr>+<span>@f</span></span>}

So ideally I'd like some kind of block/directive that allows me to write template source with line breaks and indentation as usual, but remove that whitespace from the output.

I'm not sure what the syntax for it should look like, but generally template languages have blocks that either ignore all whitespace around elements, or trim whitespace at beginning and end of every line.

@kaj
Copy link
Owner

kaj commented Jun 25, 2018

Yes, some kind of whitespace removal would be nice. But as some whitespace is sometimes needed, there need to be a good syntax to chose if whitespace should be kept or removed.

@kaj
Copy link
Owner

kaj commented Jun 27, 2018

Given a code block, there are basically four positions where there may or may not exist whitespace, and in a conditional, two of them may exist in two variants:

[before the block]
@if something {
  [at start of block]
  actual content
  [at end of block]
} else {
  [at start of block]
  other content
  [at end of block]
}
[after the block]

I think it is fairly unsurprising to amend the curly brackets (maybe with a dot or dash) to remove whitespace at start or end of a block, but it might be more surprising if something inside the block affects what happens before or after the block. Especially for a conditional block, where the if and else blocks may contain different whitespace hints.

An example where whitespace in the block should be removed might look like this:

@if something {-
  actual content
-} else {-
  other content
-}

Would this be good?

@kornelski
Copy link
Contributor Author

It looks odd to me, since {-1} and {-1-} are both valid and interpreted differently.

How about:

@some_whitespace_be_gone_keyword {
  @if something { as usual }
}

that removes:

not here 
@some_whitespace_be_gone_keyword { here
here  @if something { here too } and here
} not here

@kaj
Copy link
Owner

kaj commented Jan 24, 2019

If we want some keyword to switch between differernt whitespace-handling modes, I think I want three modes to exist:

  • As-is: All whitespace is retained.
  • Compact: The fact that there is or isn't whitespace in a given place is respected, but not the exact whitespace sequence. Instead, all whitespace that contains at least one newline is compacted to a single newline, and all whitespace that does not contain newlines is compacted to a single space.
  • Removed: All whitespace at the start and end of blocks are removed. Internal whitespace in a block (e.g. between two words in a text) is treated as in compact.

The only behaviour currently implemented is As-is, which is rarely whats wanted, but in the cases it is wanted it tends to be important. Compact is what I think should probably be the default (as long as as-is can be selected), and removed sometimes makes it possible to format the template code nicely without introducing "accidental" whitespace.

I was rather sceptical to the "mode-switching" keyword you suggested, @kornelski , but after giving it some though from time to time I think it is probably a good idea. Having the possibility to switch between three modes also makes it possible to enable whitespace for blocks inside a block where it is disabled, like so:

@whitespace(removed) {
  @for t in something {
      <li>
      @if something_else {
          @whitespace(compact) {
            la la, lots of space
           }
      }
      no extra space @t
      </li>
    }
}

@kornelski
Copy link
Contributor Author

Yes, that would work. I especially like the compact mode.

kaj added a commit that referenced this issue Jan 25, 2019
As suggested in #29.  A keyword `@whitespace` can be used to switch
whitespace handling between the tree modes `as-is`, `compact`, and
`removed`.

- [x] Implment the functionality.  Set default mode to `compact` and
  update tests.
- [ ] Decide on the exact syntax; should some keyword change?  Should
  `@ws` be allowed as an alias for `@whitespace`?  Should the
  `removed` alternative be called `trim`?  Or some other word change?
- [ ] Add documentation and more tests / examples.
- [ ] Anything else?
@kaj kaj mentioned this issue Jan 25, 2019
4 tasks
kaj added a commit that referenced this issue Mar 16, 2019
As suggested in #29.  A keyword `@whitespace` can be used to switch
whitespace handling between the tree modes `as-is`, `compact`, and
`removed`.

- [x] Implment the functionality.  Set default mode to `compact` and
  update tests.
- [ ] Decide on the exact syntax; should some keyword change?  Should
  `@ws` be allowed as an alias for `@whitespace`?  Should the
  `removed` alternative be called `trim`?  Or some other word change?
- [ ] Add documentation and more tests / examples.
- [ ] Anything else?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants