Skip to content

Commit

Permalink
Better support for parsing minified output
Browse files Browse the repository at this point in the history
  • Loading branch information
marcoroth committed Feb 11, 2024
1 parent 345a7b0 commit d61f679
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,33 @@ export class Parser {
}
},

ExpressionStatement(node: any): void {
const left = node.expression.left
const right = node.expression.right

if (node.expression.type === "AssignmentExpression" && left.type === "MemberExpression" && left.object.type === "Identifier") {
const classDeclaration = classDeclarations.find(c => c.className === left.object.name)

if (classDeclaration && classDeclaration.isStimulusClass) {
if (right.type === "ArrayExpression") {
const values = right.elements.map((element: NodeElement) => element.value)

if (left.property.name === "targets") {
controller.targets = values
}

if (left.property.name === "classes" && right.type === "ArrayExpression") {
controller.classes = values
}
}

if (left.property.name === "values" && right.type === "ObjectExpression") {
// TODO
}
}
}
},

PropertyDefinition(node: any): void {
const { name } = node.key

Expand Down
62 changes: 62 additions & 0 deletions test/parser/minified.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { expect, test, describe } from "vitest"
import { setupParser } from "../helpers/setup"

const parser = setupParser()

describe("compiled JavaScript", () => {
test("transpiled", () => {
const code = `
import { Controller as o } from "@hotwired/stimulus";
class r extends o {
initialize() {
this.intersectionObserverCallback = this.intersectionObserverCallback.bind(this);
}
connect() {
this.class = this.classValue || this.defaultOptions.class || "in", this.threshold = this.thresholdValue || this.defaultOptions.threshold || 0.1, this.rootMargin = this.rootMarginValue || this.defaultOptions.rootMargin || "0px", this.observer = new IntersectionObserver(this.intersectionObserverCallback, this.intersectionObserverOptions), this.itemTargets.forEach((t) => this.observer.observe(t));
}
disconnect() {
this.itemTargets.forEach((t) => this.observer.unobserve(t));
}
}
r.targets = ["item"];
r.classes = ["active", "inactive"];
r.values = {
class: String,
threshold: Number,
rootMargin: String
};
export {
r as default
};
`

const controller = parser.parseController(code, "minified_controller.js")

expect(controller.hasErrors).toEqual(false)
expect(controller.methods).toEqual(["initialize", "connect", "disconnect"])
expect(controller.targets).toEqual(["item"])
expect(controller.classes).toEqual(["active", "inactive"])
// expect(Object.keys(controller.values)).toEqual(["class", "threshold", "rootMargin"])
})

test("transpiled/minified", () => {
const code = `
(function(e,t){typeof exports=="object"&&typeof module<"u"?module.exports=t(require("@hotwired/stimulus")):typeof define=="function"&&define.amd?define(["@hotwired/stimulus"],t):(e=typeof globalThis<"u"?globalThis:e||self,e.StimulusScrollReveal=t(e.Stimulus))})(this,function(e){"use strict";class t extends e.Controller{initialize(){this.intersectionObserverCallback=this.intersectionObserverCallback.bind(this)}connect(){this.class=this.classValue||this.defaultOptions.class||"in",this.threshold=this.thresholdValue||this.defaultOptions.threshold||.1,this.rootMargin=this.rootMarginValue||this.defaultOptions.rootMargin||"0px",this.observer=new IntersectionObserver(this.intersectionObserverCallback,this.intersectionObserverOptions),this.itemTargets.forEach(s=>this.observer.observe(s))}disconnect(){this.itemTargets.forEach(s=>this.observer.unobserve(s))}intersectionObserverCallback(s,o){s.forEach(r=>{if(r.intersectionRatio>this.threshold){const i=r.target;i.classList.add(...this.class.split(" ")),i.dataset.delay&&(i.style.transitionDelay=i.dataset.delay),o.unobserve(i)}})}get intersectionObserverOptions(){return{threshold:this.threshold,rootMargin:this.rootMargin}}get defaultOptions(){return{}}}return t.targets=["item"],t.values={class:String,threshold:Number,rootMargin:String},t});
`

const controller = parser.parseController(code, "minified_controller.js")

expect(controller.hasErrors).toEqual(false)
expect(controller.methods).toEqual(["initialize", "connect", "disconnect","intersectionObserverCallback"])
expect(controller.classes).toEqual([])
// expect(controller.targets).toEqual(["item"])
// expect(Object.keys(controller.values)).toEqual(["class", "threshold", "rootMargin"])
})
})

0 comments on commit d61f679

Please sign in to comment.