Git Product home page Git Product logo

powerapps-tooling's Introduction

image image Build Status

Power Apps Source File Pack and Unpack Utility

This project is still in Experimental - format may change

We welcome feedback on the project, file format, and capabilities.

This tool enables Canvas apps to be edited outside of Power Apps Studio and managed in a source control tool such as GitHub. The basic work flow is:

  1. Download an existing Canvas app as a .msapp file, using File > Save as > This computer in Power Apps Studio.
  2. Use this tool to extract the .msapp file into editable source files.
  3. Edit these files with any text editor.
  4. Check these files into any source control manager.
  5. Use this tool to recreate a .msapp file from the editable source files.
  6. Upload the .msapp file using File > Open > Browse in Power Apps Studio.

This is similar to the Solution Packager for Microsoft Dataverse.

Power Platform CLI usage

To get started, download and install the Microsoft Power Platform CLI.

Easiest way to get pac cli is to use dotnet tool install:

dotnet tool install --global Microsoft.PowerApps.CLI.Tool

To unpack a .msapp file:

pac canvas unpack --msapp FromApp.msapp --sources ToSourceFolder

To pack a .msapp file:

pac canvas pack --msapp ToApp.msapp --sources FromSourceFolder

Versioning

The output files (ie, "yaml version") have a version number. During preview, the tool is not backwards compatible, so the version used to re-pack must match the version used to pack. When unpacking, keep a copy of the original msapp so that you can unpack it with future versions of the tool.

Pac CLI Version Yaml version
1.7.2 0.23
1.7.4 0.23
1.8.5 0.24

Latest Yaml version is: https://github.com/microsoft/PowerApps-Language-Tooling/blob/0a4c9e624ffad1f93b6c085aff029945a0fbc00a/src/PAModel/Serializers/SourceSerializer.cs#L49

Test app usage

You can also use this functionality stand alone, using our test console app.

Download and install the .NET Core SDK v6.0.x (x64) in order to build. Build the test console app by running: \build.cmd This will create: \bin\Debug\PASopa\PASopa.exe

To unpack a .msapp file: pasopa -unpack FromApp.msapp ToSourceFolder To pack a .msapp file: pasopa -pack ToApp.msapp FromSourceFolder

Folder structure

Unpack and pack use this folder structure:

  • \src - the control and component files. This contains the sources.
    • *.fx.yaml - the formulas extracted from the control.json file. This is the place to edit your formulas.-
    • CanvasManifest.json - a manifest file. This contains what is normally in the header, properties, and publishInfo.
    • *.json - the raw control.json file.
    • \EditorState*.editorstate.json - cached information for Studio to use.
  • \DataSources - all data sources used by the app.
  • \Connections - connection instances saved with this app and used when reloading into studio.
  • \Assets - media files embedded in the app.
  • \pkgs - A downloaded copy of external references, such as templates, API Definition files, and component libaries. These are similar to nuget/npm references.
  • \other - all miscellaneous files needed to recreate the .msapp
    • entropy.json - volatile elements (like timestamps) are extracted to this file. This helps reduce noisy diffs in other files while ensuring that we can still round trip.
    • Holds other files from the msapp, such as what is in \references

File format

The .fx.yaml files use a subset of YAML. Most notably and similar to Excel, all expressions must begin with an = sign. More details are available here

Merging changes from Studio

When merging changes made in two different Studio sessions:

  • Ensure that all control names are unique. It is easy for them not to be, as inserting a button in two different sessions can easily result in two Button1 controls. We recommend naming controls soon after creating them to avoid this problem. The tool will not accept two controls with the same name.
  • Ensure variable and collection names don't conflict. These won't have merge conflicts, but they can have semantic conflicts.
  • For these files, merge them as you normally would:
    • \src*.fx.yaml
  • If there are conflicts or errors, you can delete these files:
    • \src\editorstate*.json - These files contain optional information in studio (such as whether a control is locked for editing).
    • \Entropy* - this includes checksum.json and entropy.json.
    • \Connections* - these files save per-org connection information. Deleting them is similar to "logging out". Note for security purposes, these files don't include the actual login tokens, they just include a guid pointing into the environment where the login tokens are stored.
  • If there are any merge conflicts under these paths, it is not safe to merge. Let us know if this happens often and we will work on restructuring the file format to avoid conflicts. However, it is safe to add whole files when they don't conflict.
    • \DataSources*
    • \pkgs*
    • CanvasManifest.json

When merging multiple apps together into a single app:

  • Be sure to merge App.OnStart formulas together.

Known Issues

For a list of commonly known issues around pack and unpack and instructions for workarounds to resolve them please head over here

Contributing

We welcome feedback on the design, file format, and capabilities. Comments and issues are very welcome.

This project is still experimental and we routinely refactor the folder structure, file format, and implementation in big ways. As such, we aren't yet accepting code contributions until we are more stable.

Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

Before making a Pull Request, please file an Issue and solicit discussion.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

Setting up a dev box

For a developer machine (Windows 10, WSL, Linux, macOS), install:

Building and running tests

After cloning this repo (https://github.com/microsoft/PowerApps-Language-Tooling), open a terminal/cmd/PS prompt with the dotnet executable on the path. Check with: dotnet --version

To build, run tests and produce nuget packages, run this command:

./build ci

To list all build targets, run: ./build --list-tree

To see other build help, run: ./build --help

powerapps-tooling's People

Contributors

akjana35 avatar akshar2401 avatar anpetroc avatar arpavan avatar cwduncan avatar davidjenni avatar davidyack avatar gesnaaggarwal avatar ghurlman avatar gregli-msft avatar jack-work avatar joem-msft avatar jt000 avatar landonarogers avatar lesaltzm avatar microsoft-github-operations[bot] avatar microsoftopensource avatar mikefactorial avatar mikestall avatar milantomic6 avatar mizrael avatar msyuey avatar navneetthekkumpat avatar petrochuk avatar rnwoodhcl avatar shpakh-msft avatar suskumar-msft avatar tehcrashxor avatar tomjschneider avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

powerapps-tooling's Issues

Proper error reporting

Remove the Console.WriteLines and use a proper error reporting callback.
The host (PAC CLI) can then implement this callback and show errors properly.

oom on msapps with large files

The basic problem is that we load the entire msapp into memory (CanvasDocument).

And then oom at places like this:

                        case FileKind.AppCheckerResult:
                            var appChecker = Encoding.UTF8.GetString(entry.ToBytes());
                            app._entropy.AppCheckerResult = appChecker;
                            break;

We should calculating this in a streaming way rather than ToBytes().
(sarif file can be huge)

We should scrutinize usage of FileEntry.ToBytes, and probably need to be lazier and have documents backed by disk.

Review use of YAML

YAML is like marmite - you either love it or hate it! I think there an opportunity here for an open community discussion around the use of YAML as the 'source code format' - possibly from the perspective of:

  1. Diff/Merge - we obviously want it easily diff/merge in source control and ALM - would alternatives (e.g. JSON/XML/Other) make it easier or harder to diff/merge?
  2. Authoring Experience - if it is intended that this 'language' be used to write apps 'by hand' - then is the format going to support that and be easy to learn? Should there be an editor that understands the format and can provide IntelliSense?

A number of starting points to discuss spring to mind:

  1. Verbosity - Some formats like XML are very verbose - JSON can also be quite verbose especially where you have string escaping inside string escaping.
    E.g Consider the following YAML
imgControl As image:
    Image: =If(varCurrentMode=ThisItem.ani,ThisItem.imgSel,ThisItem.imgOff)
    ZIndex: =1
    Width: =82
    Height: =151
    ImagePosition: =ImagePosition.Fill
    OnSelect: |
        // explode all lemmings
        UpdateIf(colLemmings,ani<>"" && Not(ani in ["explode","explode_done","splut_done"]),{
            countdown:10
        });

In JSON the OnSelect value would look far more verbose with lots of escaping - this does make it harder to read.

{
  "imgControl As image": {
    "Image": "If(varCurrentMode=ThisItem.ani,ThisItem.imgSel,ThisItem.imgOff)",
    "ZIndex": 1,
    "Width": 82,
    "Height": 151,
    "ImagePosition": "ImagePosition.Fill",
    "OnSelect": "// explode all lemmings\n                    UpdateIf(colLemmings,ani<>\"\" && Not(ani in [\"explode\",\"explode_done\",\"splut_done\"]),{\n                        countdown:10\n                    });"
  }
}

What do folks think - is there a better option to YAML from this perspective?

  1. Indentation/Escaping/New Lines - If this format is intended to be written by hand then how hard will the format be for people to learn? Especially where there are multi-line expressions that all need to be indented the same as the parent containing YAML element
    E.g. Consider the following that will pack:
        imgControl As image:
            Image: =If(varCurrentMode=ThisItem.ani,ThisItem.imgSel,ThisItem.imgOff)
            ZIndex: =1
            Width: =82
            Height: =151
            ImagePosition: =ImagePosition.Fill
            OnSelect: |
                =Set(varCurrentMode,ThisItem.ani);
                If(ThisItem.ani="nuke",

but the following will throw the error Can't have empty multiline expressions. or Missing ':'. If this is a multiline property, use | at ... (because the =Set is not indented correctly).

        imgControl As image:
            Image: =If(varCurrentMode=ThisItem.ani,ThisItem.imgSel,ThisItem.imgOff)
            ZIndex: =1
            Width: =82
            Height: =151
            ImagePosition: =ImagePosition.Fill
            OnSelect: |
=Set(varCurrentMode,ThisItem.ani);
            If(ThisItem.ani="nuke",

This will make it difficult to copy/paste code between expressions - without some IDE tooling.

What do folks think about the alternatives to YAML from the perspective of indentation/escaping/newlines?

  1. Consistency - How important do folks value this? Currently, some of the elements are unpacked as json and some as yaml - should there be a sinle format for all elements apart from resources such as images?
    For perspective - for a large app, the majority of the files in the unpacked files are JSON and XML (Data sources, Resource metadata, etc.)

What do folks think - is consistency important?

Shard PropertyJson.LibraryDependencies

When consuming a component via a libraries, in the Consumer, there’s this in propertiesJson:

"LibraryDependencies": "[{\"LibraryId\":\"737b973d-124d-4927-83a4-799e6b60c49b\",\"LibraryLogicalName\":\"\",\"OriginalComponentDefinitionTemplateId\":\"51d8f4a68c934385b451a1bedba9d8ed\",\"SourceLastTimeSaved\":\"2021-01-05T20:12:30.194+00:00\",\"RefusedSourceLastTimeSaved\":\"0001-01-01T00:00:00\",\"InstanceCount\":1}]",

[
{
"LibraryId": "737b973d-124d-4927-83a4-799e6b60c49b",
"LibraryLogicalName": "",
"OriginalComponentDefinitionTemplateId": "51d8f4a68c934385b451a1bedba9d8ed",
"SourceLastTimeSaved": "2021-01-05T20:12:30.194+00:00",
"RefusedSourceLastTimeSaved": "0001-01-01T00:00:00",
"InstanceCount": 1
}
]

This guid points back to Component1.json.

Action:

  1. Need to shard Properties.LibraryDependencies. This is nested json. Maybe this is a new “ComponentsReference.json” file?
  2. Do we do anything special for the copy of the component in the Consumer?

Test failing due to newline encoding issues

YamlWriter test is failing on windows when download from Zip due to CRLF issues:

Expected:<P0: =abc\nObj1:\n P1a: |-\n =A#B\n P1b: =B\n Obj2:\n P2a: =A\n P1c: =C\n>.
Actual: <P0: =abc\r\nObj1:\r\n P1a: |-\r\n =A#B\r\n P1b: =B\r\n Obj2:\r\n P2a: =A\r\n P1c: =C\r\n>."}

ACTION REQUIRED: Microsoft needs this private repository to complete compliance info

There are open compliance tasks that need to be reviewed for your PowerApps-Language-Tooling repo.

Action required: 4 compliance tasks

To bring this repository to the standard required for 2021, we require administrators of this and all Microsoft GitHub repositories to complete a small set of tasks within the next 60 days. This is critical work to ensure the compliance and security of your microsoft GitHub organization.

Please take a few minutes to complete the tasks at: https://repos.opensource.microsoft.com/orgs/microsoft/repos/PowerApps-Language-Tooling/compliance

  • The GitHub AE (GitHub inside Microsoft) migration survey has not been completed for this private repository
  • No Service Tree mapping has been set for this repo. If this team does not use Service Tree, they can also opt-out of providing Service Tree data in the Compliance tab.
  • No repository maintainers are set. The Open Source Maintainers are the decision-makers and actionable owners of the repository, irrespective of administrator permission grants on GitHub.
  • Classification of the repository as production/non-production is missing in the Compliance tab.

You can close this work item once you have completed the compliance tasks, or it will automatically close within a day of taking action.

If you no longer need this repository, it might be quickest to delete the repo, too.

GitHub inside Microsoft program information

More information about GitHub inside Microsoft and the new GitHub AE product can be found at https://aka.ms/gim or by contacting [email protected]

FYI: current admins at Microsoft include @MattB-msft, @JimDaly, @davidjenni, @MikeStall, @lajusp

Noisy diff: Sarif file

The Sarif file is a noisy diff. It's 1-line json file, and changes each time we export.

Adding new control gives error: MsApp is corrputed. Duplicate Control Unique Ids

I added a new control into a screen.pa.yaml (copied from an existing control but with a new Unique ID - and then packed.

    # Existing control
    img_1 As image:
        Image: =powerapps
        ZIndex: =2
        Y: =162
        X: =varImg2X

    # New control
    img_2 As image:
        Image: =powerapps
        ZIndex: =2
        Y: =250
        X: =varImg3X

The following error was thrown, but the app loads ok:

Error   PA3007: MsApp is corrupted. Duplicate Control Unique Ids
Warning PA2001: Checksum mismatch. Sources have changed since when they were unpacked.
Warning PA2001: Checksum mismatch. File Controls\3.json checksum does not match on extract

Are there some additional steps I need to do when adding a new control via code - rather than via studio?
If I round-trip - I get a new entry in editorstate.json for the new control.

Warning PA2001: Checksum mismatch. File Controls\194.json checksum does not match on extract

What be the cause of the warning:

Warning PA2001: Checksum mismatch. File Controls\194.json checksum does not match on extract

I also get messages like the following:

FAIL: hash mismatch: Controls\145.json
FAIL: hash mismatch: Controls\194.json
FAIL: hash mismatch: Controls\22.json
FAIL: hash mismatch: Controls\3.json
FAIL: hash mismatch: Controls\88.json
FAIL: hash mismatch: Properties.json
FAIL: hash mismatch: References\Templates.json
FAIL!!

This happens on first extract where there were no existing files extracted.

Review file format

Review the file format to ensure it plays well with source control and Pull Request merging. Ensure each Directory falls into the following category, where all files in the directory have the same rules:

# Kind Details Examples
1 Source file should be checked in pa.yaml
2 cache file (in-theory) can be recreated, Still require checking in for now, but future version may have offline recovery. In theory, server could recover if missing packages, ApiDef/Swagger
3 optional file can be safely deleted. editorstate.json,
4 config org-specific data. Connections

Per-file checksum for diagnostics

For diagnostics, provide a checksum per-file.
Still keep the top-level msapp checksum for easy compare., But if that's different, then we can look at per-file checksums. This can help diagnose things like which Screen or Data source was changed.

Resolve .editorState

Determine what to do with .editorState files.

Maybe also split the .editorstate.json into a subfolder under /src/editorstate so it's less crowded.

  • if you delete the .pa.yaml, we'll just ignore the corresponding .editorstate
  • if you delete the .editorstate, we'll create a bunch of defaults that may not be the same as the original.

Noisy diffs from Multiple exports

In canvasmanifest.json:
Lots of volatile perf counters, etc that don't below. Move to entropy?
image

image

image

In resources.json:
(the msapp has an image, it looks like the RootPath for the image has a volatile guid)
image

Custom component Input and output properties should be better differentiated

In the bleow, CustomProperty1 is an Input property and CustomProperty2 is an Output property. Yet they show up the same way, which is very confusing.

Component1 As CanvasComponent:
  CustomProperty1: ="Text, Modified"
  CustomProperty2: ="Text, Modified"

It should be something closer to:

Component1 As CanvasComponent:
    CustomProperty1:
        InputDefault: ="Text, Modified"
    CustomProperty2: ="Text, Modified"

In the future, we may be supporting separated Input and Output properties:

Component1 As CanvasComponent:
    CustomProperty3:
        InputDefault: ="Text, Modified"
        Output: ="Text, Modified"

Not something blocking public preview, but we should look at this as we add the other metadata for property parameters.

Parse error: Missing ':' when using #comments in .pa.yaml source files

The following code gives the error Error PA3003: Parse error: Missing ':'. If this is a multiline property, use | at Screen1.pa.yaml:2,18-2,18

Screen1 As screen:
    # Some comment
    sldSlider As slider:
        # Another comment
        Max: =sldSlider.Width
       ...

but this code packs ok:

Screen1 As screen:
# Some comment
    sldSlider As slider:
        # Another comment
        Max: =sldSlider.Width

When I unpack after a pack with comments - the pa.yaml is missing all the detal after the comment and is just:

Screen1 As screen:

Are yaml comments supported in pa.yaml files?

build issue: don't require GIT on path

Our build infrastructure, /targets/Program.cs takes a hard dependeny on Git being on the path:

static string RootDir = Read("git", "rev-parse --show-toplevel", noEcho: true).Trim();

If it's not on the path, we get a cryptic error.

Ideas to make .msapp files 'source code' (i.e. developer) friendly

Hello,

Having read the blog post at https://powerapps.microsoft.com/en-us/blog/source-code-files-for-canvas-apps/, I have some feedback for you to consider, in order of importance.

  1. Don't build extra tools to compensate for a file format that isn't source code/git friendly to begin with. The process of packing and unpacking the .msapp files is what I consider a legacy concept taken from Dynamics 365/CDS/Dataverse/PowerApps/(insert your preferred technology name here) solutions. You don't need to do this! Instead, make the server-side export process for an .msapp itself place the unpacked file's contents directly in the .msapp file (a zip file renamed to .msapp). Then, it's just a matter of unzipping the file before editing on the local machine and saving to source control. No extra specialized tooling is then required beyond using a zip/unzip program/command already built into every OS and scripting language. If you need the files to be packed into some other format, do that yourself on the server after the .msapp file containing the unpacked files is uploaded. Don't offload the responsibility for this cumbersome process to everyone else when you can handle it yourself. Remove the barriers to adopting source control by removing unnecessary steps.
  2. It seems like you're using YAML to create a domain specific language that is meant to be a less verbose data structure format than JSON or XML would be. But, you're admittedly saying in https://github.com/microsoft/PowerApps-Language-Tooling/blob/master/docs/YAMLFileFormat.md that YAML standards like escaping and comments aren't supported. All the rules and exceptions and special cases for how the file format works makes me think this isn't the right file format to use and you're twisting YAML into doing something else as a convenience to you rather than a convenience to the users who will be working with these source code files. Why don't you come up with your own DSL where everything can be expressed in the most logical syntax possible without any special rules or edge cases meant to satisfy your YAML file format rules. Work with Microsoft research or the F#/C# compiler teams to do this if the PowerApps team doesn't know how to do this themselves.
  3. Make sure there is a compiler and there's IDE support with intellisense/autocomplete, go to definition, etc. Then the files can be edited with guidance and compiled/validated on a user's (i.e. developer's) local machine without wondering if what's being typed in is valid. Raw text files that can be edited by humans without any local validation is going to result in errors no matter how much guidance is provided. This is also going to be needed to deal with merging files as mentioned at https://github.com/microsoft/PowerApps-Language-Tooling#merging-changes-from-studio.
  4. Last thing to add just so I can say I've said it, add support for a real programming language so we don't have to use expressions. I'm not as serious about this one, but this is truly what every developer who is forced to build canvas apps is thinking when they're told to build one. There are more of us than you may think. There are dozens of beautiful programming languages that people love and we could do things so much easier with them than with than expressions. Something as simple as trying to express conditional logic with expressions is way too difficult. You could use C#, JavaScript, TypeScript, Python, Ruby, and so many more, and convert them to WASM so they run on the browser. You could make the properties with expressions be function calls to a namespace and function by name with supplied parameters, and the rest of the logic exists in the source code files, and by doing so enable code reuse.

Thanks for your consideration.

Alan

noisy diffs: screen ordering

If I change screen order, editorstate.json Index changes. What this means is that if I insert a screen into a 30 screen app, 29 editorstate json files will all change.

We should have a single place that lists the screen order (either separate file or an array in CanvasManifest.json)

Supress empty properties

If a property is empty, then consider removing it from the pa.yaml

E.g Could HoverFill and HoverBorderColor be removed to lower verbosity?

        imgBox As image:
            Image: =box.img
            ImagePosition: =ImagePosition.Stretch
            X: =0
            Y: =0
            Width: =1024
            Height: =32
            HoverFill: =
            HoverBorderColor: =
            ZIndex: =1

Format: Extract "api definitions" from data source to their own file

In data source, extract the “API Definitions” (ie, TableDefinition,Swagger,Wadl,etc) to a separate file. The API def for CDS Contacts is 1.6 MB.
Also need to consider whether these files can be optional (can they just be deleted?) - What happens when an API definition changes?

better source span on yaml.

better source span on yaml.

Do a duplicate control definition in pa.yaml and verify we get meaningful source locations..

Handle missing parameters gracefully

Using pasopa -unpack outputs the error:

Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at PASopa.Program.Main(String[] args) in C:\repos\PASopa\PowerApps-Language-Tooling\src\PASopa\Program.cs:line 51

Expected output:

A required argument -unpack is missing.

Usage: 
-unpack PathToApp.msapp PathToNewSourceFolder
-unpack PathToApp.msapp  // infers source folder

Since this will eventually make its way into SolutionPackager - maybe this isn't a priority?!

Template.json isn't roundtripping

Template.json doesn't round-trip the Components information.

Template.json gets fully sharded to xml files in the \pkg dir, so it doesn't even appear in the source file.
That's losing the Components information.

We're also wrongfully excluding it from checksum because of the escaped xml. The checksum should cover everything.

Server side changes to improve .msapp format.

Improve the real .msapp format to make conversions easier.

As general principles:

  • avoid double json encoding because that breaks checksums.
  • separate out volatile information (timestamps, per-environment) from stable information.
  • remove fields that are redundant or don't need to be emitted.

Some specific things:

  • Double encoding in PCF controls
  • Double encoding in Properties.json
  • Test cases. (see updates in #52)

NewPathToApp Folder Auto-create

When using -pack NewPathToApp.msapp PathToSourceFolder

It will be useful to create the NewPathToApp folder if it doesn't exist, instead of erroring out.

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.