Giter Club home page Giter Club logo

swiftkotlin's Introduction

status Swift 5 Swift Package Manager License Twitter

SwiftKotlin

A tool to convert Swift code to Kotlin in a very easy and quick way.

What is this?

SwiftKotlin is a framework, a command line tool and a Mac application for translating Swift code into Kotlin.

It applies transformations to the Swift code to get as correct as possible Kotlin code (see limitations below). It does string transformations as well as some more complicated ones like transforming guard statements to negative if statements, properties, memory management and many others.

It comes with a desktop Mac application to copy & paste your code, as well as a command line tool to transform a complete project to Kotlin.

Why use SwiftKotlin?

Why Kotlin?

Kotlin is a great language, it is to Android/Java what Swift is to iOS/Objective-C. It adds lots of great features while at the same time it keeps complete interop with Java, which means that you can combine them both together as you prefer.

If you are a Swift developer, you will love Kotlin. It provides the most important Swift features (optionals, extensions, generics, lambdas,...) and a very similar syntax. You can check a side by side comparison of Swift and Kotlin here.

If you are a Java developer, you will find in Kotlin a much more modern and safer language (optionals and mutation). It is a pleasure to write Kotlin code, much more readable and compact than the Java counterpart. You can check some of the benefits and differences in Kotlin official documentation and a nice list of reasons to chose Kotlin over Java.

Moreover, Kotlin is fully integrated in IntelliJ (Android Studio), so you can keep using the "de facto" IDE for Android with all the added benefits brought by Google, and it even has a Java to Kotlin converter if you want to update your legacy Java.

On top of that, if you consider the similarities between Swift and Kotlin, you can easily convert code in one language to the other one, and have Swift developers writing Kotlin (and vice versa) with ease. That is, in fact, the purpose of this project, to help you with that conversion.

Benefits over shared code across platforms

There are many alternatives for making multiplatform projects or sharing code between them. Some alternatives are Xamarin, ReactNative, Cordova or low level C++ libraries.

The main issue with all of them is that once you chose to use them, you need to keep in their boundaries, including specific tools and libraries, introducing a steep learning curve and a big risk in terms of dependency on that 3rd party. Besides that, for many of those options the resulting app will lack the quality of a fully native app.

On the other hand, by using Kotlin, you will still have 2 fully native applications, with all the benefits (best quality, performance, best tools per platform -Xcode/Android Studio-, follow platform conventions,...), but at the same time minimize the extra work required to translate between them due to the similarity with Swift.

In fact, I explored an actual example using MVVM+Rx, where I got between a 50% and 90% of code similarity depending on the layer (non UIKit dependent is much more reusable than UIKit dependent classes of course). It took me around 30% the time to convert the Android version from the iOS version and I did not have SwiftKotlin then. ;)

Limitations

Despite the similarities, Swift and Kotlin are different languages, with some intrinsic differences in them that cannot be fully translated. Besides that, they both run in different environments and have access to very different frameworks and system libraries.

Because of that, this tool does not have as a goal to produce production ready Kotlin code, but just a Kotlin translation that will require manual editing. For example, things as simple as adding a new item to an array have different method names:

// Swift
array.append("This is in Swift")
// Kotlin
array.add("This is in Kotlin")

The scope of this project is not mapping all existing methods and data types to their Kotlin counterpart, but to translate the language itself. This means that manual editing will be required afterwards, especially when dealing with system libraries. It is intentional and important that the developer checks the output.

Status

The project is in active development, with many rules and improvements still to be implemented. Some of them include:

  • Constructors
  • Simple Control flow statments (guard, if, for, while, switch)
  • Composed Control flow statments (multiple guard, if let)
  • Extensions
  • Keyword replacements (val, this, fun, ...)
  • Basic memory management (weak, captures,...)
  • Function returns and named parameters
  • Basic property transfromers (getters and setters)
  • Lazy properties
  • Properties with didSet/willSet
  • Static to Companion
  • Struct to data class
  • String interpolators
  • Foundation types (arrays, maps,...)
  • Basic exception handling syntax
  • Simple enums
  • Complex enum cases to Sealed classes
  • ... (check open issues)

With the implemented rules you can already get pretty decent Kotlin output for many of your classes. The rest will come in future releases.

Installation

The project comes with 2 executable targets:

  • SwiftKotlinCommandLine
  • SwiftKotlinApp

Checkout the project's releases page to get a preview compiled version of the app or compile it manually:

  • Install Xcode 11+ and check it is the default selected one by running xcode-select -p
  • clone the repo: git clone [email protected]:angelolloqui/SwiftKotlin.git; cd SwiftKotlin
  • Run swift package update and swift package generate-xcodeproj --enable-code-coverage
  • Open the project: open SwiftKotlin.xcworkspace

From Xcode, run the desired target and copy the generated executables (you can find it under the Products generated folder) in a directory with executable rights for later use. Typically, you could use:

  • swiftkotlin command line tool: /usr/local/bin/
  • SwiftKotlinApp desktop app: /Applications/

NOTE: If you upgrade any project dependencies, make sure you run: swift package generate-xcodeproj --enable-code-coverage after upgrade

Usage

Command line tool

If you placed swiftkotlin in any of your path directories, just run: swiftkotlin [<file>] [--output path]

Note that you can specify a directory as input. Output will by default use the input directory, creating a <name>.kt file for each existing <name>.swift file found.

License

MIT licensed.

Collaboration

Forks, patches and other feedback are always welcome.

For a list of missing features, check the disabled Unit Tests.

Credits

SwiftKotlin uses Swift-Transform and Swift-AST for generating the AST for transpilation.

SwiftKotlin is brought to you by Angel Garcia Olloqui. You can contact me on:

And special credits for the contributors:

swiftkotlin's People

Contributors

albinekcom avatar aliaziz avatar angelolloqui avatar jonnermut avatar levidahl avatar mikemee avatar petermichaux avatar shaurya-objc avatar thmatuza avatar toshi0383 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  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

swiftkotlin's Issues

get/set property in protocol

Swift:

    var isPromotionLoading: Bool { get set }

Translated:

    var isPromotionLoading: Boolean {
        get
        set
    }

Correct translated

var isPromotionLoading: Boolean

Switch cases with where clauses not translated properly

In Swift, switch cases can contain where clauses like the following:

switch exception {
case .generic(let error) where error != nil:
    trackError(name: "generic", message: error!)
default:
    trackError(name: "generic", message: R.string.localizable.generic_error())
}

Currently, SwiftKotlin generates:

when (exception) {
    .generic where error != null -> trackError(name = "generic", message = error!!)
    else -> trackError(name = "generic", message = R.string.localizable.generic_error())
}

But that is incorrect Kotlin. It should instead remove the variable from the when and use expressions for the cases. Like:

when {
    exception is Exception.generic && error != null -> trackError(name = "generic", message = error!!)
    else -> trackError(name = "generic", message = R.string.localizable.generic_error())
}

Static constants not properly mapped to Companion objects

This Swift:

public struct VoucherCampaign {
    public static let inviteFriendsId = VoucherCampaignId("INVITE_FRIENDS")
}

Translates to:

public data class VoucherCampaign(
public val inviteFriendsId = VoucherCampaignId("INVITE_FRIENDS")
) {}

But should have a companion object with the static constant:

public data class VoucherCampaign {
    object Companion {
        val inviteFriendsId = VoucherCampaignId("INVITE_FRIENDS")
    }
}

Translate complex enums to Sealed classes

When an enum in Swift contains tuples must be transltated to Sealed classes, which is the closest in Kotlin.

Example:

Swift:

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(named: String)
    case empty
}

Koltin:

sealed class Barcode {
   data class upc(val v1: Int, val v2: Int, val v3: Int, val v4: Int) : Barcode()
   data class qrCode(val named: String) : Barcode()
   object empty : Barcode()
}

Translation to Korean

Hey there!
I am a Swift developer who is studying Android development.
As a mobile application developer, I was impressed with your work.
I would like to introduce these good works to Koreans.
Is there any chance that I can help translate Readme.md to Korean?

Remove unecessary {} on method definitions

When body is empty, Kotlin allows to remove the {}

Example:

class A {
    init() {}
    func test() {}
}

Translates to:

class A {
    constructor() {}
    fun test() {}
}

But could be:

class A {
    constructor()
    fun test()
}

Switch cases with tuple decomposition values does not translate properly

This Swift code:

switch exception {
case .qrCode(let name):
    trackCode(name: name)
default:
    trackError(name: "generic")
}

Translates to right now to:

when (exception) {
    .qrCode -> trackCode(name = name)
    else -> trackError(name = "generic")
}

However, the name variable in Swift has been decomposed from the tuple, and hence the Kotlin version should prefix its usage with the variable in the when expression. In this case:

when (exception) {
    .qrCode -> trackCode(name = exception.name)
    else -> trackError(name = "generic")
}

Switch cases with multiple lines not properly indented by {}

This Swift switch:

switch exception {
            case .network(_, _, let serverMessage):
                if let message = serverMessage {
                    trackError(name: message.status, message: message.message)
                } else {
                    trackError(name: "network", message: R.string.localizable.network_error())
                }
            case .generic(let error):
                trackError(name: "generic", message: error)
            default:
                trackError(name: "generic", message: R.string.localizable.generic_error())
            }

Translates to:

when (exception) {
    .network -> val message = serverMessage
    if (message != null) {
        trackError(name = message.status, message = message.message)
    } else {
        trackError(name = "network", message = R.string.localizable.network_error())
    }
    .generic -> trackError(name = "generic", message = error)
    else -> trackError(name = "generic", message = R.string.localizable.generic_error())
}

But should add {} like:

when (exception) {
    .network -> {
        val message = serverMessage
        if (message != null) {
            trackError(name = message.status, message = message.message)
        } else {
            trackError(name = "network", message = R.string.localizable.network_error())
        }
    }
    .generic -> trackError(name = "generic", message = error)
    else -> trackError(name = "generic", message = R.string.localizable.generic_error())
}

SwiftKotlinApp changes text selection while writing

When using SwiftKotlinApp, if you type new text into the Swift text area input, the translator runs for every key pressed, formatting the written text, and hence making the text selection invalid. As a result, typing on the text area is unusable.

Possible solutions:

  1. Try to keep the focus on the proper place: This might be difficult considering that the format will be dynamically changed, so the position could not be identical after running.
  2. Do not run the translator until some time passes: Only when idle, run the translator. The problem will still happen but less frequently, probably making the solution "good enough" for usage
  3. Add a button to "format" the Swift code, and apply that as a manual action. Word highlighting will not be shown until the format happens.

Optimize single line body methods

Kotlin allows for = methods instead of { return.

Example:

func mapToUserItem(user: User) -> UserItem {
    return UserItem(name: user.fullName)
}

Translates to:

fun mapToUserItem(user: User) : UserItem {
    return UserItem(name = user.fullName)
}

But could be:

fun mapToUserItem(user: User)  =
    UserItem(name = user.fullName)

Generic parameter clause in methods not properly placed

This Swift:

public func whenAll<T>(promises: [Promise<T>]) -> Promise<[T]> {
	return Promise<T>()
}

translates to:

public fun whenAll<T>(promises: List<Promise<T>>) : Promise<List<T>> {
    return Promise<T>()
}

However, the place of <T> is wrong, and should be at the beginning like:

public fun <T> whenAll(promises: List<Promise<T>>) : Promise<List<T>> {
    return Promise<T>()
}

Use invoke when calling an optional lambda

In Swift, this is possible:

let optionalLambda: (() -> Void)? = nil
...
optionalLambda?()

But in Kotlin, it should be:

val optionalLambda: (() -> Unit)? = null 
...
optionalLambda?.invoke()

Allow Semicolons in Swift Code

I'm brand new to Kotlin. I'm actually hoping to learn quite a lot about Kotlin by looking at translations created by SwiftKotlin. I put the following very basic swift class definition into SwiftKotlin 0.1.0 and nothing happened. No output. No error messages. It seems like this swift code cannot be translated.

class Person {

    private let name: String;

    init(name: String) {
        self.name = name;
    }

    func getName() -> String {
        return self.name;
    }

}

What to do?

Add plugin with basic support for UIKit -> Android widget conversions

Optional plugin that could transform some types:

UIView -> View
UITextField -> EditText
UIButton -> Button
UILabel -> Label
UITableView -> RecyclerView
UIScrollView -> ScrollView
UIImageView -> ImageView
...

Then, as part of the same or other plugin, we could also make use of Butterknife (http://jakewharton.github.io/butterknife/) to map @IBOutlet to @BindView(R.id.<variable_name>) and @IBAction to @OnClick(), which is not always the event we want but most of the times.

Resulting code will be far from funcional, but of a good starting point when converting UIKIt views to Android views.

Format Variable Number Of Arguments

Varargs in Swift are:

func sumOf(_ numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
        sum += number
    }
    return sum
}
sumOf(42, 597, 12)

And in Kotlin:

fun sumOf(vararg numbers: Int): Int {
    var sum = 0
    for (number in numbers) {
        sum += number
    }
    return sum
}
sumOf(42, 597, 12)

Any plans for Kotlin <-> Swift?

Hi there,

Are there any plans for implementing similar conversion the other way, from Kotlin to Swift?

If not, are you aware of any libraries like SwiftFormat for Kotlin or have any advice on how one would approach this task?

Thanks for the great work!

Preserve original comments

Current version transforms Swift code to an AST and then back to Kotlin, but the initial comments get removed.

A possible solution would be to look for all comments (contained in the TopDeclaration) and look for the closest node in the Swift code and place it next to the first corresponding Kotlin token. This strategy could result in comments wrongly placed in some circumstances, but should work OK on most cases.

Download page?

Hi there, you mention binaries are available for download on the info page but don't see any downloads enabled in GitHub. Mind please adding the release do that we don't have to build from sources for it?

Thx!

Optimize guard unwrapping expressions

Kotlin allows ternary operators to return.

This code:

func showTenants() {
    guard let intent = coordinator.tenantsIntent() else {
        return
    }
    navigationManager.show(intent, animation: .push)
}

Translates to

fun showTenants() {
    val intent = coordinator.tenantsIntent()
    if (intent == null) {
        return
    }
    navigationManager.show(intent, animation = .push)
}

But could be

fun showTenants() {
    val intent = coordinator.tenantsIntent() ?: return
    navigationManager.show(intent, animation = .push)
}

Convert basic operators

Swift allows for custom operators. In Kotlin, operators are restricted to:
https://kotlinlang.org/docs/reference/operator-overloading.html

Transform the operators that have a Kotlin counterpart. Example:

public func + (left: Price, right: Price) -> Price {
    return Price(amount: left.amount + right.amount, currency: left.currency)
}
public func - (left: Price, right: Price) -> Price {
    return Price(amount: left.amount - right.amount, currency: left.currency)
}

Translates to:

operator fun Price.plus(price: Price) =
        Price(amount = this.amount + price.amount, currency = this.currency)

operator fun Price.minus(price: Price) =
        Price(amount = this.amount - price.amount, currency = this.currency)

Remove underscore assignments

In Swift, when not using a method/function result, it is common to write:

        _ = service.refresh(cart: cart)

However, in Kotlin the resulting code:

_ = service.refresh(cart = cart)

Is not valid because underscore is reserved for lambdas.

It should just be removed like:

service.refresh(cart = cart)

reduce function

Swift:

            .reduce(0, +)

Translated:

            .reduce(0, +)

Should be translated to:

                .fold(0.0) { total, next ->
                    total + next
                }

Consider using an AST based parser

Hi Angel!

Just stumbled upon this project, very cool implementation you've got. Figured I'd suggest considering an AST based parser since implementing type specific conversions like the array append/add limitation listed in your Readme should be easier than with your current tokenizer. SwiftLint leverages SourceKit for this reason.

Transform foundation methods

List of some methods that could be transformed.

On List:

  • list.first --> list.firstOrNull()
  • list.last --> list.lastOrNull()
  • list.count --> list.size
  • list.isEmpty --> list.isEmpty()
  • list.index(of: a) --> list.indexOf(a)
  • list.append(element) --> list.add(element)
  • list.remove(at: index) --> list.removeAt(index)
  • list.sorted(by: lambda) --> sortedWith(comparator = Comparator(lambda))
  • list.joined(separator: joiner) --> elements. joinToString(separator = joiner)

On String:

  • string.count --> string.length
  • string.uppercased() --> string.toUpperCase()
  • string.lowercased() --> string.toLowerCase()

typing double quotes into SwiftKotlin app becomes curly quotes

I tried typing the following into SwiftKotlin app. As I type it, the editor converts the first double quotation mark into curly quotes. Then the line cannot be translated because there is a parsing error.

let s: String = "abc"

If I copy and paste the above into SwiftKotlin app, the translation to Kotlin happens successfully.

Removed unnecessary annotations in Kotlin

In Swift, there are some annotations that have no meaning in Kotlin. Some examples:

@escaping
@autoclosure
@discardableResult

Remove this annotations when translating

conversion of lazy properties

This Swift

private lazy var name: String = {() -> String in
    return "abc"
}()

is translated to the following Kotlin

private lazy var name: String = {   -> 
    return "abc"
}()

I think it should result in the following Kotlin.

private val name: String by lazy {
    "abc"
}

The var, val issue is tricky. The return issue is tricky.

Transform ternary expression

Transform ternary expression like:

let label = x > 0 ? "Positive" : "negative"

to Kotlin:

val label = if (x > 0) "Positive" else "negative"

Remove @escaping annotations

This Swift:

func validate(callback: @escaping ((Voucher) -> Void))

Should be:

fun validate(callback: ((Voucher) -> Unit))

Missing Files

Unable to build. The following file are missing: Formatter.swift and Tokenizer.swift

Implement didSet and willSet observable properties

In Swift, as part of the language, a property can have a didSet and/or willSet. Example:

class A {
    var isLocating = false {
        didSet {
            delegate.set(isLocating: isLocating) 
        }
    }
}

In Kotlin there is no default way of expressing property observers but can be done with delegated properties or by writing a custom setter (https://stackoverflow.com/a/39842353/378433)

For simplicity, implement a custom setter like:

class A {
    var isLocating = false
        set(value) {
            field = value
            delegate.set(isLocating = value)
        }
}

In case of willSet, just write the code before the field = value assignment

let function inside lambda is translated to val

        if let intent = coordinator.methodName(param1: param1, param2: param2, onComplete: {
            self.view.let { self.navigationManager.dismiss(view: $0, animated: true) }
        }) {
            navigationManager.show(intent, animation: .present)
        }

Translated:

        val intent = coordinator.methodName(param1: param1, param2: param2, onComplete = {
            this.view.val { this.navigationManager.dismiss(view = it, animated = true) }
        })
        if (intent != null) {
            navigationManager.show(intent, animation = .present)
        }

Correct Translate:

        val intent = coordinator.methodName(param1: param1, param2: param2, onComplete = {
            this.view?.let { this.navigationManager.dismiss(view = it, animated = true) }
        })
        if (intent != null) {
            navigationManager.show(intent, animation = .present)
        }

miss files

:0: error: no such file or directory: '/Users/james/Desktop/download/SwiftKotlin-develop/Source/SwiftKotlinFramework/External/SwiftFormat/SwiftFormat/Tokenizer.swift'
:0: error: no such file or directory: '/Users/james/Desktop/download/SwiftKotlin-develop/Source/SwiftKotlinFramework/External/SwiftFormat/SwiftFormat/Formatter.swift'

Remove -> from lambdas when no parameter

This code:

func changePhoto(picture: Data) {
    userService.updateUser(picture: picture).always { [weak self] in
        self?.hasPhoto = true
    }
}

Translates to

fun changePhoto(picture: Data) {
    userService.updateUser(picture = picture).always {   -> 
        this?.hasPhoto = true
    }
}

But could be improved removing the ->

Kotlin -> Swift

If you can code in swift and go to kotlin, you can code in kotlin and go to swift ?

When capturing self as weak, remove ?

In Swift, it is common in lambdas to capture self in weak mode and use self? inside the lambda body.

In Kotlin, due to GC, this is unnecesary and the ? must be removed.

Example:

func changePhoto(picture: Data) {
    userService.updateUser(picture: picture).always { [weak self] in
        self?.hasPhoto = true
    }
}

Translates to:

fun changePhoto(picture: Data) {
    userService.updateUser(picture = picture).always {  
        this?.hasPhoto = true
    }
}

But must be

fun changePhoto(picture: Data) {
    userService.updateUser(picture = picture).always {  
        this.hasPhoto = true
    }
}

Optional chainning in Kotlin requires optional checks in all expressions

In Swift, the optional check can be done on the optional properties only when chaining.

Example:

Given this Swift:

struct User {
    let name: String
}
func optionalUser() -> User? {
    return nil
}

This sentence in Swift is correct:

optionalUser()?.name.count

But in Kotlin, it should be:

optionalUser()?.name?.count

(Note the carried ? on the chaining)

Add support for fatalError()

A fatal error in Swift

fatalError("An error \(error) occurred")

could be converted to

throw Exception("An error $error occurred")

Guard with more than one let

Swift:

guard array.count > row,
            let a = CustomView.viewFor(item: array1[column].array[row]), 
            let b = something(a) else {
                return UIView()
            }
           ...

Tool Return:

val a = CustomView.viewFor(item = array1[column].array[row])
val b = somethin(a)
if (array.size <= row || playerView == null || b == null) {
    return UIView()
}
...

Correct return:

if (array.size <= row) return UIView()
val a = CustomView.viewFor(item = array1[column].array[row]) ?: return UIView()
val b = somethin(a) ?: return UIView()
...

Initialize nullable properties to null

In swift, nullable properties have a default value of nil. However, in Kotlin they need explicit initialization.

Example:

This Swift:

class PaymentSelectorPresenter {
    private var selectedPaymentMethod: PaymentMethod?
}

Translates to:

class PaymentSelectorPresenter {
    private var selectedPaymentMethod: PaymentMethod?
}

But should be:

class PaymentSelectorPresenter {
    private var selectedPaymentMethod: PaymentMethod? = null
}

Error when running from xcode

Hi there, this code looks interestin. However, i get the following error when i run from xcode
"Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc failed with exit code 1"
Grateful for any kind of help.

Translate simple enums to Kotlin

Simple Swift enums (without associated values) look like:

enum CompassPoint {
    case north
    case south
    case east
    case west
}

In Kotlin translates to:

enum class CompassPoint {
    north, south, east, west
}

Enums with inheritance not working

This swift enum:

public enum AnemoneException: Error {
    case notFound
    case network(HttpResponse, Error?)
}

Can be translated to a sealed class. However, the current version does not work because of the inheritance clause. Removing the inheritance translates to:

public sealed class AnemoneException {
    object notFound : AnemoneException()
    data class network(val v1: HttpResponse, val v2: Error?) : AnemoneException()
}

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.