Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
the simplest plug-in has the form:
<unit>
<view-source>
import { stream } from "m2"
export default ({ source/*, targets */}) => {
return stream( (emt, { over }) => {
over.add(source.on((evt, src) => {
emt(evt, src);
}));
} );
}
</view-source>
</unit>
you can access nested nodes and modify them
<unit>
<view-source>
import { stream } from "m2"
export default ({ source, targets: [ { node } ] }) => {
const inner = node.querySelector("[custom-plugin-inner]");
return stream( (emt, { over }) => {
over.add(source.on(emt ));
inner.textContent = 77;
} );
}
</view-source>
<div>
<span custom-plugin-inner>custom-value</span>
</div>
</unit>
you can also modify the data stream before use:
<unit>
<stream-source>
import { stream } from "m2"
export default ({ obtain }) =>
obtain().map( data => [data] )
</stream-source>
</unit>
data transmission from events
<span>`${property}`</span>
the event source must have the form
[{property: 77}]
the data source can be an object with a nested structure
<span>`${somefield.nested}`</span>
[{somefield: {nested: 77} }]
formatting
if you provide number settings, you can use formatting:
<span>`${intl.formatter-resource-name(value)}`</span>
,where {formatter-resource-name}
- data transmission template
the event source must have the form
[{property: 77}]
formatting resource file example:
[
"formatters",
["currency", { "style": "currency", "splitter": ".", "currencyDisplay": "symbol" }],
["compact-currency", { "style": "currency", "splitter": ".", "currencyDisplay": "symbol",
"minimumFractionDigits": 0
}],
["number", { "style": "decimal", "splitter": "." }],
["percent", { "style": "percent" }]
]
localization
if you supply localization resources you can use automatic literal substitution:
<span>`${lang.localization-string-resource-name}`</span>
localization resource file example:
<?xml version="1.0" encoding="utf-8"?>
<languages>
<en>
<string name="example-literal-string">Example literal text content</string>
<string name="example-literal-string-2">Example literal text content 2</string>
</en>
<ru>
<string name="example-literal-string">Пример случайной строки</string>
<string name="example-literal-string-2">Пример случайной строки 2</string>
</ru>
</languages>
<keyframe [name = default] [prop = {easing:"linear",duration:5}] >
<key [offset = 0] prop = {scale:0}></key>
<key [offset = 1] prop = {scale:1}></key>
</keyframe>
inline fade-in fade-out supported
<keyframe name = fade-in [duration = 5]>
<key [offset = 0] prop = {translateX:0}></key>
<key [offset = 1] prop = {translateX:100}></key>
</keyframe>
binding data from stream
<keyframe name = fade-in [duration = 5]>
<key prop = {scaleX:(x)}></key>
</keyframe>
[{x: 1.5}]
<unit>
<style [type="text/scss"]> <!-- to enable SASS processing -->
body { /* global selector */
padding: 0;
margin: 0;
}
:scope { /* local selector */
width: 100%;
background-color: #0026ff;
height: 100%;
}
</style>
<div></div>
</unit>
<keyframe>
<key prop = {classList:{active:(isactive)}}></key>
</keyframe>
[{isactive: true}]
or
<keyframe>
<key prop = {classList:{red|green|black:(selectedColor)}}></key>
</keyframe>
[{selectedColor: "red"}]
<keyframe name="animation-name">
<key prop={sound:'sound-name'}></key>
</keyframe>
Sound will be played once
or
<keyframe name="animation-name" prop="{duration: 2}">
<key offset="0.2" prop={sound:'sound-name'} ></key>
<key offset="0.7" prop={sound:'sound-name'} ></key>
</keyframe>
Sounds will be played 2 times with certain offsets and will be stopped if duration of animation less than duration of sounds
, where
sound
- name of resource declared in <sound>
tagSound resource declaration
<sound name="sound-name" rel="sound-resource"></sound>
, where
name
- name of resourcerel
- file name without extension from the directory
component/res/sounds/sound-resource
if you want to use the general sounds for components, you can go up the nesting levels
rel="../../sound-resource"
<unit onclick = req("action-name",{/*args*/})></unit>
where environment variables:
"onclick"
"onclickoutside" (synthetic)
"onpointermove"
"onpointerenter"
"onpointerleave"
"onpointerup"
"onpointerdown"
"onmouseenter"
"onmouseleave"
"onmouseover"
"onmouseout"
"onchange"
"oninput"
"onglobalkeydown" (synthetic)
"onglobalkeyup" (synthetic)
"onkeydown"
"onkeyup"
"onwheel"
"onscroll"
also supported custom events
"on:custom-event"
<view-source>
import { stream } from "m2"
class MyEvent extends Event {
constructor() {
super("my-event");
this.myData = 100;
}
log() {
console.log("check", this);
}
}
export default ({ source, targets }) => {
return stream( (emt, { over }) => {
over.add(source.on((evt, src) => {
setTimeout( () => {
targets[0].node.dispatchEvent(new MyEvent());
}, 1000);
emt(evt, src);
}));
} );
}
</view-source>
selects one view state available according to the model.
<unit tee = {a:10,b:-1}></unit>
rendered to the page if the condition when mapping data from the stream is fully met
[{a: 10, b: -1, ...other}]
or not rendered
[{a: 10, b: -2, ...other}]
allowed to use attachments and abbreviated forms
<unit tee = {obj:{prop}}></unit>
[{obj: {prop: 1}}]
functional form is also now supported
<unit tee() = "obj.prop > 0"></unit>
[{obj: {prop: 1}}]
you can even use a static form
<unit tee() = 1></unit>
however, the view component will still wait for the model stream
you can link your view to the stream to get actions and process reactions
<unit stream = ./path>
any relative path will be calculated relative to the parent view, which is related to the model.
you can use the constant $name
as a parameter to pass the current name of the view to the model
<unit stream = ./path/to/model[key=$name]>
you can use the included submodules
<unit use = url(./path-to-src-module)></unit>
or
<unit use = ./path-to-registered-module></unit>
each model is a function that returns a stream:
it is a new stream
import { stream } from "m2"
export default ( { /*...args*/ } ) =>
stream(emt => {
emt( "something" );
})
, where
or an existing converted stream
import { stream } from "m2"
export default ( { obtain, /*...args*/ } ) =>
obtain("../some/existing-stream/path")
.map( count => count + 1 )
.controller(
obtain("../some/existing-stream-controller/path"),
({action}) => ({ action, data: "ok" })
)
, where
can be specified in the "obtain" method
obtain("./path", { argv: 10 })
or right on the path
obtain("./path[argv=10]")
the simplest path has the form:
"./cat-a/cat-b/cat-c"
"./cat-a"
- entry to the directory"./"
- current directory"../"
- parent directory"./{name: abc, kind: 10}"
- directories with a complex name"./cat-a[kind=10]"
- passing arguments"./#component-id"
- search by id"./@component-key"
- search by keyNote: when using search by id or key it begins from parent layer and move upward until root layer. So, sometimes you MUST specify exact path to model
FAQs
the simplest plug-in has the form:
We found that air-m2 demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.