Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@lightningjs/blits

Package Overview
Dependencies
Maintainers
7
Versions
91
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lightningjs/blits - npm Package Compare versions

Comparing version 0.6.4 to 0.6.5

2

boilerplate/package.json

@@ -34,4 +34,4 @@ {

"dependencies": {
"@lightningjs/blits": "^0.6.4"
"@lightningjs/blits": "^0.6.5"
}
}

@@ -14,6 +14,20 @@ import Blits from '@lightningjs/blits'

fonts: [
{family: 'lato', type: 'msdf', png: '/fonts/Lato-Regular.msdf.png', json: '/fonts/Lato-Regular.msdf.json'},
{family: 'raleway', type: 'msdf', png: '/fonts/Raleway-ExtraBold.msdf.png', json: '/fonts/Raleway-ExtraBold.msdf.json'},
{family: 'opensans', type: 'web', file: '/fonts/OpenSans-Medium.ttf'}
{
family: 'lato',
type: 'msdf',
png: 'fonts/Lato-Regular.msdf.png',
json: 'fonts/Lato-Regular.msdf.json',
},
{
family: 'raleway',
type: 'msdf',
png: 'fonts/Raleway-ExtraBold.msdf.png',
json: 'fonts/Raleway-ExtraBold.msdf.json',
},
{
family: 'opensans',
type: 'web',
file: 'fonts/OpenSans-Medium.ttf',
},
],
})

@@ -6,2 +6,3 @@ import { defineConfig } from 'vite'

return {
base: '/', // Set to your base path if you are deploying to a subdirectory (example: /myApp/)
plugins: [...blitsVitePlugins],

@@ -8,0 +9,0 @@ resolve: {

# Changelog
# v0.6.5
_16 jan 2024_
- Added `path` to boilerplate vite.config.js for deployments in a sub folder
- Improved error handling in the template parser, with more contextual error messages
# v0.6.4

@@ -4,0 +11,0 @@

{
"name": "@lightningjs/blits",
"version": "0.6.4",
"version": "0.6.5",
"description": "Blits: The Lightning 3 App Development Framework",

@@ -5,0 +5,0 @@ "bin": "bin/index.cjs",

@@ -50,7 +50,7 @@ /*

const Component = (name = required('name'), config = required('config')) => {
const setupComponent = (lifecycle) => {
const setupComponent = (lifecycle, parentComponent) => {
// code generation
if (!config.code) {
Log.debug(`Generating code for ${name} component`)
config.code = codegenerator.call(config, parser(config.template))
config.code = codegenerator.call(config, parser(config.template, name, parentComponent))
}

@@ -119,3 +119,3 @@

if (!component.setup) {
setupComponent(this.lifecycle)
setupComponent(this.lifecycle, parentComponent)
}

@@ -122,0 +122,0 @@

@@ -269,3 +269,2 @@ /*

this.node[p] = v
console.log('set it', this.node[p], v)
}

@@ -272,0 +271,0 @@ }

export default {
currentView: Symbol('currentView'),
cursorTagStart: Symbol('cursorTagStart'),
computedKeys: Symbol('computedKeys'),

@@ -4,0 +5,0 @@ destroy: Symbol('destroy'),

@@ -20,12 +20,5 @@ /*

class TemplateParseError extends Error {
constructor(message, name, context) {
super(`TemplateParseError: ${message}`)
this.name = name
this.context = context
}
}
export default (template = '') => {
export default (template = '', componentName, parentComponent, filePath = null) => {
let cursor = 0
let prevCursor = 0
let tags = []

@@ -49,9 +42,6 @@ let currentTag = null

} catch (error) {
if (error instanceof TemplateParseError) {
console.error(`${error.message} | ${error.name}`)
} else {
console.error(error)
if (error.name == 'TemplateParseError' || error.name == 'TemplateStructureError') {
error.message = `${error.message}\n${error.context}`
}
// return errors gracefully
return null
throw error
}

@@ -68,5 +58,5 @@ }

// utils
const clean = (template) => {
const clean = (templateText) => {
// remove all unnecessary new lines and comments
return template
return templateText
.replace(/<!--.*?-->/gms, '') // remove comments

@@ -81,3 +71,6 @@ .replace(/\r?\n\s*\r\n/gm, ' ') // remove empty lines

const match = template.slice(cursor).match(regex)
if (match) cursor += match[0].length
if (match) {
prevCursor = cursor
cursor += match[0].length
}
return match

@@ -90,3 +83,8 @@ }

if (match) {
tags.push({ type: null, [symbols.type]: 'opening', [symbols.level]: currentLevel })
tags.push({
type: null,
[symbols.type]: 'opening',
[symbols.level]: currentLevel,
[symbols.cursorTagStart]: prevCursor,
})
currentLevel++

@@ -103,3 +101,7 @@ parseLoop(parseEmptyTagStart)

currentLevel--
tags.push({ type: null, [symbols.type]: 'closing', [symbols.level]: currentLevel })
tags.push({
type: null,
[symbols.type]: 'closing',
[symbols.level]: currentLevel,
})
parseLoop(parseEmptyTagStart)

@@ -114,7 +116,13 @@ } else {

if (match) {
currentTag = {
type: match[1],
[symbols.level]: currentLevel,
[symbols.cursorTagStart]: prevCursor,
}
if (match[0].startsWith('</')) {
currentLevel--
currentTag = { type: match[1], [symbols.type]: 'closing', [symbols.level]: currentLevel }
currentTag[symbols.type] = 'closing'
currentTag[symbols.level] = currentLevel
} else {
currentTag = { type: match[1], [symbols.type]: 'opening', [symbols.level]: currentLevel }
currentTag[symbols.type] = 'opening'
currentLevel++

@@ -124,3 +132,3 @@ }

} else {
throw new TemplateParseError('InvalidTag', template.slice(cursor))
throw TemplateParseError('InvalidTag')
}

@@ -134,4 +142,3 @@ }

if (currentTag[symbols.type] === 'closing') {
// 10 is arbitrary, just to show some context by moving the cursor back a bit
throw new TemplateParseError('InvalidClosingTag', template.slice(cursor - 10))
throw TemplateParseError('InvalidClosingTag')
}

@@ -159,5 +166,10 @@ currentTag[symbols.type] = 'self-closing'

//fixme: closing tags cannot have attributes
const parseAttributes = () => {
const attrNameMatch = moveCursorOnMatch(attrNameRegex)
if (attrNameMatch) {
if (currentTag[symbols.type] === 'closing') {
throw TemplateParseError('AttributesInClosingTag')
}
const delimiter = attrNameMatch[2]

@@ -173,6 +185,6 @@ const attrValueRegex = new RegExp(`^(.*?)${delimiter}\\s*`)

} else {
throw new TemplateParseError('MissingOrInvalidAttributeValue', template.slice(cursor))
throw TemplateParseError('MissingOrInvalidAttributeValue')
}
} else {
throw new TemplateParseError('InvalidAttribute', template.slice(cursor))
throw TemplateParseError('InvalidAttribute')
}

@@ -191,6 +203,4 @@ }

// formating and validation
/*
validation rules:
Formatting & validation rules:
#1: Every opening tag must have a corresponding closing tag at the same level. If a closing tag is encountered without

@@ -215,3 +225,3 @@ a preceding opening tag at the same level, or if an opening tag is not followed by a corresponding closing tag at

if (rootElementDefined) {
throw new TemplateParseError('MultipleTopLevelTags', formatErrorContext(element))
throw TemplateStructureError('MultipleTopLevelTags', element)
}

@@ -226,2 +236,3 @@ rootElementDefined = true

[symbols.type]: element[symbols.type],
[symbols.cursorTagStart]: element[symbols.cursorTagStart],
type: element.type,

@@ -240,3 +251,3 @@ parent: currentParent, // helps getting the previous parent when closing tag is encountered

if (isStackEmpty || isLevelMismatch || isTagMismatch) {
throw new TemplateParseError('MismatchedClosingTag', formatErrorContext(element))
throw TemplateStructureError('MismatchedClosingTag', element)
}

@@ -253,2 +264,3 @@

delete newItem[symbols.level]
delete newItem[symbols.cursorTagStart]

@@ -270,20 +282,77 @@ // if it is an opening tag, add children[] to it and update current parent

if (stack.length > 0) {
const unclosedTags = stack
.map((item) => {
return formatErrorContext(item)
})
.join(', ')
throw new TemplateParseError('UnclosedTags', unclosedTags)
throw TemplateStructureError('UnclosedTags', stack)
}
function formatErrorContext(element) {
return `${element.type || 'empty-tag'}[${element[symbols.type]}] at level ${
element[symbols.level]
}`
return output
}
// error reporting
const contextPaddingBefore = 10 // number of characters to show before the error location
const contextPaddingAfter = 50 // number of characters to show after the error location
const TemplateParseError = (message, context) => {
const location = getErrorLocation()
message = `${message} in ${location}`
const error = new Error(message)
error.name = 'TemplateParseError'
// generate context if the error is related to parsing
if (!context) {
const start = Math.max(0, prevCursor - contextPaddingBefore)
const end = Math.min(template.length, cursor + contextPaddingAfter)
const contextText = template.slice(start, end)
// add ^ caret to show where the error is
const caretPosition = cursor - start
error.context = insertContextCaret(caretPosition, contextText)
} else {
error.context = context
}
return error
}
return output
const TemplateStructureError = (message, context) => {
const location = getErrorLocation()
message = `${message} in ${location}`
const error = new Error(message)
error.name = 'TemplateStructureError'
// check if context is an array
if (Array.isArray(context)) {
error.context = context.map((tag) => generateContext(tag)).join('\n')
} else {
error.context = generateContext(context)
}
function generateContext(element) {
const start = Math.max(0, element[symbols.cursorTagStart] - contextPaddingBefore)
const contextText = template.slice(start, start + contextPaddingAfter)
// add ^ caret to show where the error is
return insertContextCaret(contextPaddingBefore, contextText)
}
return error
}
const insertContextCaret = (position, contextText) => {
const caret = ' '.repeat(position) + '^'
return `\n${contextText}\n${caret}\n`
}
const getErrorLocation = () => {
if (parentComponent) {
let hierarchy = componentName || ''
let currentParent = parentComponent
while (currentParent) {
hierarchy = `${currentParent.type}/${hierarchy}`
currentParent = currentParent.parent
}
return hierarchy
}
return filePath ? filePath : 'Blits.Application'
}
return parse()
}

@@ -597,39 +597,2 @@ /*

// test('Parse template with a nameless tag but with arguments', (assert) => {
// const template = `
// <x="100" y="200">
// <x="50" y="20">
// <Component w="100" h="20" />
// </>
// </>`
// const expected = {
// children: [
// {
// type: null,
// x: '100',
// y: '200',
// children: [
// {
// type: null,
// x: '50',
// y: '20',
// children: [
// {
// type: 'Component',
// w: '100',
// h: '20',
// },
// ],
// },
// ],
// },
// ],
// }
// const actual = parser(template)
// assert.deepEqual(actual, expected, 'Parser should return object representation of template')
// assert.end()
// })
test('Parse template with a transition argument (single value)', (assert) => {

@@ -978,4 +941,12 @@ const template = `

const actual = parser(template)
assert.equal(actual, null, 'Parser should throw an error')
try {
parser(template)
assert.fail('Parser should throw TemplateStructureError:MultipleTopLevelTags')
} catch (error) {
assert.equal(error.name, 'TemplateStructureError', 'Parser should throw TemplateStructureError')
assert.ok(
error.message.startsWith('MultipleTopLevelTags'),
'Parser should throw TemplateStructureError:MultipleTopLevelTags'
)
}

@@ -992,4 +963,12 @@ assert.end()

const actual = parser(template)
assert.equal(actual, null, 'Parser should throw an error')
try {
parser(template)
assert.fail('Parser should throw TemplateStructureError:MismatchedClosingTag')
} catch (error) {
assert.equal(error.name, 'TemplateStructureError', 'Parser should throw TemplateStructureError')
assert.ok(
error.message.startsWith('MismatchedClosingTag'),
'Parser should throw TemplateStructureError:MismatchedClosingTag'
)
}
assert.end()

@@ -1010,4 +989,12 @@ })

const actual = parser(template)
assert.equal(actual, null, 'Parser should throw an error')
try {
parser(template)
assert.fail('Parser should throw TemplateStructureError:MismatchedClosingTag')
} catch (error) {
assert.equal(error.name, 'TemplateStructureError', 'Parser should throw TemplateStructureError')
assert.ok(
error.message.startsWith('MismatchedClosingTag'),
'Parser should throw TemplateStructureError:MismatchedClosingTag'
)
}
assert.end()

@@ -1024,4 +1011,12 @@ })

const actual = parser(template)
assert.equal(actual, null, 'Parser should throw an error')
try {
parser(template)
assert.fail('Parser should throw TemplateParseError:InvalidClosingTag')
} catch (error) {
assert.equal(error.name, 'TemplateParseError', 'Parser should throw TemplateParseError')
assert.ok(
error.message.startsWith('InvalidClosingTag'),
'Parser should throw TemplateParseError:InvalidClosingTag'
)
}

@@ -1037,4 +1032,13 @@ assert.end()

const actual = parser(template)
assert.equal(actual, null, 'Parser should throw an error')
try {
parser(template)
assert.fail('Parser should throw TemplateStructureError:MultipleTopLevelTags')
} catch (error) {
assert.equal(error.name, 'TemplateStructureError', 'Parser should throw TemplateStructureError')
assert.ok(
error.message.startsWith('MultipleTopLevelTags'),
'Parser should throw TemplateStructureError:MultipleTopLevelTags'
)
}
assert.end()

@@ -1051,5 +1055,36 @@ })

const actual = parser(template)
assert.equal(actual, null, 'Parser should throw an error')
try {
parser(template)
assert.fail('Parser should throw TemplateStructureError:MismatchedClosingTag')
} catch (error) {
assert.equal(error.name, 'TemplateStructureError', 'Parser should throw TemplateStructureError')
assert.ok(
error.message.startsWith('MismatchedClosingTag'),
'Parser should throw TemplateStructureError:MismatchedClosingTag'
)
}
assert.end()
})
test('Parse template with a closing tag that has attributes and parsing should fail', (assert) => {
const template = `
<Component>
<Text>Lorem ipsum dolor sit amet</Text>
<Element></Element x="200">
</Component>
`
try {
parser(template)
assert.fail('Parser should throw TemplateParseError:AttributesInClosingTag')
} catch (error) {
assert.equal(error.name, 'TemplateParseError', 'Parser should throw TemplateParseError')
assert.ok(
error.message.startsWith('AttributesInClosingTag'),
'Parser should throw TemplateParseError:AttributesInClosingTag'
)
}
assert.end()
})
import parser from '../src/lib/templateparser/parser.js'
import generator from '../src/lib/codegenerator/generator.js'
import path from 'path'

@@ -11,3 +12,3 @@ export default function () {

},
transform(source) {
transform(source, filePath) {
if (config.blits && config.blits.precompile === false) return source

@@ -31,3 +32,8 @@ if (source.indexOf('Blits.Component(') > -1 || source.indexOf('Blits.Application(') > -1) {

// Parse the template
const parsed = parser(templateContentResult[1])
let resourceName = 'Blits.Application'
if (source.indexOf('Blits.Component(') > -1) {
resourceName = source.match(/Blits\.Component\(['"](.*)['"]\s*,/)[1]
}
const componentPath = path.relative(process.cwd(), filePath)
const parsed = parser(templateContentResult[1], resourceName, null, componentPath)

@@ -34,0 +40,0 @@ // Generate the code

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc