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

@semantic-ui/templating

Package Overview
Dependencies
Maintainers
1
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@semantic-ui/templating - npm Package Compare versions

Comparing version 0.0.20 to 0.0.21

12

package.json

@@ -8,9 +8,9 @@ {

"dependencies": {
"@semantic-ui/component": "^0.0.20",
"@semantic-ui/query": "^0.0.20",
"@semantic-ui/reactivity": "^0.0.20",
"@semantic-ui/templating": "^0.0.20",
"@semantic-ui/utils": "^0.0.20"
"@semantic-ui/component": "^0.0.21",
"@semantic-ui/query": "^0.0.21",
"@semantic-ui/reactivity": "^0.0.21",
"@semantic-ui/templating": "^0.0.21",
"@semantic-ui/utils": "^0.0.21"
},
"version": "0.0.20"
"version": "0.0.21"
}

@@ -31,3 +31,3 @@ import { each, isString, last } from '@semantic-ui/utils';

VERBOSE_PROPERTIES: /(\w+)\s*=\s*(((?!\w+\s*=).)+)/gms,
STANDARD: /(\w.*?)($|\s)/gm,
STANDARD: /(\w+)\s*=\s*((?:(?!\n|$|\w+\s*=).)+)/g,
DATA_OBJECT: /(\w+)\s*:\s*([^,}]+)/g, // parses { one: 'two' }

@@ -260,15 +260,9 @@ };

let data = {};
const matches = [...expression.matchAll(regExp.STANDARD)];
each(matches, (match, index) => {
if (index == 0) {
templateInfo.name = `'${match[0].trim()}'`;
}
else {
const parts = match[0].split('=');
if (parts.length) {
let name = parts[0].trim();
let value = parts[1].trim();
data[name] = value;
}
}
const name = expression.split(/\b/)[0];
templateInfo.name = `'${name}'`;
const dataMatches = [...expression.matchAll(regExp.STANDARD)];
each(dataMatches, (match, index) => {
let name = match[1].trim();
let value = match[2].trim();
data[name] = value;
});

@@ -275,0 +269,0 @@ templateInfo.data = data;

@@ -8,2 +8,3 @@ import { Reaction } from '@semantic-ui/reactivity';

formatDate,
each,
escapeHTML,

@@ -33,2 +34,5 @@ tokenize,

},
concat(a, b) {
return a + b;
},
not(a) {

@@ -50,2 +54,11 @@ return !a;

},
classMap(classObj) {
let classNames = [];
each(classObj, (condition, className) => {
if(condition) {
classNames.push(className);
}
});
return (classNames.length) ? `${classNames.join(' ')} `: '';
},
maybe(expr, trueExpr, falseExpr) {

@@ -52,0 +65,0 @@ return expr ? trueExpr : falseExpr;

import { $ } from '@semantic-ui/query';
import { capitalize, fatal, each, remove, generateID, isEqual, noop, isServer, inArray, isFunction, extend, wrapFunction } from '@semantic-ui/utils';
import { capitalize, fatal, each, remove, clone, generateID, isEqual, noop, isServer, inArray, isFunction, extend, wrapFunction } from '@semantic-ui/utils';
import { ReactiveVar, Reaction } from '@semantic-ui/reactivity';

@@ -23,3 +23,3 @@

events,
state,
stateConfig,
subTemplates,

@@ -46,3 +46,4 @@ createInstance,

this.reactions = [];
this.state = state || {};
this.stateConfig = stateConfig;
this.state = this.createReactiveState(stateConfig) || {};
this.templateName = templateName || this.getGenericTemplateName();

@@ -60,2 +61,3 @@ this.subTemplates = subTemplates;

this.isPrototype = isPrototype;
this.parentTemplate = parentTemplate;
this.attachStyles = attachStyles;

@@ -69,2 +71,18 @@ this.element = element;

createReactiveState(stateConfig) {
let reactiveState = {};
each(stateConfig, (config, name) => {
if(config?.value && config?.options) {
// complex config { counter: { value: 0, options: { equalityFunction }}}
reactiveState[name] = new ReactiveVar(config.value, config.options);
}
else {
// simple config i.e. { counter: 0 }
const initialValue = config;
reactiveState[name] = new ReactiveVar(initialValue);
}
});
return reactiveState;
}
setDataContext(data, { rerender = true } = {}) {

@@ -188,2 +206,3 @@ this.data = data;

...this.data,
...this.state,
...this.tpl,

@@ -226,2 +245,3 @@ };

css: this.css,
stateConfig: this.stateConfig,
events: this.events,

@@ -233,2 +253,3 @@ renderingEngine: this.renderingEngine,

onRendered: this.onRenderedCallback,
parentTemplate: this.parentTemplate,
onDestroyed: this.onDestroyedCallback,

@@ -243,17 +264,9 @@ createInstance: this.createInstance,

attachEvents(events = this.events) {
if (!this.parentNode || !this.renderRoot) {
fatal('You must set a parent before attaching events');
}
this.removeEvents();
// format like 'click .foo baz'
const parseEventString = (eventString) => {
const parts = eventString.split(' ');
let eventName = parts[0];
parts.shift();
const selector = parts.join(' ');
parseEventString(eventString) {
// we are using event delegation so we will have to bind
// some events to their corresponding event that bubbles
const getBubbledEvent = (eventName) => {
const bubbleMap = {
blur: 'focusout',
focus: 'focusin',
//change: 'input',
load: 'DOMContentLoaded',

@@ -264,8 +277,46 @@ unload: 'beforeunload',

};
if (bubbleMap[eventName]) {
if(bubbleMap[eventName]) {
eventName = bubbleMap[eventName];
}
return { eventName, selector };
return eventName;
};
let events = [];
let parts = eventString.split(/\s+/);
let addedEvents = false;
const eventNames = [];
const selectors = [];
each(parts, (part, index) => {
const value = part.replace(/(\,|\W)+$/, '').trim();
if(!addedEvents) {
eventNames.push(getBubbledEvent(value));
addedEvents = (part.includes(',') === false);
}
else {
selectors.push(value);
}
});
if(eventNames.length > 1) {
each(eventNames, (eventName) => {
events.push({ eventName, selector: selectors[0] });
});
}
else if(selectors.length > 1) {
each(selectors, (selector) => {
events.push({ eventName: eventNames[0], selector });
});
}
else {
events.push({ eventName: eventNames[0], selector: selectors[0] || '' });
}
return events;
}
attachEvents(events = this.events) {
if (!this.parentNode || !this.renderRoot) {
fatal('You must set a parent before attaching events');
}
this.removeEvents();
// this is to cancel event bindings when template tears down

@@ -288,38 +339,37 @@ // <https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal>

each(events, (eventHandler, eventString) => {
const { eventName, selector } = parseEventString(eventString);
const subEvents = this.parseEventString(eventString);
const template = this;
// BUG: iOS Safari will not bubble the touchstart / touchend events
// if theres no handler on the actual element
if(selector) {
$(selector, { root: this.renderRoot }).on(eventName, noop);
}
$(this.renderRoot).on(
eventName,
selector,
(event) => {
if (!this.isNodeInTemplate(event.target)) {
console.log('ignored event because it is not in template', eventName, selector);
return;
}
if (
(eventName === 'mouseover' || eventName === 'mouseout') &&
event.relatedTarget &&
event.target.contains(event.relatedTarget)
) {
return;
}
const targetElement = (selector)
? $(event.target).closest(selector).get(0) // delegation
: event.target
;
const boundEvent = eventHandler.bind(targetElement);
const eventData = event?.detail || {};
const elData = targetElement.dataset;
template.call(boundEvent, {
additionalData: { event: event, data: { ...elData, ...eventData } },
});
},
{ abortController: this.eventController }
);
each(subEvents, (event) => {
const { eventName, selector } = event;
// BUG: iOS Safari will not bubble the touchstart / touchend events
// if theres no handler on the actual element
if(selector) {
$(selector, { root: this.renderRoot }).on(eventName, noop);
}
$(this.renderRoot).on(
eventName,
selector,
(event) => {
if (!this.isNodeInTemplate(event.target)) {
return;
}
if (inArray(eventName, ['mouseover', 'mouseout'])
&& event.relatedTarget
&& event.target.contains(event.relatedTarget)) {
return;
}
const targetElement = (selector)
? $(event.target).closest(selector).get(0) // delegation
: event.target
;
const boundEvent = eventHandler.bind(targetElement);
const eventData = event?.detail || {};
const elData = targetElement.dataset;
template.call(boundEvent, {
additionalData: { event: event, data: { ...elData, ...eventData } },
});
},
{ abortController: this.eventController }
);
});
});

@@ -339,3 +389,7 @@ }

while (node && node.parentNode !== this.parentNode) {
node = node.parentNode;
if (node.parentNode === null && node.host) {
node = node.host;
} else {
node = node.parentNode;
}
}

@@ -353,3 +407,3 @@ return node;

if (node === null) {
return;
return false;
}

@@ -415,3 +469,3 @@ const startComparison = startNode.compareDocumentPosition(node);

$$(selector, args) {
return this.$(selector, { root: this.renderRoot, filterTemplate: false, ...args });
return this.$(selector, { root: this.renderRoot, pierceShadow: true, filterTemplate: true, ...args });
}

@@ -432,2 +486,3 @@

$: this.$.bind(this),
$$: this.$$.bind(this),

@@ -439,7 +494,7 @@ reaction: this.reaction.bind(this),

settings: this.element.settings,
state: this.element.state,
state: this.state,
isRendered: this.rendered,
isServer: Template.isServer,
isClient: !Template.isServer, // convenience
isClient: !Template.isServer,

@@ -446,0 +501,0 @@ dispatchEvent: this.dispatchEvent.bind(this),

@@ -667,2 +667,85 @@ import { describe, expect, it, vi } from 'vitest';

});
it('should compile a template with a partial and data containing parentheses', () => {
const compiler = new TemplateCompiler();
const template = `
<div>
{{> CodePlaygroundPanel size=(getPanelSize) }}
</div>
`;
const ast = compiler.compile(template);
const expectedAST = [
{ type: 'html', html: '<div>\n ' },
{
type: 'template',
name: "'CodePlaygroundPanel'",
data: { size: '(getPanelSize)' },
},
{ type: 'html', html: '\n </div>' },
];
expect(ast).toEqual(expectedAST);
});
it('should compile a template with a partial and data containing parentheses and spaces', () => {
const compiler = new TemplateCompiler();
const template = `
<div>
{{> CodePlaygroundPanel size=(getPanelSize panel) }}
</div>
`;
const ast = compiler.compile(template);
const expectedAST = [
{ type: 'html', html: '<div>\n ' },
{
type: 'template',
name: "'CodePlaygroundPanel'",
data: { size: '(getPanelSize panel)' },
},
{ type: 'html', html: '\n </div>' },
];
expect(ast).toEqual(expectedAST);
});
it('should compile a template with a partial and data containing line breaks', () => {
const compiler = new TemplateCompiler();
const template = `
<div>
{{> CodePlaygroundPanel
panel=panel
size=(getPanelSize panel)
}}
</div>
`;
const ast = compiler.compile(template);
const expectedAST = [
{ type: 'html', html: '<div>\n ' },
{
type: 'template',
name: "'CodePlaygroundPanel'",
data: { panel: 'panel', size: '(getPanelSize panel)' },
},
{ type: 'html', html: '\n </div>' },
];
expect(ast).toEqual(expectedAST);
});
it('should compile a template with a partial and data containing multiple parentheses', () => {
const compiler = new TemplateCompiler();
const template = `
<div>
{{> CodePlaygroundPanel size=(getPanelSize (getPanel)) }}
</div>
`;
const ast = compiler.compile(template);
const expectedAST = [
{ type: 'html', html: '<div>\n ' },
{
type: 'template',
name: "'CodePlaygroundPanel'",
data: { size: '(getPanelSize (getPanel))' },
},
{ type: 'html', html: '\n </div>' },
];
expect(ast).toEqual(expectedAST);
});
});

@@ -738,2 +821,5 @@

});
});

@@ -740,0 +826,0 @@

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