Code Monkey home page Code Monkey logo

refactored-pancake's Introduction

Beremiz POC

List of doable things that could be implemented later for a vscode/theia version of Beremiz.

This repo has two main goals:

  • Find a way to build beremiz core mechanics in js.
  • Make sure these features are isomorphic and can work in both browser & Node.Js.
Feature Browser Node.Js
Xslt processor ✔️ ✔️
Xslt js function callback ✔️ ✔️
Xslt dom access ✔️
XPath ✔️ ✔️
Xsd validation ✔️ ✔️
Matiec WASM ✔️ ✔️
gettext ✔️ ✔️

This repository is a pnpm workspace. Make sure you have pnpm and Node.js 18+ installed.

It contains 3 packages:

  • core: Xml/Xslt/Xsd implementations.
  • matiec: WASM toolchain to compile & run matiec as a WASM module using emscripten.
  • matiec-demo: A demo of matiec using nuxt & monaco editor in browser. DEMO

There is currently no build system such as lerna to have global build/test scripts.

To run tests or build, clone or fork this repo and then:

cd packages/[package]
pnpm run test or build

To build matiec demo SPA, use generate

cd packages/matiec-demo
pnpm run generate

Note

The matiec package has a DockerFile which clones matiec repository and runs the emcc compiler.

Running docker won't be enough as we need to copy the output inside the src folder.

The matiec-2-wasm Powershell file is here to run all this process automatically. See matiec for more.

Saxon

Usage of saxon

Saxonica provides the saxon-js package to overcome built-in Xslt browser limitations.

The library can also support evaluations of js functions. The globalThis object is available in all environments, so i declared all xslt functions as keys of globalThis.

Moreover, Typescript can be easily extended using module declarations.

declare module globalThis {
    function ConfigTagName(_name: SaxonNode): void
    function ResourceTagName(_ancestor: SaxonNode, _name: SaxonNode): void
}

You can see how all beremiz collectors are implemented in core/plcopen/collectors

DOM

DOM access should not be a problem since saxon has access to global context. However, it is impossible to access DOM on Node.js for obvious reasons.

XPath

XPath with saxon is different from lxml, for example, the following code from plcopen.py:

def getpous(self, exclude=None, filter=None):
    filter = [] if filter is None else filter
    return self.xpath(
        "ppx:types/ppx:pous/ppx:pou%s%s" %
        (("[@name!='%s']" % exclude) if exclude is not None else '',
         ("[%s]" % " or ".join(
             ["@pouType='%s'" % x for x in filter]))
         if len(filter) > 0 else ""),
        namespaces=PLCOpenParser.NSMAP)

Would be like this with saxon:

const getPous = (exclude?: string, filter: string[] = []) => {
    let clause1 = exclude !== null ? `[@name!='${exclude}']` : '';
    let clause2 = filter.length > 0
        ? `[${filter.map(x => `@pouType='${x}'`).join(' or ')}]`
        : '';

    return saxon.XPath.evaluate(`//ppx:types/ppx:pous/ppx:pou${clause1}${clause2}`, this._beremizFile, { ...ns, resultForm: "array" })
        .map(x => ({
            getName: saxon.XPath.evaluate('@name', x, ns).value,
            getPouType: saxon.XPath.evaluate('@pouType', x, ns).value,
            getBodyType: saxon.XPath.evaluate('local-name(./body/*[1])', x, ns)
        }))
}

Because we can't have direct access to the attributes the same way as lxml, we return a list of getters for each POU the first evaluate function could find.

XSD

While we can leverage a lot from saxon-js, It can't validate xsd schemas.

But recently someone decided to make a port of libxml2 to wasm using emscripten.

So TC6 validation is available.

Matiec

Matiec can be compiled to WebAssembly with emcc.

The output is a single ES6 module thanks to --SINGLE-FILE parameter, and the wasm binary is stored inside the js file.

Note

Both iec2c & iec2iec executables are generated, but I could not find a usage of iec2iec executable in Beremiz source code, so only iec2c is bundled.

This is how the PowerShell scripts compile matiec:

graph LR
    A[matiec repo]
    B[matiec source]
    C[wasm output]
    D[PowerShell]
    F[src folder]

    subgraph E[Docker]
        A
        B
        C
    end
    
    A --cloned--> B
    B ==compiled with emcc ==> C
    C --copy wasm output --> F
    D --mount--> E
    
Loading

Bundler

I've decided to choose esbuild as it became my weapon of choice for web libraries over the last years.

This is purely opinion-based and can be changed to webpack or rollup depending on future needs.

Since saxon-js needs XSLT files to be converted to SEF (stylesheet export file) first, the bundler will also compile all XSLT files to *.sef.json.

graph LR
    A[.ts]
    B[.xslt]
    C[.xsd/.xml/.csv]
    D[.sef.json]
    E[.js]
    F[.d.ts]
    G[.po]

    subgraph "src folder"
        A
        B
        C
        G
    end

    subgraph "dist folder"
        E
        F
    end

    A -- emit js with tsc --> E
    A -- emit declarations with tsc --> F
    B -- compile using XSLT3 XX --> D
    C -- transform --> E
    D -- transform --> E
    G -- transform --> E
Loading

Both .js & .d.ts are emitted for typescript, so non-ts user can use the package in a pure javascript project.

This configuration allows us to import all non-js files directly in js, esbuild will take care of the rest.

gettext

Support for gettext is available thanks to gettext.js

gettext is available as a global singleton and locales can be loaded automatically.

Warning

gettext.js does not seem to support "%s" & "%a1" placeholders. Therefore, all placeholders have been converted to numeric ones. The original .po files remain unchanged, everything is done during the build process.

Front end frameworks

Most front end frameworks heavily use JSON for their template and reactivity system.

At first, you might be thinking a painful conversion between XML -> JSON and then JSON -> XML is the only way.

But some frameworks allow the developers to override their reactivity systems such as vue customRef.

An implementation of customRef could be like this:

import { customRef } from 'vue'

export function getPous(XpathGet, XPathSet) {
    return customRef((track, trigger) => {
        return {
            get() {
                // Do some XPATH stuff here to get a value ...
                track()
                return value
            },
            set(newValue) {
                // Do some XPATH stuff here to change a value ...
                trigger()
            }
        }
    })
}

Then we can use getPous and have reactive objects compatible with templates.

<script setup>
  import { getPous } from './plc'
  const allPous = getPous(XpathGet, XpathSet)
</script>

<template>
  <span>{{ allPous }}</span>
</template>

refactored-pancake's People

Contributors

adclz avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.