firescript
Version:
Firescript transpiler
175 lines (137 loc) • 4.64 kB
JavaScript
const NodeNotAllowedError = require('../errors/NodeNotAllowedError')
const TemplateNotFoundError = require('../errors/TemplateNotFoundError')
const templates = require('../js-templates/esx.js')
class JSElement {
constructor (ast) {
this.parent = null
this.type = ast.type
this.childs = []
this.indention = 0
this.__indention = 0
this.indentionSize = 2
this.location = ast.loc ? ast.loc.start : null
// this.leadingComments = ast.leadingComments ? ast.leadingComments.map((comment) => this.createElement(comment)) : null
// this.trailingComments = ast.trailingComments ? ast.trailingComments.map((comment) => this.createElement(comment)) : null
// this.innerComments = ast.innerComments ? ast.innerComments.map((comment) => this.createElement(comment)) : null
}
compile () {
throw new Error(`Element ${this.type} has no compile method implementd!`)
}
indentionStr () {
return ' '.repeat(this.indention * this.indentionSize)
}
getIndention () {
return ' '.repeat((this.__indention) * this.indentionSize)
}
getTemplate () {
if (!(this.type in templates)) {
throw new TemplateNotFoundError(this.type)
}
return templates[this.type]
}
createElement (ast, ALLOWED_NODES, indentionSize) {
if (!ast.type) {
return null
}
let Element
try {
Element = require(`./${ast.type}`)
} catch (err) {
if (err.code === 'MODULE_NOT_FOUND') {
throw new Error(`Element ${ast.type} not implemented yet`)
}
throw err
}
const child = new Element(ast)
if (ALLOWED_NODES && !ALLOWED_NODES.includes(child.type)) {
throw new NodeNotAllowedError(child.type, this.type, ALLOWED_NODES)
}
child.parent = this
child.indention = indentionSize ? this.indention + indentionSize : this.indention
if (ast.leadingComments && ast.leadingComments.length) {
child.leadingComments = ast.leadingComments.map((item) => this.createElement(item))
}
if (ast.trailingComments && ast.trailingComments.length) {
child.trailingComments = ast.trailingComments.map((item) => this.createElement(item))
}
if (ast.innerComments && ast.innerComments.length) {
child.innerComments = ast.innerComments.map((item) => this.createElement(item))
}
return child
}
createElementList (ast, ALLOWED_NODES, indentionSize) {
return ast.map((child) => this.createElement(child, ALLOWED_NODES, indentionSize))
}
getLineLength () {
// console.warn(`getLineLength method not implemented for element ${this.type}`)
return 0
}
addComments (arr) {
const Comment = require('./Comment')
if (this.leadingComments) {
arr.unshift.apply(arr, this.leadingComments.map((item) => new Comment(item)))
}
if (this.trailingComments) {
arr.push.apply(arr, this.trailingComments.map((item) => new Comment(item)))
}
if (this.innerComments) {
arr.push.apply(arr, this.innerComments)
}
return arr
}
renderLeadingComments () {
return this.renderComments(this.leadingComments, false)
}
renderTrailingComments () {
return this.renderComments(this.trailingComments, true)
}
renderInnerComments () {
return this.renderComments(this.innerComments, false)
}
wrapComments (arr) {
if (this.leadingComments) {
arr.unshift(this.renderLeadingComments())
}
if (this.trailingComments) {
arr.push(this.renderTrailingComments())
}
if (this.innerComments) {
arr.push(this.renderInnerComments())
}
return arr
}
renderComments (comments, isTrailing) {
if (!comments) return ''
const trailingLine = !isTrailing ? '' : ''
const leadingLine = isTrailing ? '' : ''
console.log('CMTS', comments)
return comments.map((comment, index, arr) => {
if (comment.type === 'Line') {
return '//' + comment.value
}
const blockCommentSpacing =
arr[index + 1] && arr[index + 1].type === 'Block'
? '\n'
: ''
return leadingLine +
'/*' +
comment.value +
'*/' +
blockCommentSpacing
}).join('\n') + trailingLine
}
renderElement (str) {
if (this.location) {
this.renderTree.push({
location: this.location
})
}
return (this.leadingComments ? this.renderComments(this.leadingComments, false) : '') +
str +
(this.trailingComments ? '\n\n' + this.renderComments(this.trailingComments, true) : '')
}
isParent (type) {
return this.parent && this.parent.type === type
}
}
module.exports = JSElement