11_COMPAT_KEY =
'__compat'
12_EXPERIMENTAL_KEY =
'experimental'
14_SUPPORT_KEY =
'support'
15_VERSION_ADDED_KEY =
'version_added'
18def _get_browser_compat_data():
19 current_dir = os.path.dirname(__file__)
21 browser_compat_folder = os.path.abspath(
22 os.path.join(current_dir,
'..',
'..',
'..',
'third_party',
'mdn',
23 'browser-compat-data',
'src'))
25 if not os.path.exists(browser_compat_folder):
26 raise RuntimeError(
'Browser compatibility data not found at %s' %
27 browser_compat_folder)
29 browser_compat_data = {}
40 os.path.join(browser_compat_folder, dir)
for dir
in INCLUDE_DIRS
43 def process_json_dict(json_dict):
46 if 'api' in json_dict:
48 api_dict = json_dict[
'api']
49 interface_name =
next(iter(api_dict))
50 return (interface_name, api_dict[interface_name])
51 elif 'html' in json_dict:
52 html_dict = json_dict[
'html']
53 if 'elements' in html_dict:
54 elements_dict = html_dict[
'elements']
55 element_name =
next(iter(elements_dict))
57 interface = str(
'HTML' + element_name +
'Element')
58 return (interface, elements_dict[element_name])
59 elif 'svg' in json_dict:
60 svg_dict = json_dict[
'svg']
61 if 'elements' in svg_dict:
62 elements_dict = svg_dict[
'elements']
63 element_name =
next(iter(elements_dict))
65 interface = str(
'SVG' + element_name +
'Element')
66 return (interface, elements_dict[element_name])
72 def _unify_compat(a, b):
74 def _has_compat_data(metadata):
75 return _COMPAT_KEY
in metadata
and _SUPPORT_KEY
in metadata[_COMPAT_KEY]
80 def _unify_support(support_a, support_b):
81 for browser
in support_a.keys():
82 if browser
in support_b:
83 if _is_simple_support_statement(support_a[browser])
and _is_simple_support_statement(support_b[browser]):
84 support_a[browser][_VERSION_ADDED_KEY] = _unify_versions(
85 support_a[browser][_VERSION_ADDED_KEY],
86 support_b[browser][_VERSION_ADDED_KEY])
89 support_a[browser] = {_VERSION_ADDED_KEY:
None}
90 for browser
in support_b.keys():
91 if not browser
in support_a:
92 support_a[browser] = support_b[browser]
94 if not _has_compat_data(b):
96 if not _has_compat_data(a):
97 a[_COMPAT_KEY] = b[_COMPAT_KEY]
100 support_a = a[_COMPAT_KEY][_SUPPORT_KEY]
101 support_b = b[_COMPAT_KEY][_SUPPORT_KEY]
103 _unify_support(support_a, support_b)
107 def _unify_status(a, b):
109 def _has_status(metadata):
110 return _COMPAT_KEY
in metadata
and _STATUS_KEY
in metadata[_COMPAT_KEY]
113 def _unify_experimental(status_a, status_b):
116 status_a[_EXPERIMENTAL_KEY] = status_a.get(
117 _EXPERIMENTAL_KEY,
False)
or status_b.get(_EXPERIMENTAL_KEY,
False)
119 if not _has_status(b):
121 if not _has_status(a):
122 a[_COMPAT_KEY] = b[_COMPAT_KEY]
125 status_a = a[_COMPAT_KEY][_STATUS_KEY]
126 status_b = b[_COMPAT_KEY][_STATUS_KEY]
128 _unify_experimental(status_a, status_b)
133 def _unify_metadata(a, b):
138 for attr
in list(a.keys()):
139 if attr == _COMPAT_KEY:
142 _unify_compat(a[attr], b[attr])
143 _unify_status(a[attr], b[attr])
144 for attr
in b.keys():
148 for (dir_path, dirs, files)
in os.walk(browser_compat_folder):
150 def should_process_dir(dir_path):
151 if os.path.abspath(dir_path) == browser_compat_folder:
153 for dir
in INCLUDE_DIRS:
154 if dir_path.startswith(dir):
158 if should_process_dir(dir_path):
160 file_name = os.path.join(dir_path, name)
161 (interface_path, ext) = os.path.splitext(file_name)
163 with open(file_name)
as src:
164 json_dict = json.load(src)
165 interface, metadata = process_json_dict(json_dict)
166 if not interface
is None:
171 interface = interface.lower()
174 for member, info
in metadata.items()
177 if interface
in browser_compat_data:
178 _unify_metadata(browser_compat_data[interface],
181 browser_compat_data[interface] = metadata
185 return browser_compat_data
189def _unify_versions(version_a, version_b):
192 def _greater_version(version_a, version_b):
193 version_a_split = list(
map(int, version_a.split(
'.')))
194 version_b_split = list(
map(int, version_b.split(
'.')))
195 for i
in range(
min(
len(version_a_split),
len(version_b_split))):
196 if version_a_split[i] > version_b_split[i]:
198 elif version_a_split[i] < version_b_split[i]:
200 return version_a
if len(version_a_split) >
len(
201 version_b_split)
else version_b
204 def _validate_version(version):
209 if isinstance(version, str):
210 pattern = re.compile(
'^([0-9]+\.)*[0-9]+$')
211 if not pattern.match(version):
219 'Type of version_a was not handled correctly! type(version) = '
220 + str(
type(version)))
222 version_a = _validate_version(version_a)
223 version_b = _validate_version(version_b)
225 if not version_a
or not version_b:
229 if version_a
is True:
231 if version_b
is True:
234 return _greater_version(version_a, version_b)
239def _is_simple_support_statement(support_statement):
240 if isinstance(support_statement, list):
247 if len(support_statement.keys()) > 1:
257 _BROWSER_COMPAT_DATA = _get_browser_compat_data()
262 def _get_attr_compatibility(self, compat_data):
268 browser_version_map = {
276 for browser
in browser_version_map.keys():
277 support_data = compat_data[_SUPPORT_KEY]
278 if browser
not in support_data:
280 support_statement = support_data[browser]
281 if not _is_simple_support_statement(support_statement):
283 version = support_statement[_VERSION_ADDED_KEY]
285 target = browser_version_map[browser]
286 if _unify_versions(version, target) != target:
290 status_data = compat_data[_STATUS_KEY]
291 if _EXPERIMENTAL_KEY
in status_data
and status_data[_EXPERIMENTAL_KEY]:
298 interface = attribute.doc_js_interface_name.lower()
302 id_name = attribute.id.lower()
303 secure_context_key =
'isSecureContext'
307 elif secure_context_key
in interface_dict:
311 elif id_name
in interface_dict:
312 id_data = interface_dict[id_name]
323 if not compatible
in [
True,
False,
None]:
324 raise ValueError(
'Cannot set a non-boolean object for compatible')
325 interface = attribute.doc_js_interface_name.lower()
328 if attribute.id
and len(attribute.id) > 0:
329 id_name = attribute.id.lower()
static float next(float f)
def set_compatible(self, attribute, compatible)
def _get_attr_compatibility(self, compat_data)
def is_compatible(self, attribute)
static float min(float r, float g, float b)
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>