TextMateLib 1.0
Modern C++ implementation of the TextMate syntax highlighting engine
Loading...
Searching...
No Matches
parseRawTheme.cpp
1#include "parseRawTheme.h"
2#include "rapidjson/document.h"
3#include "rapidjson/error/en.h"
4#include <stdexcept>
5
6using namespace rapidjson;
7
8namespace tml {
9
10IRawTheme* parseRawTheme(const std::string& content) {
11 try {
12 Document doc;
13 doc.Parse(content.c_str());
14
15 if (doc.HasParseError()) {
16 return nullptr;
17 }
18
19 // Create IRawTheme from JSON
20 auto rawTheme = new IRawTheme();
21
22 // Get theme name
23 if (doc.HasMember("name") && doc["name"].IsString()) {
24 rawTheme->name = new std::string(doc["name"].GetString());
25 }
26
27 // Parse settings array (supports both "settings" and "tokenColors" keys)
28 // VSCode themes use "tokenColors", TextMate themes use "settings"
29 const Value* settingsArray = nullptr;
30 if (doc.HasMember("tokenColors") && doc["tokenColors"].IsArray()) {
31 settingsArray = &doc["tokenColors"];
32 } else if (doc.HasMember("settings") && doc["settings"].IsArray()) {
33 settingsArray = &doc["settings"];
34 }
35
36 if (settingsArray) {
37 for (const auto& settingObj : settingsArray->GetArray()) {
38 if (!settingObj.IsObject()) {
39 continue;
40 }
41
42 auto setting = new IRawThemeSetting();
43
44 // Get name
45 if (settingObj.HasMember("name") && settingObj["name"].IsString()) {
46 setting->name = new std::string(settingObj["name"].GetString());
47 }
48
49 // Get scope(s)
50 if (settingObj.HasMember("scope")) {
51 const auto& scopeVal = settingObj["scope"];
52 if (scopeVal.IsString()) {
53 setting->scopeString = scopeVal.GetString();
54 auto scopeVec = new std::vector<std::string>();
55 scopeVec->push_back(setting->scopeString);
56 setting->scope = scopeVec;
57 } else if (scopeVal.IsArray()) {
58 setting->scope = new std::vector<std::string>();
59 for (const auto& scopeStr : scopeVal.GetArray()) {
60 if (scopeStr.IsString()) {
61 setting->scope->push_back(scopeStr.GetString());
62 }
63 }
64 }
65 }
66
67 // Get settings object
68 if (settingObj.HasMember("settings") && settingObj["settings"].IsObject()) {
69 const auto& settingsObj = settingObj["settings"];
70
71 if (settingsObj.HasMember("fontStyle") && settingsObj["fontStyle"].IsString()) {
72 setting->settings.fontStyle = new std::string(settingsObj["fontStyle"].GetString());
73 }
74 if (settingsObj.HasMember("foreground") && settingsObj["foreground"].IsString()) {
75 setting->settings.foreground = new std::string(settingsObj["foreground"].GetString());
76 }
77 if (settingsObj.HasMember("background") && settingsObj["background"].IsString()) {
78 setting->settings.background = new std::string(settingsObj["background"].GetString());
79 }
80 }
81
82 rawTheme->settings.push_back(setting);
83 }
84 }
85
86 // VSCode themes have editor colors in "colors" section
87 // Extract editor.foreground and editor.background as default theme colors
88 if (doc.HasMember("colors") && doc["colors"].IsObject()) {
89 const auto& colors = doc["colors"];
90
91 std::string* defaultForeground = nullptr;
92 std::string* defaultBackground = nullptr;
93
94 if (colors.HasMember("editor.foreground") && colors["editor.foreground"].IsString()) {
95 defaultForeground = new std::string(colors["editor.foreground"].GetString());
96 }
97 if (colors.HasMember("editor.background") && colors["editor.background"].IsString()) {
98 defaultBackground = new std::string(colors["editor.background"].GetString());
99 }
100
101 // Create a default setting with empty scope for editor colors
102 if (defaultForeground || defaultBackground) {
103 auto defaultSetting = new IRawThemeSetting();
104 // Empty scope means this is the default
105 defaultSetting->scope = nullptr;
106 defaultSetting->scopeString = "";
107
108 if (defaultForeground) {
109 defaultSetting->settings.foreground = defaultForeground;
110 }
111 if (defaultBackground) {
112 defaultSetting->settings.background = defaultBackground;
113 }
114
115 // Insert at beginning so it acts as the base default
116 rawTheme->settings.insert(rawTheme->settings.begin(), defaultSetting);
117 }
118 }
119
120 return rawTheme;
121 } catch (...) {
122 return nullptr;
123 }
124}
125
126Theme* parseJSONTheme(const std::string& content) {
127 try {
128 IRawTheme* rawTheme = parseRawTheme(content);
129 if (!rawTheme) {
130 return nullptr;
131 }
132
133 // Create Theme from raw theme
134 Theme* theme = Theme::createFromRawTheme(rawTheme);
135 delete rawTheme;
136
137 return theme;
138 } catch (...) {
139 return nullptr;
140 }
141}
142
143} // namespace tml