zspecza / common-tags

🔖 Useful template literal tags for dealing with strings in ES2015+
Other
1.99k stars 60 forks source link

[Feature Request] Add a way to intentionally insert line break inside a `oneLine` #176

Open ricokahler opened 5 years ago

ricokahler commented 5 years ago

First off, thanks for an amazing and simple library! I like using oneLine to keep long text within 100 characters 🙌. However, (as far as I know) there is no way to add an intentional line break in a oneLine.

For example, I'll have a longer paragraph like so:

const longParagraph = oneLine`
  Four score and seven years ago our fathers brought forth on this continent, a new nation,
  conceived in Liberty, and dedicated to the proposition that all men are created equal.

  Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived
  and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to
  dedicate a portion of that field, as a final resting place for those who here gave their lives
  that that nation might live. It is altogether fitting and proper that we should do this.
`;

and my intention would be to add two intentional line breaks after "created equal." and maybe an additional line break after "should do this.".

I have three proposals to get this feature:

  1. add an extra directive to import that when oneLine (or any other tag) sees it, it will add the intentional line break
    
    import { oneLine, NEW_LINE } from 'common-tags';

const longParagraph = oneLine Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.${NEW_LINE} ${NEW_LINE} Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this.${NEW_LINE} ;


2. import or add some special directive that allows you to escape new lines (or even other things like tabs).
```js
import { oneLine, escape } from 'common-tags';

const longParagraph = oneLine`
  Four score and seven years ago our fathers brought forth on this continent, a new nation,
  conceived in Liberty, and dedicated to the proposition that all men are created equal.${escape('\n')}
  ${escape('\n')}
  Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived
  and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to
  dedicate a portion of that field, as a final resting place for those who here gave their lives
  that that nation might live. It is altogether fitting and proper that we should do this.${escape('\n')}
`;

instead of importing escape, there could be an escape sequence similar to javascript's backslashes \

  1. create a brand new tag that will add insert a single line break when two line breaks are present (similar to how markdown works)
    
    import { paragraph } from 'common-tags';

const longParagraph = paragraph` Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.

Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this.

`;


The logic for the `paragraph` tag (could use renaming) is for every two consecutive line breaks (without considering whitespace), it will insert one line break. The rest of the line breaks will be ignored.

**I would be willing to work on the PRs after I get your blessing for any or all of the above proposals. I think both 2 and 3 are worth implementing.**

Let me know what you think and I apologize if I missed something!
reidgould commented 5 years ago

+1. I'd like a set of tags that work exactly like YAML Multiline Strings with the double newline in folded style to produce a newline in the result, the final chomping option, and (like the tags in this package already do) default chomping of the first newline.

fatfisz commented 5 years ago

@ricokahler I think both 2 & 3 are worth considering. If you still want to tackle them, PRs are welcome! In that case please create two separate PRs for those features.

@reidgould Do I understand correctly that proposal number 3. is what you have in mind or is it something different?

vipulbhj commented 4 years ago

Is this still open, I would like to work on this. Having a paragraph tagged literal would be great. And the escaping function also sounds like it can open up a lot of new use cases

fatfisz commented 4 years ago

Sure, go ahead! I think the second proposal is the best one because it's the most explicit. Would you like to work on that?

ricokahler commented 4 years ago

@vipulbhj i opened this issue and then i got busy, then i forgot to work on it 😅

please finish what i started lol

vipulbhj commented 4 years ago

@ricokahler sure, which one should we go for ??

vipulbhj commented 4 years ago
const paragraph = createTag(
  replaceResultTransformer(/(?:\n+)/g, '\n'),
  trimResultTransformer(),
);

Does this look okay to you guys ??

abyss commented 4 years ago

+1. I'm fond of method 3, personally. I may attempt to get a PR for this but just incase I don't - maybe someone will finish this?

Edit: Spent some time on it and couldn't figure it out. Hopefully someone better at regex can pick this up

mrmachine commented 2 years ago

Definitely the 3rd option, like Markdown. Hard wrapped paragraphs should be restored to one line, but distinct paragraphs should remain intact.

FoxxMD commented 1 year ago

@vipulbhj this was close but did not work for me.

This works to implement method 3:

const doubleReturnNewline = new TemplateTag(
    // remove instances of single line breaks
    replaceResultTransformer(/(?<=.)\n(?!\n+)/g, ''),
    // replace instances of two or more line breaks with one line break
    replaceResultTransformer(/(?<=.)\n{2,}/g, '\n'),
    trimResultTransformer(),
);

May only work for server/node usage due to lookbehind/lookahead