Skip to content
4 changes: 4 additions & 0 deletions src/components.json
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,10 @@
"title": "Docker",
"owner": "JustinBeckwith"
},
"dotenv": {
"title": "Dotenv (.env)",
"owner": "DmitrySharabin"
},
"dot": {
"title": "DOT (Graphviz)",
"owner": "RunDevelopment"
Expand Down
98 changes: 98 additions & 0 deletions src/languages/dotenv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/** @type {LanguageProto<'dotenv'>} */
export default {
id: 'dotenv',
optional: 'bash',
grammar () {
/**
* @param {RegExp} prefix
* @returns {Array<GrammarToken>}
*/
const commonPatterns = prefix => {
return [
{
pattern: RegExp(
prefix.source +
/(?:-?[1-9]\d*|0)(?:\\.\d+)?(?=\s*\}|\s[^}]+$|\s*$|"$)/.source
),
alias: 'number',
},
{
pattern: RegExp(prefix.source + /(?:false|true)(?=\s*\}|\s[^}]+$|\s*$)/.source),
alias: 'boolean',
},
{
// Ignore leading and trailing whitespace characters
pattern: RegExp(prefix.source + /\S[^}]*?\S(?=\s*\})/.source),
alias: 'string',
},
];
};

// Based on https://dotenvx.com/docs/env-file
return {
'comment':
/(?:^|(?<=[\s"'`]))#(?![^\n"'`]*["'`])[^\r\n \t]*(?:[ \t]+[^\r\n \t]+)*[ \t]*/,
'keyword': /^export(?=\s)/m,
'key': {
// Allow bare keys (without values)
pattern: /(?<=^[ \t]*)[a-z_]\w*(?=[ \t]*(?:=|$))/im,
alias: 'constant',
},
'value': [
{
pattern: /(?<==\s*)(?:-?[1-9]\d*|0)(?:\.\d+)?(?=\s*$)/,
alias: 'number',
},
{
pattern: /(?<==\s*)(?:false|true)(?=\s*$)/,
alias: 'boolean',
},
{
pattern:
/(?<==\s*)(?:(['"`])(?:\\[\s\S]|(?!\1)[^\\])*?\1|\S(?:.*?\S)?)(?=\s*$|\s+#.*$)/m,
alias: 'string',
inside: {
'command-substitution': {
// Command substitution is disabled in strings enclosed in "'" (single quotes) and "`" (backticks)
pattern: /(?<!['`][\s\S]*)\$\(.+\)/,
inside: {
'command-substitution-punctuation': {
pattern: /\$\(|\)/,
alias: 'punctuation',
},
'shell-command': {
pattern: /.+/,
inside: 'bash',
},
},
},
'variable-expansion': {
// Variable expansion is disabled in strings enclosed in "'" (single quotes) and "`" (backticks)
pattern: /(?<!['`][\s\S]*)\$(?:\{[^{]+\}|[^\s"]+)/,
inside: {
'variable': /(?<=\$\{|\$)[a-z_]\w*/i,
'default-value': commonPatterns(/(?<=(?::-|-)\s*)/),
'alternative-value': commonPatterns(/(?<=(?::\+|\+)\s*)/),
'variable-expansion-punctuation': {
pattern: /\$\{|:-|:\+|[$}+-]/,
alias: 'punctuation',
},
},
},
'escape-sequence': {
pattern: /\\['"`#\\nrt]/,
alias: 'char',
},
'punctuation': /^['"`]|['"`]$/,
},
},
],
'assignment-operator': {
pattern: /=/,
alias: 'operator',
},
};
},
};

/** @import { GrammarToken, LanguageProto } from '../types.d.ts'; */
44 changes: 44 additions & 0 deletions tests/languages/dotenv+bash/bash_inclusion.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
SHORT_HASH=$(git rev-parse --short HEAD)
PWD_MESSAGE="Running from $(pwd)"
DATABASE_URL=postgres://$(whoami)@localhost/my_database

----------------------------------------------------

[
["assign-left", ["SHORT_HASH"]],
["operator", ["="]],
["variable", [
["variable", "$("],
["function", "git"],
" rev-parse ",
["parameter", "--short"],
" HEAD",
["variable", ")"]
]],

["assign-left", ["PWD_MESSAGE"]],
["operator", ["="]],
["string", [
"\"Running from ",
["variable", [
["variable", "$("],
["builtin", "pwd"],
["variable", ")"]
]],
"\""
]],

["assign-left", ["DATABASE_URL"]],
["operator", ["="]],
"postgres://",
["variable", [
["variable", "$("],
["function", "whoami"],
["variable", ")"]
]],
"@localhost/my_database"
]

----------------------------------------------------

Check for bash inclusion.
115 changes: 115 additions & 0 deletions tests/languages/dotenv/command_substitution_feature.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
DATE=$(date)
SHORT_HASH=$(git rev-parse --short HEAD)
LONG_HASH=`git rev-parse HEAD`
BUILD_ID="build-$(uuidgen)"
PWD_MESSAGE="Running from $(pwd)"

DATABASE_URL="postgres://$(whoami)@localhost/my_database"
WITH_SUBSTITUTION=postgres://$(whoami)@localhost/my_database
NO_SUBSTITUTION='postgres://$(whoami)@localhost/my_database'
AND_HERE=`Some text...
postgres://$(whoami)@localhost/my_database`

----------------------------------------------------

[
["key", "DATE"],
["assignment-operator", "="],
["value", [
["command-substitution", [
["command-substitution-punctuation", "$("],
["shell-command", "date"],
["command-substitution-punctuation", ")"]
]]
]],

["key", "SHORT_HASH"],
["assignment-operator", "="],
["value", [
["command-substitution", [
["command-substitution-punctuation", "$("],
["shell-command", "git rev-parse --short HEAD"],
["command-substitution-punctuation", ")"]
]]
]],

["key", "LONG_HASH"],
["assignment-operator", "="],
["value", [
["punctuation", "`"],
"git rev-parse HEAD",
["punctuation", "`"]
]],

["key", "BUILD_ID"],
["assignment-operator", "="],
["value", [
["punctuation", "\""],
"build-",
["command-substitution", [
["command-substitution-punctuation", "$("],
["shell-command", "uuidgen"],
["command-substitution-punctuation", ")"]
]],
["punctuation", "\""]
]],

["key", "PWD_MESSAGE"],
["assignment-operator", "="],
["value", [
["punctuation", "\""],
"Running from ",
["command-substitution", [
["command-substitution-punctuation", "$("],
["shell-command", "pwd"],
["command-substitution-punctuation", ")"]
]],
["punctuation", "\""]
]],

["key", "DATABASE_URL"],
["assignment-operator", "="],
["value", [
["punctuation", "\""],
"postgres://",
["command-substitution", [
["command-substitution-punctuation", "$("],
["shell-command", "whoami"],
["command-substitution-punctuation", ")"]
]],
"@localhost/my_database",
["punctuation", "\""]
]],

["key", "WITH_SUBSTITUTION"],
["assignment-operator", "="],
["value", [
"postgres://",
["command-substitution", [
["command-substitution-punctuation", "$("],
["shell-command", "whoami"],
["command-substitution-punctuation", ")"]
]],
"@localhost/my_database"
]],

["key", "NO_SUBSTITUTION"],
["assignment-operator", "="],
["value", [
["punctuation", "'"],
"postgres://$(whoami)@localhost/my_database",
["punctuation", "'"]
]],

["key", "AND_HERE"],
["assignment-operator", "="],
["value", [
["punctuation", "`"],
"Some text...\r\npostgres://$(whoami)@localhost/my_database",
["punctuation", "`"]
]]
]

----------------------------------------------------

Check for command substitution.
90 changes: 90 additions & 0 deletions tests/languages/dotenv/comment_feature.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# This is a comment

KEY=VAL # inline comment
KEY="VAL"# and another one
KEY='VAL'# and another one
KEY=`VAL`# and another one

KEY="String with a hash # this is not a comment"
KEY='String with a hash # this is not a comment'
KEY=`String with a hash # this is not a comment`
KEY=VAL# also not a comment
KEY=Escaped \# hash is not a comment as well

----------------------------------------------------

[
["comment", "# This is a comment"],

["key", "KEY"],
["assignment-operator", "="],
["value", ["VAL"]],
["comment", "# inline comment"],

["key", "KEY"],
["assignment-operator", "="],
["value", [
["punctuation", "\""],
"VAL",
["punctuation", "\""]
]],
["comment", "# and another one"],

["key", "KEY"],
["assignment-operator", "="],
["value", [
["punctuation", "'"],
"VAL",
["punctuation", "'"]
]],
["comment", "# and another one"],

["key", "KEY"],
["assignment-operator", "="],
["value", [
["punctuation", "`"],
"VAL",
["punctuation", "`"]
]],
["comment", "# and another one"],

["key", "KEY"],
["assignment-operator", "="],
["value", [
["punctuation", "\""],
"String with a hash # this is not a comment",
["punctuation", "\""]
]],

["key", "KEY"],
["assignment-operator", "="],
["value", [
["punctuation", "'"],
"String with a hash # this is not a comment",
["punctuation", "'"]
]],

["key", "KEY"],
["assignment-operator", "="],
["value", [
["punctuation", "`"],
"String with a hash # this is not a comment",
["punctuation", "`"]
]],

["key", "KEY"],
["assignment-operator", "="],
["value", ["VAL# also not a comment"]],

["key", "KEY"],
["assignment-operator", "="],
["value", [
"Escaped ",
["escape-sequence", "\\#"],
" hash is not a comment as well"
]]
]

----------------------------------------------------

Check for comments.
14 changes: 14 additions & 0 deletions tests/languages/dotenv/export_keyword_feature.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export EXPORTED_VAR=value

----------------------------------------------------

[
["keyword", "export"],
["key", "EXPORTED_VAR"],
["assignment-operator", "="],
["value", ["value"]]
]

----------------------------------------------------

Check for the export keyword.
Loading
Loading