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

Format inline HTML tags #1407

Merged
merged 10 commits into from
Jun 30, 2018
Merged

Format inline HTML tags #1407

merged 10 commits into from
Jun 30, 2018

Conversation

madman-bob
Copy link
Contributor

Fixes #1033

Replaces concept of unformatted tags with inline tags, which are not wrapped. Previous unformatted functionality moved to content_unformatted tags. This allows us to format the attributes of inline tags correctly.

By comparison with textarea, note that <textarea><textarea></textarea></textarea>
is not balanced, as there is actually only one opening tag.
The second is raw text inside the text area.
@bitwiseman
Copy link
Member

@madman-bob
This is very exciting. :)

One problem I see so far is this is going to be a breaking change as you've written it. That would mean having to update the beautifier to v2 and I only want to do that as part of larger changes.

Would you be willing to modify it to make it so it is non-breaking? Specifically, if someone uses unformatted it should continue to work.

@madman-bob
Copy link
Contributor Author

Understandable. Would it be acceptable to alias unformatted to unformatted_content? It would still change the behaviour of unformatted, but only by formatting the attributes, when it didn't before. I can't imagine cases where you wouldn't want to format the attributes.

On an unrelated note, do you have a preferred letter for the command line name of inline? All the obvious ones seem to be taken.

Copy link
Member

@bitwiseman bitwiseman left a comment

Choose a reason for hiding this comment

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

@madman-bob
I don't have a good one-letter option. That's it secondary concern - this can go public without that.

As to aliasing unformatted to unformatted_content:
Tough call. Most users would want unformatted to alias to inline. But others would want the behavior to not change at all.

I think the right choice is to have the behavior of the unformatted option not change at all, but have it be empty be default (with current values moved to inline).

@@ -1010,23 +1010,23 @@ exports.test_data = {
]
}, {
fragment: true,
input: '<div><p>Beautify me</p></div><p><p>But not me</p></p>',
input: '<div><p>Beautify me</p></div><p><div>But not me</div></p>',
Copy link
Member

Choose a reason for hiding this comment

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

Please keep the original test inputs. You can (and should) create new tests with new values, but wherever possible the tests with the original inputs should also be kept. Then if the original inputs produce changed output it is clear what has changed.

In this case, the new tests are definitely interesting. Please add them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test wasn't testing what it was intended to test.

Here, p is content_unformatted, so the final </p> tag is unmatched, in the same way that in

<textarea><textarea></textarea></textarea>

we have the opening tag <textarea>, the literal text "<textarea>", followed by the closing tag </textarea> to match the first tag, and then the unmatched tag </textarea>.

// bth('<div><span>content</span></div>');
bth('<div><span>content</span></div>');

test_fragment('<p>Should remove <q><span \n\nclass="some-class">attribute</span></q> newlines</p>',
Copy link
Member

Choose a reason for hiding this comment

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

Instead of just this one test, add a whole new section showing the accurate behavior of inlines.
You also need to show them behaving correctly in line-wrap situations.

@@ -237,7 +237,7 @@ function Beautifier(html_source, options, js_beautify, css_beautify) {
indent_character = (options.indent_char === undefined) ? ' ' : options.indent_char;
brace_style = (options.brace_style === undefined) ? 'collapse' : options.brace_style;
wrap_line_length = parseInt(options.wrap_line_length, 10) === 0 ? 32786 : parseInt(options.wrap_line_length || 250, 10);
unformatted = options.unformatted || [
inline_tags = options.inline_tags || [
Copy link
Member

Choose a reason for hiding this comment

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

The public option is called inline, not inline_tags.

@bitwiseman
Copy link
Member

bitwiseman commented Jun 5, 2018

@madman-bob
If keeping the existing unformatted behavior is a serious blocker, I'm open to having it map to inline or content-unformatted, which ever produces the least changes (or at least the most sensible changes) from the existing output.

People use unformatted to work with xml documents and add templating elements, it may be hard to get the behavior to not break those scenarios.

In all cases add tests (or even examples) is going to be vital.

@madman-bob
Copy link
Contributor Author

Have now added unformatted tags back in, and some more tests.

@madman-bob
Copy link
Contributor Author

Are there any further changes required?

@@ -229,6 +239,17 @@ function Beautifier(html_source, options, js_beautify, css_beautify) {
}
};

this.get_last_tag = function() {
var last_tag;
for (var i = this.output.length - 1; i >= 0; i --) {
Copy link
Member

Choose a reason for hiding this comment

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

Walking back one character at a time is going to have really bad performance characteristics.
At minimum, we should store the last_tag info when we find a tag and then replace it each time a new tag is found.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is walking back one line at a time, and, while I wrote it defensively, I cannot think of any situation where it would loop more than twice.

@@ -182,6 +184,14 @@ function Beautifier(html_source, options, js_beautify, css_beautify) {
}
}
return false;
},
get_tag_name: function(full_tag) {
Copy link
Member

Choose a reason for hiding this comment

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

This information already found during the process of processing the tag: https://github.com/madman-bob/js-beautify/blob/def3cbda7911a343ff603b81a03d63670db456a4/js/src/html/beautifier.js#L534

It would be better to store or pass that information back form there.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The linked line only gets the tag name, while this function also distinguishes whether it's an opening/closing tag. Ideally, I'd refactor the other locations to use this function, but that would introduce minor behavioural changes.

Copy link
Member

@bitwiseman bitwiseman left a comment

Choose a reason for hiding this comment

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

@madman-bob
I need to run some local tests.
I want @garretwilson to test this before it is released.
And a couple implementation points.

@bitwiseman bitwiseman merged commit 108e4e5 into beautifier:master Jun 30, 2018
@bitwiseman
Copy link
Member

@madman-bob
Thanks!

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.

2 participants