Match maker
Given a CSS query, output the unindented html needed that will produce a match.
For example, a.foo>b#bar
should produce <a class=‘foo’><b id=‘bar’></b></a>
The html should have full tags, not self closing ones. The query follows the following grammar:
query ::= element (">" element)* element ::= name [id] class* id ::= "#" name class ::= "." name name ::= [a-z0-9]+
However for the test cases you should expect at most 9 levels of nesting elements.
Judge
(async function*(context: Context): Challenge { // Single Test const testcases = {'h3#title3.class3': "<h3 id='title3' class='class3'></h3>", 'figure>figcaption': '<figure><figcaption></figcaption></figure>', 'span.flair': "<span class='flair'></span>", 'a.b.c.d': "<a class='b c d'></a>", 'main>audio.rickroll': "<main><audio class='rickroll'></audio></main>", 'table#scores>tbody.bytes>tr.me': "<table id='scores'><tbody class='bytes'><tr class='me'></tr></tbody></table>", 'div>div>div': '<div><div><div></div></div></div>', 'html>body>main>div.warning': "<html><body><main><div class='warning'></div></main></body></html>", 'html#html>html.html': "<html id='html'><html class='html'></html></html>", 'nav#menu>ul.navlist>li.navitem': "<nav id='menu'><ul class='navlist'><li class='navitem'></li></ul></nav>", 'form#login>input#user.username': "<form id='login'><input id='user' class='username'></input></form>", 'article.blogpost>h1.title': "<article class='blogpost'><h1 class='title'></h1></article>", 'section#about>div.container>p.text': "<section id='about'><div class='container'><p class='text'></p></div></section>", 'div#wrapper>header.main>h2#subtitle': "<div id='wrapper'><header class='main'><h2 id='subtitle'></h2></header></div>", 'footer>div.footercontent>p>a#discord': "<footer><div class='footercontent'><p><a id='discord'></a></p></div></footer>", 'aside#sidebar>div.widget>ul.links': "<aside id='sidebar'><div class='widget'><ul class='links'></ul></div></aside>", 'main#content>section.hero>img.banner': "<main id='content'><section class='hero'><img class='banner'></img></section></main>", 'div.grid>div.cell>span.value': "<div class='grid'><div class='cell'><span class='value'></span></div></div>", 'header#siteheader.siteheader>nav#mainnav>ul.menu>li.item': "<header id='siteheader' class='siteheader'><nav id='mainnav'><ul class='menu'><li class='item'></li></ul></nav></header>", 'alphabet.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z': "<alphabet class='a b c d e f g h i j k l m n o p q r s t u v w x y z'></alphabet>"} const testCases = context.runTestCases(Object.entries(testcases)); for await (const testcase of testCases) { yield context.registerTestCase(testcase); } // Finally, the challenge is passed if no test cases failed return context.noFailures(); })
Example Code
const input = require('fs').readFileSync(0).toString().split('\n') const format = (selector) => { const tokens = selector.split('>') const result = [] const close_stack = [] for (const token of tokens) { const [tag, ...attributes] = token.split(/(?=[#.])/g); const id = attributes.find(a => a.startsWith('#'))?.slice(1); const classes = attributes.filter(a => a.startsWith('.')).map(a => a.slice(1)).join(' '); const idString = id ? ` id='${id}'` : ''; const classString = classes ? ` class='${classes}'` : ''; result.push(`<${tag}${idString}${classString}>`) close_stack.push(tag) } return result.join('') + close_stack.reverse().map(tag => `</${tag}>`).join('') } for (const selector of input) { console.log(format(selector)) }