{"action":"created","issue":{"url":"https://api.github.com/repos/yosssi/ace/issues/51","labels_url":"https://api.github.com/repos/yosssi/ace/issues/51/labels{/name}","comments_url":"https://api.github.com/repos/yosssi/ace/issues/51/comments","events_url":"https://api.github.com/repos/yosssi/ace/issues/51/events","html_url":"https://github.com/yosssi/ace/pull/51","id":76393418,"number":51,"title":"Option for closing tags list","user":{"login":"rzab","id":148718,"avatar_url":"https://avatars.githubusercontent.com/u/148718?v=3","gravatar_id":"","url":"https://api.github.com/users/rzab","html_url":"https://github.com/rzab","followers_url":"https://api.github.com/users/rzab/followers","following_url":"https://api.github.com/users/rzab/following{/other_user}","gists_url":"https://api.github.com/users/rzab/gists{/gist_id}","starred_url":"https://api.github.com/users/rzab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rzab/subscriptions","organizations_url":"https://api.github.com/users/rzab/orgs","repos_url":"https://api.github.com/users/rzab/repos","events_url":"https://api.github.com/users/rzab/events{/privacy}","received_events_url":"https://api.github.com/users/rzab/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-05-14T15:24:41Z","updated_at":"2015-05-14T17:50:07Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/yosssi/ace/pulls/51","html_url":"https://github.com/yosssi/ace/pull/51","diff_url":"https://github.com/yosssi/ace/pull/51.diff","patch_url":"https://github.com/yosssi/ace/pull/51.patch"},"body":"Ace has predefined list of tag names to NOT be closed. It's handy to have an option to provide the list.\r\nIf I'm producing XML, I'd have it empty.\r\n\r\nCode changes notes:\r\n- The list is kept in a `map[string]struct{}` as the size of `struct{}` is zero.\r\n- Initializing func makes a copy of `defaultNoCloseTagNames` for `opts.NoCloseTagNames`, otherwise plain assignment would create a reference to the default (as it is a map) and it could be modified outside ace.\r\n\r\nI also took the opportunity to make `initializeOptions` public. It becomes complex to re-do what the func does in non-ace code when it passes non-nil *ace.Options to ace.Load etc.\r\n"},"comment":{"url":"https://api.github.com/repos/yosssi/ace/issues/comments/102116108","html_url":"https://github.com/yosssi/ace/pull/51#issuecomment-102116108","issue_url":"https://api.github.com/repos/yosssi/ace/issues/51","id":102116108,"user":{"login":"rzab","id":148718,"avatar_url":"https://avatars.githubusercontent.com/u/148718?v=3","gravatar_id":"","url":"https://api.github.com/users/rzab","html_url":"https://github.com/rzab","followers_url":"https://api.github.com/users/rzab/followers","following_url":"https://api.github.com/users/rzab/following{/other_user}","gists_url":"https://api.github.com/users/rzab/gists{/gist_id}","starred_url":"https://api.github.com/users/rzab/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rzab/subscriptions","organizations_url":"https://api.github.com/users/rzab/orgs","repos_url":"https://api.github.com/users/rzab/repos","events_url":"https://api.github.com/users/rzab/events{/privacy}","received_events_url":"https://api.github.com/users/rzab/received_events","type":"User","site_admin":false},"created_at":"2015-05-14T17:50:07Z","updated_at":"2015-05-14T17:50:07Z","body":"My thinking is this: ace cannot be sure about the format is produces. For anything strict (XML/XHTML) it's obvious the set must be empty. For HTML4 the existing default is ok, but not for HTML5. HTML5 has a dozen of tags which should not be closed, some of which are invalid in HTML4. Ace should not guess, it's up to user to deviate from the default set.\r\n\r\nSo as long as the set is an option, it must be easy for user to modify. `delete` is straight forward. Addition is maybe ugly because of `struct{}{}` but making it a `map[string]bool` so that the syntax would be better is just wasting space. We could add a helper public method for *ace.Options accepting `[]string` or better yet `...string` for the addition to the internal `.NoCloseTagNames` like this:\r\n\r\n```go\r\nfunc (opts *Options) AddNoCloseTagNames(names ...string) {\r\n\tfor _, name := range names {\r\n\t\topts.NoCloseTagNames[name] = struct{}{}\r\n\t}\r\n}\r\n// Then we'd use it in `InitializeOptions':\r\nif opts.NoCloseTagNames == nil {\r\n\topts.AddNoCloseTagNames(\"br\", \"hr\", \"img\", \"input\", \"link\", \"meta\")\r\n}\r\n```\r\nNow imagine changing the set when it is a `[]string`.\r\n\r\n```go\r\n// Addition\r\naceopts.NoCloseTagNames = append(aceopts.NoCloseTagNames, \"input\")\r\n\r\n// Deleting \"input\"\r\nvar newnoclose []string\r\nfor _, value := range aceopts.NoCloseTagNames {\r\n\tif value != \"input\" {\r\n\t\tnewnoclose = append(newnoclose, value)\r\n\t}\r\n}\r\naceopts.NoCloseTagNames = newnoclose\r\n```"}}