Skip to content

Update to Godot 4 and highlight.js 11 #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions dist/gdscript.es.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 19 additions & 1 deletion dist/gdscript.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 3 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
{
"name": "highlightjs-gdscript",
"version": "0.0.1",
"version": "1.0.0",
"description": "highlight.js syntax definition for Godot's GDScript language",
"main": "src/languages/gdscript.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/form-follows-function/highlightjs-gdscript.git"
},
"keywords": [
"Godot",
"GDScript",
Expand All @@ -20,7 +16,7 @@
"author": "form-follows-function",
"license": "MIT",
"bugs": {
"url": "https://github.com/form-follows-function/highlightjs-gdscript/issues"
"url": "https://github.com/highlightjs/highlightjs-gdscript/issues"
},
"homepage": "https://github.com/form-follows-function/highlightjs-gdscript#readme"
"homepage": "https://github.com/highlightjs/highlightjs-gdscript#readme"
}
154 changes: 107 additions & 47 deletions src/languages/gdscript.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,128 @@
/*
Language: GDScript
Author: Khairul Hidayat <me@khairul.my.id>, Nelson Sylvest*r Fritsch <info@nelsonfritsch.de>, Hugo Locurcio <hugo.locurcio@hugo.pro>
Description: Programming language for Godot Engine
Author: Hugo Locurcio <hugo.locurcio@hugo.pro>, Khairul Hidayat <me@khairul.my.id>, Nelson Sylvest*r Fritsch <info@nelsonfritsch.de>
Description: Programming language for Godot Engine (supports Godot 4.x and 3.x)
*/

function GDScript(hljs) {
var KEYWORDS = {
keyword:
"and in not or self void as assert breakpoint class class_name " +
"extends is func setget signal tool yield const enum export " +
"onready static var break continue if elif else for pass return " +
"match while remote sync master puppet remotesync mastersync " +
"puppetsync",
module.exports = function(hljs) {
return {
aliases: ['gdscript', 'godot'],
keywords: {
keyword:
'class class_name const enum extends func namespace signal static ' +
'trait var await breakpoint yield set get and in not or void as ' +
'assert tool export onready break continue if elif else for pass ' +

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For assert, gdscript.cpp has:

                // Functions (highlighter uses global function color instead).
                "assert",
                "preload",

So maybe it should be moved to built_in like preload?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I see it is also listed under built_in already, so the one here should probably be removed.

'return match when while remote sync master puppet remotesync ' +
'mastersync puppetsync',
Comment on lines +11 to +16

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth documenting where to find those for future syncs.
Maybe use modules/gdscript/gdscript.cpp GDScriptLanguage::get_reserved_words() as reference?

BTW Godot 4.5 is adding abstract too.

There's also namespace and trait which are reserved for future use and thus highlighted by Godot, so we should include them too.


built_in:
"Color8 ColorN abs acos asin atan atan2 bytes2var " +
"cartesian2polar ceil char clamp convert cos cosh db2linear " +
"decimals dectime deg2rad dict2inst ease exp floor fmod fposmod " +
"funcref get_stack hash inst2dict instance_from_id inverse_lerp " +
"is_equal_approx is_inf is_instance_valid is_nan is_zero_approx " +
"len lerp lerp_angle linear2db load log max min move_toward " +
"nearest_po2 ord parse_json polar2cartesian posmod pow preload " +
"print_stack push_error push_warning rad2deg rand_range " +
"rand_seed randf randi randomize range_lerp round seed sign sin " +
"sinh smoothstep sqrt step_decimals stepify str str2var tan tanh " +
"to_json type_exists typeof validate_json var2bytes var2str " +
"weakref wrapf wrapi bool int float String NodePath " +
"Vector2 Rect2 Transform2D Vector3 Rect3 Plane " +
"Quat Basis Transform Color RID Object NodePath " +
"Dictionary Array PoolByteArray PoolIntArray " +
"PoolRealArray PoolStringArray PoolVector2Array " +
"PoolVector3Array PoolColorArray",
built_in:
'abs absf absi acos acosh angle_difference asin asinh atan atan2 ' +
'atanh bezier_derivative bezier_interpolate bytes_to_var ' +
'bytes_to_var_with_objects ceil ceilf ceili clamp clampf clampi ' +
Comment on lines +18 to +21

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to document how to retrieve/update that list in case it changes in the future.

I've got the list for Godot 4 with:

grep "method name=" doc/classes/@GlobalScope.xml | sed 's/.*name="\([^"]*\)".*/\1/'

and

grep "method name=" modules/gdscript/doc_classes/@GDScript.xml | sed 's/.*name="\([^"]*\)".*/\1/'

And confirmed that it matches the list you have here. But that also means we're missing 3.x built-ins.

Assuming we can include comments between lines in this long string, I'd suggest prefacing the blocks like this:

# Godot 4 @GlobalScope methods
# `grep "method name=" doc/classes/@GlobalScope.xml | sed 's/.*name="\([^"]*\)".*/\1/'`

# Godot 4 @GDScript built-ins
# `grep "method name=" modules/gdscript/doc_classes/@GDScript.xml | sed 's/.*name="\([^"]*\)".*/\1/'`

# Godot 3 @GDScript built-ins not in Godot 4
# `grep "method name=" modules/gdscript/doc_classes/@GDScript.xml | sed 's/.*name="\([^"]*\)".*/\1/'``

(there's no @GlobalScope methods in 3.x, they're all in @GDScript)

I found the following Godot 3 built-ins missing here:

ColorN
bytes2var
cartesian2polar
db2linear
dectime
deep_equal
deg2rad
dict2inst
funcref
inst2dict
linear2db
ord
parse_json
polar2cartesian
rad2deg
rand_range
rand_seed
range_lerp
stepify
str2var
to_json
validate_json
var2bytes
var2str
yield

(yield is already a reserved keyword listed above for Godot 4 so it doesn't need to be re-listed here)

'cos cosh cubic_interpolate cubic_interpolate_angle ' +
'cubic_interpolate_angle_in_time cubic_interpolate_in_time ' +
'db_to_linear deg_to_rad ease error_string exp floor floorf ' +
'floori fmod fposmod hash instance_from_id inverse_lerp ' +
'is_equal_approx is_finite is_inf is_instance_id_valid ' +
'is_instance_valid is_nan is_same is_zero_approx lerp lerp_angle ' +
'lerpf linear_to_db log max maxf maxi min minf mini move_toward ' +
'nearest_po2 pingpong posmod pow print print_rich print_verbose ' +
'printerr printraw prints printt push_error push_warning ' +
'rad_to_deg rand_from_seed randf randf_range randfn randi ' +
'randi_range randomize remap rid_allocate_id rid_from_int64 ' +
'rotate_toward round roundf roundi seed sign signf signi sin sinh ' +
'smoothstep snapped snappedf snappedi sqrt step_decimals str ' +
'str_to_var tan tanh type_convert type_string typeof var_to_bytes ' +
'var_to_bytes_with_objects var_to_str weakref wrap wrapf wrapi ' +
'Color8 assert char convert dict_to_inst get_stack inst_to_dict ' +
'is_instance_of len load preload print_debug print_stack range ' +
'type_exists',

literal: "true false null"
};
type:
'bool int float String Vector2 Vector2i Rect2 Rect2i Transform2D ' +
'Vector3 Vector3i Vector4 Vector4i Plane AABB Quaternion Basis ' +
'Transform3D Projection Color RID Object Callable Signal ' +
Comment on lines +43 to +44

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we also include the old Godot 3 math types?

Rect3 Quat Transform

'StringName NodePath Dictionary Array PackedByteArray ' +
'PackedInt32Array PackedInt64Array PackedFloat32Array ' +
'PackedFloat64Array PackedStringArray PackedVector2Array ' +
'PackedVector3Array PackedColorArray PackedVector4Array Variant ' +
Comment on lines +45 to +48

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like we lost the Godot 3 Pool*Arrays here.

'void',

return {
aliases: ["godot", "gdscript"],
keywords: KEYWORDS,

'char.escape':
'\\n \\t \\r \\a \\b \\f \\v \\" \\\' \\\\ ' +
'\\u{[0-9a-fA-F]{1,4}} \\U{[0-9a-fA-F]{1,6}}',

'variable.language': 'self super',
'variable.constant': 'PI TAU INF NAN',

literal: 'true false null',
},
contains: [
hljs.NUMBER_MODE,
hljs.HASH_COMMENT_MODE,
{
className: "comment",
className: 'string',
Copy link
Contributor Author

@Calinou Calinou May 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For context, GDScript does not actually have multiline comments, but only multiline strings. Multiline strings on their own line are standalone expressions, so they have no effect if you use them as comments.

The style guide recommends using ## for documentation comments, as this makes them display in the inspector when hovering the property.

begin: /"""/,
end: /"""/
end: /"""/,
},
{
className: 'string',
begin: /'''/,
end: /'''/,
},
{
className: 'meta',
begin: /#(end)?region/,
end: /\n/,
},
hljs.COMMENT(
'#',
'$',
{
contains: [
{
className: 'doctag',
begin: '@(tutorial|deprecated|experimental)+',
end: /$/,
},
],
},
),
hljs.QUOTE_STRING_MODE,
{
variants: [
{
className: "function",
beginKeywords: "func"
className: 'function',
beginKeywords: 'func',
},
{
className: "class",
beginKeywords: "class"
}
className: 'class',
beginKeywords: 'class',
},
],
end: /:/,
contains: [hljs.UNDERSCORE_TITLE_MODE]
}
]
contains: [
hljs.UNDERSCORE_TITLE_MODE,
],
},
{
className: 'meta',
begin: /@/,
end: /[ ,\(,\n]/,
keywords: {
keyword:
'@export @export_category @export_color_no_alpha @export_custom ' +
'@export_dir @export_enum @export_exp_easing @export_file ' +
'@export_flags @export_flags_2d_navigation @export_flags_2d_physics ' +
Comment on lines +113 to +116

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I confirmed the list of annotations is accurate for Godot 4 with:

grep "register_annotation(MethodInfo" gdscript_parser.cpp | sed 's/.*MethodInfo("\([^"]*\)".*/\1/' | sort

Could be documented too for future syncs.

'@export_flags_2d_render @export_flags_3d_navigation ' +
'@export_flags_3d_physics @export_flags_3d_render ' +
'@export_flags_avoidance @export_global_dir @export_global_file ' +
'@export_group @export_multiline @export_node_path ' +
'@export_placeholder @export_range @export_storage @export_subgroup ' +
'@export_tool_button @icon @onready @rpc @static_unload @tool ' +
'@warning_ignore @warning_ignore_restore @warning_ignore_start',
},
},
],
};
}

module.exports = GDScript;
};