Giter VIP home page Giter VIP logo

terraform-mode's People

Contributors

dod38fr avatar fbergroth avatar fuco1 avatar itiut avatar jplindstrom avatar jvshahid avatar kmosher avatar mattiaslundberg avatar pd avatar phst avatar rnikoopour avatar svend avatar syohex 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

terraform-mode's Issues

Migrate to Github Actions

After the discussion in #34 we want to migrate to Github Actions. This issue supersedes #34.

Github Actions should test incoming code in a similar manner that was done with Travis.

String interpolation breaks syntax highlightin.

Satements such as

resource "template_file" "ecs_deploy_policy" {
  template = "${path.module}/policies/ecs-deploy-policy.json"
}

and more convoluted

resource "aws_iam_role_policy" "ecs_service_role_policy" {
  policy   = "${file("${path.module}/policies/ecs-service-role-policy.json")}"
}

breaks the syntax highlighting. Both are valid HSL statements. I find the not escaping double quotes in double quotes quite strange, but to my understanding that's how it is intended.

Compile error installing from package.el

I tried installing terraform-mode-20201110.1915 via package.el and get the following error:
terraform-mode.el:71:1:Error: rx form ‘regexp’ requires args satisfying ‘stringp’

Syntax highlighting turns on within a comment

resource "aws_subnet" "subnet-1" {
  vpc_id = aws_vpc.first-vpc.id
  cidr_block = "10.0.1.0/24"

  tags = {
    Name = "prod-subnet"
  }
}

/*
resource "aws_subnet" "subnet-1" {
  vpc_id = aws_vpc.first-vpc.id
  cidr_block = "10.0.1.0/24"

  tags = {
    Name = "prod-subnet"
  }
}
*/

The words hello and world within the comment end up highlighted.

Expected result:
Things within comments are not highlighted, just like shown in the highlighting code above (on Github).

Version:
0.06

V2 Refactor

Hi All,

I wanted to do a significant refactor on the code base. As I want to implement some new highlighting, I'm struggling to determine where to put it. This code base relies on hcl-mode and it blurs the lines between what terraform-mode is responsible for and what hcl-mode is responsible for.

The refactor would achieve the following:

  • Not introduce breaking changes to terraform-mode
  • Preserve all existing features
  • Remove dependency on hcl-mode
  • Improve Syntax highlighting

I'd like to gather thoughts from folks watching this library before going down a refactor and submitting a PR.

Cheers

terraform-indent-level is not respected

If I (setq terraform-indent-level 4), it is not respected, because indent-line-function is still bound to hcl-indent-line

indent-line-function is a variable defined in ‘indent.el’.
Its value is ‘hcl-indent-line’
Local in buffer example.tf; global value is indent-relative

For now, I'm just setting hcl-indent-level to the desired value to work around the issue.

New Maintainer

Hello I'd like to be the new maintainer for this project.

What are the steps involved?

Wrong rendering of brackets before equal sign

image

 peered_networks = [
    { network = data.azurerm_virtual_network.vnet-db-dev },
    { network = data.azurerm_virtual_network.vnet-db-prod },
    { network = data.azurerm_virtual_network.vnet-app-dev },
  ]

Tag version 1?

@rnikoopour I've processed all the pull requests and issues not opened by you (which are more of a discussion points anyhow).

I think we can just arbitrarily decide now to tag version 1.0.0 so things like melpa stable pick it up. The package has enough features to be useful so I don't see a reason not to have a "version" release.

WDYT?

Refactor tests

The syntax highlighting tests go outside the scope of what is actually provided by terraform-mode.

The test should only cover syntax highlighting directly provided by terraform-mode

Unit tests failing

$ make 
cask exec emacs -Q -batch -L . -l test/test-helper.el \
	-l test/test-highlighting.el -l test/test-indentation.el \
	-l test/test-command.el \
	-f ert-run-tests-batch-and-exit
Running 24 tests (2023-02-17 14:53:07+0100, selector ‘t’)
   passed   1/24  array-indentation (0.002235 sec)
   passed   2/24  assignment-statement (0.000549 sec)
Test atlas-block backtrace:
  ert-fail(((should (face-at-cursor-p 'font-lock-builtin-face)) :form 
  (if (unwind-protect (setq value-62 (apply fn-60 args-61)) (setq form
  (let (form-description-64) (if (unwind-protect (setq value-62 (apply
  (let ((value-62 'ert-form-evaluation-aborted-63)) (let (form-descrip
  (let* ((fn-60 #'face-at-cursor-p) (args-61 (condition-case err (let 
  (progn (insert "\natlas {\n    name = \"foo\"\n}\n") (goto-char (poi
  (unwind-protect (progn (insert "\natlas {\n    name = \"foo\"\n}\n")
  (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
  (let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current
  (let ((lexical-binding nil)) (let ((temp-buffer (generate-new-buffer
  (lambda nil (let ((lexical-binding nil)) (let ((temp-buffer (generat
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name atlas-block :documentation "Syntax hi
  ert-run-or-rerun-test(#s(ert--stats :selector t :tests [... ... ... 
  ert-run-tests(t #f(compiled-function (event-type &rest event-args) #
  ert-run-tests-batch(nil)
  ert-run-tests-batch-and-exit()
  command-line-1(("-L" "." "-l" "test/test-helper.el" "-l" "test/test-
  command-line()
  normal-top-level()
Test atlas-block condition:
    (ert-test-failed
     ((should
       (face-at-cursor-p 'font-lock-builtin-face))
      :form
      (face-at-cursor-p font-lock-builtin-face)
      :value nil))
   FAILED   3/24  atlas-block (0.000147 sec)
   passed   4/24  beginning-of-defun (0.000358 sec)
   passed   5/24  boolean-keywords (0.000487 sec)
   passed   6/24  change-indent-size (0.000165 sec)
Test data-block backtrace:
  ert-fail(((should (face-at-cursor-p 'font-lock-builtin-face)) :form 
  (if (unwind-protect (setq value-27 (apply fn-25 args-26)) (setq form
  (let (form-description-29) (if (unwind-protect (setq value-27 (apply
  (let ((value-27 'ert-form-evaluation-aborted-28)) (let (form-descrip
  (let* ((fn-25 #'face-at-cursor-p) (args-26 (condition-case err (let 
  (progn (insert "\ndata \"template_file\" \"userdata\" {\n    source 
  (unwind-protect (progn (insert "\ndata \"template_file\" \"userdata\
  (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
  (let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current
  (let ((lexical-binding nil)) (let ((temp-buffer (generate-new-buffer
  (lambda nil (let ((lexical-binding nil)) (let ((temp-buffer (generat
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name data-block :documentation "Syntax hig
  ert-run-or-rerun-test(#s(ert--stats :selector t :tests ... :test-map
  ert-run-tests(t #f(compiled-function (event-type &rest event-args) #
  ert-run-tests-batch(nil)
  ert-run-tests-batch-and-exit()
  command-line-1(("-L" "." "-l" "test/test-helper.el" "-l" "test/test-
  command-line()
  normal-top-level()
Test data-block condition:
    (ert-test-failed
     ((should
       (face-at-cursor-p 'font-lock-builtin-face))
      :form
      (face-at-cursor-p font-lock-builtin-face)
      :value nil))
   FAILED   7/24  data-block (0.000261 sec)
   passed   8/24  end-of-defun (0.000586 sec)
   passed   9/24  indentation-into-block (0.000493 sec)
   passed  10/24  indentation-into-nested-block (0.000253 sec)
Test inner-block backtrace:
  ert-fail(((should (face-at-cursor-p 'font-lock-builtin-face)) :form 
  (if (unwind-protect (setq value-137 (apply fn-135 args-136)) (setq f
  (let (form-description-139) (if (unwind-protect (setq value-137 (app
  (let ((value-137 'ert-form-evaluation-aborted-138)) (let (form-descr
  (let* ((fn-135 #'face-at-cursor-p) (args-136 (condition-case err (le
  (progn (insert "\nprovisioner \"file\" {\n    source = \"conf/myapp.
  (unwind-protect (progn (insert "\nprovisioner \"file\" {\n    source
  (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
  (let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current
  (let ((lexical-binding nil)) (let ((temp-buffer (generate-new-buffer
  (lambda nil (let ((lexical-binding nil)) (let ((temp-buffer (generat
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name inner-block :documentation "Syntax hi
  ert-run-or-rerun-test(#s(ert--stats :selector t :tests ... :test-map
  ert-run-tests(t #f(compiled-function (event-type &rest event-args) #
  ert-run-tests-batch(nil)
  ert-run-tests-batch-and-exit()
  command-line-1(("-L" "." "-l" "test/test-helper.el" "-l" "test/test-
  command-line()
  normal-top-level()
Test inner-block condition:
    (ert-test-failed
     ((should
       (face-at-cursor-p 'font-lock-builtin-face))
      :form
      (face-at-cursor-p font-lock-builtin-face)
      :value nil))
   FAILED  11/24  inner-block (0.000486 sec)
   passed  12/24  map-indentation (0.000384 sec)
   passed  13/24  map-statement (0.000322 sec)
Test module-block backtrace:
  ert-fail(((should (face-at-cursor-p 'font-lock-builtin-face)) :form 
  (if (unwind-protect (setq value-37 (apply fn-35 args-36)) (setq form
  (let (form-description-39) (if (unwind-protect (setq value-37 (apply
  (let ((value-37 'ert-form-evaluation-aborted-38)) (let (form-descrip
  (let* ((fn-35 #'face-at-cursor-p) (args-36 (condition-case err (let 
  (progn (insert "\nmodule \"consul\" {\n    source = \"foo\"\n}\n") (
  (unwind-protect (progn (insert "\nmodule \"consul\" {\n    source = 
  (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
  (let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current
  (let ((lexical-binding nil)) (let ((temp-buffer (generate-new-buffer
  (lambda nil (let ((lexical-binding nil)) (let ((temp-buffer (generat
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name module-block :documentation "Syntax h
  ert-run-or-rerun-test(#s(ert--stats :selector t :tests ... :test-map
  ert-run-tests(t #f(compiled-function (event-type &rest event-args) #
  ert-run-tests-batch(nil)
  ert-run-tests-batch-and-exit()
  command-line-1(("-L" "." "-l" "test/test-helper.el" "-l" "test/test-
  command-line()
  normal-top-level()
Test module-block condition:
    (ert-test-failed
     ((should
       (face-at-cursor-p 'font-lock-builtin-face))
      :form
      (face-at-cursor-p font-lock-builtin-face)
      :value nil))
   FAILED  14/24  module-block (0.000254 sec)
   passed  15/24  multiple-line-comment (0.000278 sec)
   passed  16/24  no-indentation (0.000117 sec)
   passed  17/24  no-indentation-into-comment (0.000094 sec)
   passed  18/24  no-indentation-with-empty-line (0.000104 sec)
Test output-block backtrace:
  ert-fail(((should (face-at-cursor-p 'font-lock-builtin-face)) :form 
  (if (unwind-protect (setq value-47 (apply fn-45 args-46)) (setq form
  (let (form-description-49) (if (unwind-protect (setq value-47 (apply
  (let ((value-47 'ert-form-evaluation-aborted-48)) (let (form-descrip
  (let* ((fn-45 #'face-at-cursor-p) (args-46 (condition-case err (let 
  (progn (insert "\noutput \"address\" {\n    value = \"foobar\"\n}\n"
  (unwind-protect (progn (insert "\noutput \"address\" {\n    value = 
  (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
  (let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current
  (let ((lexical-binding nil)) (let ((temp-buffer (generate-new-buffer
  (lambda nil (let ((lexical-binding nil)) (let ((temp-buffer (generat
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name output-block :documentation "Syntax h
  ert-run-or-rerun-test(#s(ert--stats :selector t :tests ... :test-map
  ert-run-tests(t #f(compiled-function (event-type &rest event-args) #
  ert-run-tests-batch(nil)
  ert-run-tests-batch-and-exit()
  command-line-1(("-L" "." "-l" "test/test-helper.el" "-l" "test/test-
  command-line()
  normal-top-level()
Test output-block condition:
    (ert-test-failed
     ((should
       (face-at-cursor-p 'font-lock-builtin-face))
      :form
      (face-at-cursor-p font-lock-builtin-face)
      :value nil))
   FAILED  19/24  output-block (0.000127 sec)
Test provider-block backtrace:
  ert-fail(((should (face-at-cursor-p 'font-lock-builtin-face)) :form 
  (if (unwind-protect (setq value-7 (apply fn-5 args-6)) (setq form-de
  (let (form-description-9) (if (unwind-protect (setq value-7 (apply f
  (let ((value-7 'ert-form-evaluation-aborted-8)) (let (form-descripti
  (let* ((fn-5 #'face-at-cursor-p) (args-6 (condition-case err (let ((
  (progn (insert "\nprovider \"aws\" {\n    access_key = \"foo\"\n}\n"
  (unwind-protect (progn (insert "\nprovider \"aws\" {\n    access_key
  (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
  (let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current
  (let ((lexical-binding nil)) (let ((temp-buffer (generate-new-buffer
  (lambda nil (let ((lexical-binding nil)) (let ((temp-buffer (generat
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name provider-block :documentation "Syntax
  ert-run-or-rerun-test(#s(ert--stats :selector t :tests ... :test-map
  ert-run-tests(t #f(compiled-function (event-type &rest event-args) #
  ert-run-tests-batch(nil)
  ert-run-tests-batch-and-exit()
  command-line-1(("-L" "." "-l" "test/test-helper.el" "-l" "test/test-
  command-line()
  normal-top-level()
Test provider-block condition:
    (ert-test-failed
     ((should
       (face-at-cursor-p 'font-lock-builtin-face))
      :form
      (face-at-cursor-p font-lock-builtin-face)
      :value nil))
   FAILED  20/24  provider-block (0.000429 sec)
Test provisioner-block backtrace:
  ert-fail(((should (face-at-cursor-p 'font-lock-builtin-face)) :form 
  (if (unwind-protect (setq value-57 (apply fn-55 args-56)) (setq form
  (let (form-description-59) (if (unwind-protect (setq value-57 (apply
  (let ((value-57 'ert-form-evaluation-aborted-58)) (let (form-descrip
  (let* ((fn-55 #'face-at-cursor-p) (args-56 (condition-case err (let 
  (progn (insert "\nresource \"aws_instance\" \"web\" {\n    provision
  (unwind-protect (progn (insert "\nresource \"aws_instance\" \"web\" 
  (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
  (let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current
  (let ((lexical-binding nil)) (let ((temp-buffer (generate-new-buffer
  (lambda nil (let ((lexical-binding nil)) (let ((temp-buffer (generat
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name provisioner-block :documentation "Syn
  ert-run-or-rerun-test(#s(ert--stats :selector t :tests ... :test-map
  ert-run-tests(t #f(compiled-function (event-type &rest event-args) #
  ert-run-tests-batch(nil)
  ert-run-tests-batch-and-exit()
  command-line-1(("-L" "." "-l" "test/test-helper.el" "-l" "test/test-
  command-line()
  normal-top-level()
Test provisioner-block condition:
    (ert-test-failed
     ((should
       (face-at-cursor-p 'font-lock-builtin-face))
      :form
      (face-at-cursor-p font-lock-builtin-face)
      :value nil))
   FAILED  21/24  provisioner-block (0.000538 sec)
Test resource-block backtrace:
  ert-fail(((should (face-at-cursor-p 'font-lock-builtin-face)) :form 
  (if (unwind-protect (setq value-17 (apply fn-15 args-16)) (setq form
  (let (form-description-19) (if (unwind-protect (setq value-17 (apply
  (let ((value-17 'ert-form-evaluation-aborted-18)) (let (form-descrip
  (let* ((fn-15 #'face-at-cursor-p) (args-16 (condition-case err (let 
  (progn (insert "\nresource \"aws_security_group\"\"default\" {\n    
  (unwind-protect (progn (insert "\nresource \"aws_security_group\"\"d
  (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
  (let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current
  (let ((lexical-binding nil)) (let ((temp-buffer (generate-new-buffer
  (lambda nil (let ((lexical-binding nil)) (let ((temp-buffer (generat
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name resource-block :documentation "Syntax
  ert-run-or-rerun-test(#s(ert--stats :selector t :tests ... :test-map
  ert-run-tests(t #f(compiled-function (event-type &rest event-args) #
  ert-run-tests-batch(nil)
  ert-run-tests-batch-and-exit()
  command-line-1(("-L" "." "-l" "test/test-helper.el" "-l" "test/test-
  command-line()
  normal-top-level()
Test resource-block condition:
    (ert-test-failed
     ((should
       (face-at-cursor-p 'font-lock-builtin-face))
      :form
      (face-at-cursor-p font-lock-builtin-face)
      :value nil))
   FAILED  22/24  resource-block (0.000325 sec)
   passed  23/24  single-line-comment (0.000301 sec)
   passed  24/24  string-interpolation (0.000117 sec)

Ran 24 tests, 16 results as expected, 8 unexpected (2023-02-17 14:53:08+0100, 1.199346 sec)

8 unexpected results:
   FAILED  atlas-block
   FAILED  data-block
   FAILED  inner-block
   FAILED  module-block
   FAILED  output-block
   FAILED  provider-block
   FAILED  provisioner-block
   FAILED  resource-block

make: *** [Makefile:18: test] Error 1

Provide folding of blocks

It would be great to hide/show blocks of a terraform file with something like folding mode or outline mode. I put together some code to make it work with outline-minor-mode. Feel free to adapt it, etc.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Allow simple visibility toggling in outline mode with TAB
;;

(defun my-outline-toggle-or-indent (&optional ARG)
  (interactive)
  (if (outline-on-heading-p)
	  (outline-toggle-children)
	(indent-for-tab-command ARG)
	)
  )

(define-key outline-minor-mode-map "\C-i" 'my-outline-toggle-or-indent)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; set outline headings for terraform mode
;;

(defun my-terraform-mode-hook ()
  (make-local-variable 'outline-regexp)
  (setq outline-regexp
		(concat
		 (mapconcat (lambda (item)
					  (and (car item) (format "\\(%s\\)" (regexp-quote (car item))))
					  )
					imenu-generic-expression
					"\\|")
		 "[[:blank:]].*{[[:blank:]]*$")
		)
  (setq outline-heading-alist
		(mapcar (lambda (item)
				  (cons (car item) 2)
				  )
				imenu-generic-expression)
		)
  (outline-minor-mode 1)
  )

	   
(add-hook 'terraform-mode-hook 'my-terraform-mode-hook)

Support for inline functions

Inline functions such as jsonencode do not have syntax highlighting.

Ideally all functions in Terraform should be highlighted.

Feature request: show workspace name in modeline

I'm using terraform-mode, which works great, thanks for sharing!
I use projectile-compile-project to run terraform plan while coding.
What I'm missing is to know which is my current workspace, which could be displayed in the modeline.
I'm not sure if the feature could possibly belong here or it should be in a separate, optional package. I've also searched for a magit-like terraform interface, which I haven't found and I might be eventually doing. Maybe there would be better. Or maybe it would be also acceptable here.
Also, never done anything with modeline before (novice elisp'er still), but I might take a stab at it if it would be accepted. I guess it should be no big deal.

EDIT: I've started working on a terraform transient interface package 😄
EDIT 2: I've published the initial version of terraform-cli 🚀

data block within resource wrongly detected as data source

Hi

Resource kubernetes_secret requires a data parameter. This parameter is wrongly detected as a data source.

For instance:

resource "kubernetes_secret" "wildcard-cert" {
  data = {
    "tls.key" = file(var.wildcard-tls-key-file)
    "tls.crt" = file(var.wildcard-tls-crt-file)
  }

  type = "kubernetes.io/tls"
}

This triggers the creation of =/{ entry in menu Terraform -> data.

This also shows up in speedbar (with other similar errors):
2022-11-16_11-02

"backend" syntax not supported

The following is legal Terraform, but is highlighted incorrectly in a buffer and seems to break the auto-reformatter:

terraform {
  backend "s3" {
    encrypt = true
    bucket  = "foobar"
    key     = "dummy.tfstate"
    region  = "us-east-2"
  }
}

Can we inherit terraform faces from font-lock faces?

Hi

At leaset those two faces have hardcoded colors.

  • terraform-resource-type-face
  • terraform-resource-name-face

Can we inherit from font-lock faces instead? It does not play well with so many colorschemes and I do not see the point of not having them just using font-lock type or variable faces?

Mode overwrites `C-h` which is special in emacs.

C-h is used throughout emacs to describe all key binding starting with current prefix. terraform-mode overwrites it in C-c C-h.

I think it's customary to use C-c C-d for mode specific documentation.

NonGNU ELPA?

Hi,

first of all thanks for this package!

Is there any chance of putting it on NonGNU ELPA as well? If so, may I suggest to get in touch with @phikal to see what needs to be done?

here-doc shell scripts break syntax highlighting

Using 0.4. I have a user_data section in an AWS resource, which uses the here-doc syntax. The shell script contains the character sequence /* as part of a shell command. This is interpreted as begin multiline quote and break highlighting for the remainder of the file.

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.