Skip to content

Commit

Permalink
feat: add support for javascript tags
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickhulce committed Mar 8, 2017
1 parent be6274a commit 019f6ff
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 10 deletions.
26 changes: 23 additions & 3 deletions lib/sources/html-source.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,46 @@
const _ = require('lodash')
const HtmlParser = require('htmlparser2').Parser
const ParsedSource = require('./parsed-source')
const JsSource = require('./js-source')

const DEFAULT_ATTRIBUTES = ['id', 'class', 'ng-class', 'data-ng-class']

class HtmlSource extends ParsedSource {
get type() {
return 'html'
}

_findToken(selector) {
return _.find(this._parsed.children, source => source.contains(selector))
}

static get joiner() {
return '\n<!-- joined by nukecss -->\n'
}

static parse(text) {
static parse(text, opts) {
const tokens = new Set()
const children = []
const attributeKeys = _.get(opts, 'html.attributes', DEFAULT_ATTRIBUTES)

let error
let innerText
const parser = new HtmlParser({
onopentag(name, attributes) {
[name, attributes.id, attributes.class]
const attributeValues = Array.isArray(attributeKeys) ?
attributeKeys.map(key => attributes[key]) : []
attributeValues.concat([name])
.filter(candidate => typeof candidate === 'string')
.forEach(candidate => tokens.add(candidate.toLowerCase()))
},
ontext(value) {
innerText = value
},
onclosetag(name) {
if (name === 'script' && innerText) {
children.push(JsSource.from(innerText))
}
},
onerror(err) {
error = err
},
Expand All @@ -35,7 +55,7 @@ class HtmlSource extends ParsedSource {
throw new Error('No tokens found')
}

return tokens
return {tokens, children}
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/sources/js-source.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class JsSource extends ParsedSource {
ancestry.pop()
},
})
return tokens
return {tokens}
}
}

Expand Down
21 changes: 16 additions & 5 deletions lib/sources/parsed-source.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ const debug = require('debug')('nukecss:parsed-source')
const SimpleSource = require('./simple-source')

class ParsedSource {
constructor(text, tokens, opts = {}) {
constructor(text, parsed, opts = {}) {
this._text = text
this._parsed = parsed
this._options = opts
this._tokensArray = Array.from(tokens).map(t => t.toLowerCase())
this._tokensArray = Array.from(parsed.tokens).map(t => t.toLowerCase())
this._tokens = new Set(this._tokensArray)
}

Expand Down Expand Up @@ -34,13 +35,22 @@ class ParsedSource {
return false
}

_findToken() {
return false
}

contains(selector) {
selector = selector.toLowerCase()
return Boolean(this._tokens.has(selector) ||
this._findToken(selector) ||
this._findWholeSelectorInTokens(selector) ||
this._findSelectorPartsInTokens(selector))
}

_joinParsed(parsedA, parsedB, tokens) {
return Object.assign({}, parsedA, parsedB, {tokens})
}

join(that) {
const Class = this.constructor
if (this.type !== that.type) {
Expand All @@ -53,14 +63,15 @@ class ParsedSource {
const thatTokens = that._tokensArray || []
const tokens = new Set(thisTokens.concat(thatTokens))
const joiner = Class.joiner
return new Class(`${this._text}${joiner}${that._text}`, tokens, this._options)
const parsed = this._joinParsed(this._parsed, that._parsed, tokens)
return new Class(`${this._text}${joiner}${that._text}`, parsed, this._options)
}

static from(text, opts) {
try {
const Class = this
const tokens = Class.parse(text, opts)
return new Class(text, tokens, opts)
const parsed = Class.parse(text, opts)
return new Class(text, parsed, opts)
} catch (err) {
debug(err)
return new SimpleSource(text, opts)
Expand Down
11 changes: 10 additions & 1 deletion test/sources/html-source.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ describe('sources/html-source.js', () => {
<div class="several classes in-a-row">
<h1>My Header</h1>
<p class="lead">Examplelongtext</p>
<div ng-class="{strike: deleted}" ng-repeat="value in obj">
{{template value}}
</div>
</div>
</div>
<script>
Expand All @@ -66,6 +69,7 @@ describe('sources/html-source.js', () => {
expect(source).to.contain('container')
expect(source).to.contain('ConTainer')
expect(source).to.contain('lead')
expect(source).to.contain('strike')
})

it('should find tokens as multiple classes', () => {
Expand All @@ -80,13 +84,18 @@ describe('sources/html-source.js', () => {

it('should not find tokens as other attribtues', () => {
expect(source).to.not.contain('stylesheet')
expect(source).to.not.contain('javascript')
expect(source).to.not.contain('text/javascript')
})

it('should not find tokens as text', () => {
expect(source).to.not.contain('Header')
expect(source).to.not.contain('examplelongtext')
})

it('should find tokens in script', () => {
expect(source).to.contain('my-javascript-class')
expect(source).to.not.contain('myJsVar')
})
})
})
})

0 comments on commit 019f6ff

Please sign in to comment.