Skip to content
This repository has been archived by the owner on Feb 13, 2019. It is now read-only.

Commit

Permalink
Merge branch 'refs/heads/master' into gh-pages
Browse files Browse the repository at this point in the history
  • Loading branch information
drublic committed Mar 28, 2012
2 parents 411c8f2 + 4c87a14 commit 5fd5c65
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 46 deletions.
31 changes: 31 additions & 0 deletions .gitignore
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,31 @@
# Numerous always-ignore extensions
*.diff
*.err
*.orig
*.log
*.rej
*.swo
*.swp
*.vi
*~
*.sass-cache

# OS or Editor folders
.DS_Store
Thumbs.db
.cache
.project
.settings
.tmproj
*.esproj
nbproject
*.sublime-project
*.sublime-workspace

# Dreamweaver added files
_notes
dwsync.xml

# Komodo
*.komodoproject
.komodotools
56 changes: 48 additions & 8 deletions README.md
Original file line number Original file line Diff line number Diff line change
@@ -1,19 +1,40 @@
# Support Browsers with Feature Detection # HTML5 Please API


This project provides an API based on [caniuse](http://caniuse.com)'s API to retrieve browser support information based on features you require on the client-side. ## Introduction


For example, if you want your page to only render on browsers that support Transitions and Canvas, you can send in an API request to [api.html5please.com](http://api.html5please.com) and print the returned HTML as a message when the page is viewed on browsers that do not support these features. Developers wishing to use modern browser features in their applications or demos often run into a very common issue: a user somewhere may be using a browser **incompatible** with what your project needs to function correctly. There are instances where this behaviour can be normalized using polyfills, but for all other instances, it's necessary to display a notification or message informing the user they need to **upgrade** to a different browser. The HTML5 Please API can help with this.


- TODO: Add images of how it looks like on browsers with/without support Rather than needing to take care of browser detection and manually listing the latest versions of browsers supported each time you use a modern feature, we provide a solution for this. Our **API** uses data sourced from [caniuse](http://caniuse.com)
and retrieves browser support information based on features you require on the client-side. For example, if you want your page to only render on browsers that support Transitions and Canvas, you can send in an API request to [api.html5please.com](http://api.html5please.com) and print the returned HTML as a message when the page is viewed on browsers that do not support these features.

We also provide a number of useful snippets to save you time creating a notification for your users. The project can generate widgets using a special [Modernizr](http://modernizr.com) plugin, pure JavaScript snippets that do the same or simply HTML links for those that wish to link their users out to a page with suggestions on browsers to consider upgrading to in order to support all the features needed for your site.


# Reference # Reference


URI Format: http://api.html5please.com/[feature1+feature2..+featureN].[format]?[option1&option2..optionN] Most users will be able to configure a snippet for their needs using our main widget/snippet [builder](http://api.html5please.com). If however you would like to learn more about the options supported by the API, please see below for more details.

## API URIs

URI Format:

http://api.html5please.com/[feature1+feature2..+featureN].[format]?[option1&option2..optionN]

URI Example:

http://api.html5please.com/video+audio+webgl.json?callback=h5please&texticon&html

For more information on formats supported, see the 'Formats' section below.



## Features ## Features
Any feature that you are looking for. Please look into the `keywords.json` to find out what features are supported. Alternatively you can use the autocomplete on the site to do so.
We support the majority of HTML5 features and probably cover any feature you're looking for. Please feel free to look at the `keywords.json` to find out what features are supported. Alternatively you can use the autocomplete on the site to do so.



## Formats ## Formats

Data from the API is output either as a JSON object, XML or HTML (depending on the format you choose). For complete details on our data objects, see the [wiki](https://github.com/h5bp/html5please-api/wiki/Data-Object-Reference).

- `html`: the output will be valid HTML with the mimetype of `text/html`. - `html`: the output will be valid HTML with the mimetype of `text/html`.


- `json`: the output will be valid JSON with the mimetype of `text/json`. - `json`: the output will be valid JSON with the mimetype of `text/json`.
Expand All @@ -28,20 +49,39 @@ Any feature that you are looking for. Please look into the `keywords.json` to fi


- `icon`: the HTML will be optimized for icon output. - `icon`: the HTML will be optimized for icon output.


-`supported`: the JSON will only output whether the agent supports the requested features. - `supported`: the JSON will only output whether the agent supports the requested features.


- `noagent`: the JS will return results for all browsers with no agent detection. - `noagent`: the JS will return results for all browsers with no agent detection.


- `callback = [ functionName ]`: the output will be JavaScript, wrapped in this function name. - `callback = [ functionName ]`: the output will be JavaScript, wrapped in this function name.


## UA Detection

The HTML5 Please service uses UA detection as a part of our process for detecting the browser currently used by the user. This is strictly used for deciding what browsers and browser versions we should recommend end-users upgrade to in order to use a feature. For more information on this, please see [this](https://github.com/h5bp/html5please-api/wiki/How-does-the-UA-Detection-work%3F
) entry on the wiki.

## Examples

We will be posting more demos and examples of the how the project can be used shortly. In the mean time if you would like to look at two projects already making use of the API, see [http://mothereffinganimatedgif.com/](http://mothereffinganimatedgif.com/) or [http://lab.simurai.com/flashlight/](http://lab.simurai.com/flashlight/).


The site that represents this project runs off `index.html` and references files from `site` folder. It uses SASS so please make any changes to `style.scss` rather than `style.css`. # History

Divya has a [post](http://nimbupani.com/html5please-api.html) about the project history we recommend checking out. This project began as one of her [LazyWeb](https://github.com/paulirish/lazyweb-requests/issues/39) requests for a healthy choose-your-browser page. [@addyosmani](http://github.com/addyosmani) worked on the initial implementation, to be later replaced with a much more rich API and UI by [@jonathantneal](http://github.com/jonathantneal), [@nimbupani](http://github.com/nimbupani) and other contributors. Jons service is what currently powers much of the HTML5 Please API. We are still very much working on improving it and recommend looking at the 'Contributing' section below in case you would like to help out.

# Contributing

We welcome any and all contributions to improve the project. Please feel free to fork and send through a pull request if there's something you feel we could be doing better.

Note that the site that represents this project runs off `index.html` and references files from `site` folder. It uses [SASS](http://sass-lang.com/) so please make any changes to `style.scss` rather than `style.css`. The logic for much of the UI is based in `site/js/script.js` should any changes need to be made on that front.


# Credits # Credits


- @fyrd for amazing caniuse API which underlies this work - @fyrd for amazing caniuse API which underlies this work
- @jonathantneal for all the magic with PHP and building a robust API on top of caniuse's data - @jonathantneal for all the magic with PHP and building a robust API on top of caniuse's data
- @aaronlayton for initial design of html output - @aaronlayton for initial design of html output
- @drublic for various fixes to the builder/UI
- @addyosmani for help with the docs
- @divya & @paul_irish for corralling the project together - @divya & @paul_irish for corralling the project together





12 changes: 6 additions & 6 deletions agents.json
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"type": "desktop", "type": "desktop",
"url": "http:\/\/www.firefox.com\/", "url": "http:\/\/www.firefox.com\/",
"sniffer": "/firefox\\/([\\d\\.]+)/i", "sniffer": "/firefox\\/([\\d\\.]+)/i",
"currentVersion": "10" "currentVersion": "11"
}, },
"chrome": { "chrome": {
"name": "Chrome", "name": "Chrome",
Expand All @@ -37,7 +37,7 @@
"type": "desktop", "type": "desktop",
"url": "http:\/\/www.opera.com\/", "url": "http:\/\/www.opera.com\/",
"sniffer": "/opera[\\W\\w]*?version\\/([\\d\\.]+)|opera[\\W\\w]*?([\\d\\.]+)/i", "sniffer": "/opera[\\W\\w]*?version\\/([\\d\\.]+)|opera[\\W\\w]*?([\\d\\.]+)/i",
"currentVersion": "11.6" "currentVersion": "11.61"
}, },
"ios_saf": { "ios_saf": {
"name": "iOS Safari", "name": "iOS Safari",
Expand All @@ -52,16 +52,16 @@
"prefix": "o", "prefix": "o",
"type": "mobile", "type": "mobile",
"url": "http:\/\/www.opera.com\/mobile\/", "url": "http:\/\/www.opera.com\/mobile\/",
"sniffer": "/opera\\s*mobi[\\W\\w]*?version\\/([\\d\\.]+)/i", "sniffer": "/opera\\s*mini[\\W\\w]*?version\\/([\\d\\.]+)/i",
"currentVersion": "5.0-6.0" "currentVersion": "7"
}, },
"op_mob": { "op_mob": {
"name": "Opera Mobile", "name": "Opera Mobile",
"prefix": "o", "prefix": "o",
"type": "mobile", "type": "mobile",
"url": "http:\/\/www.opera.com\/mobile\/", "url": "http:\/\/www.opera.com\/mobile\/",
"sniffer": "/opera\\s*mini[\\W\\w]*?version\\/([\\d\\.]+)/i", "sniffer": "/opera\\s*mobi[\\W\\w]*?version\\/([\\d\\.]+)/i",
"currentVersion": "11.5" "currentVersion": "12"
}, },
"android": { "android": {
"name": "Android Browser", "name": "Android Browser",
Expand Down
2 changes: 1 addition & 1 deletion css/icon.css
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


.caniuse-agt-ico:before .caniuse-agt-ico:before
{ {
background: url(http://h5bp.github.com/caniuse/i/icons-32.png) 0 0 no-repeat; background: url(http://h5bp.github.com/html5please-api/i/icons-32.png) 0 0 no-repeat;
content: ""; content: "";
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
Expand Down
14 changes: 12 additions & 2 deletions handler.methods.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ function filter_features(& $request_features_array = array(), & $keywords_array
// returns filtered support metrics from features, agents, and data // returns filtered support metrics from features, agents, and data
function filter_supportmetrics(& $option_features = array(), $agents_array = array(), & $data_array = array()) { function filter_supportmetrics(& $option_features = array(), $agents_array = array(), & $data_array = array(), $state) {
$return_array = array( $return_array = array(
'agents' =>& $agents_array, 'agents' =>& $agents_array,
'features' => array(), 'features' => array(),
Expand All @@ -218,7 +218,7 @@ function filter_supportmetrics(& $option_features = array(), $agents_array = arr
} }
foreach ($option_features as $feature_name) { foreach ($option_features as $feature_name) {
$property_array = first_set(@$data_array[$feature_name]['supported'], array()); $property_array = first_set(@$data_array[$feature_name][$state], array());
$return_array['result'][$feature_name] = $property_array; $return_array['result'][$feature_name] = $property_array;
Expand Down Expand Up @@ -396,22 +396,32 @@ function html_encode(&$return_array = array(), $requested_style_string = '', $re
$html = preg_replace('/\s*<% supported %>[\W\w]*?<% \/supported %>/', '', $html); $html = preg_replace('/\s*<% supported %>[\W\w]*?<% \/supported %>/', '', $html);
$html = preg_replace('/\s*<% supported_with_upgrade %>[\W\w]*?<% \/supported_with_upgrade %>/', '', $html); $html = preg_replace('/\s*<% supported_with_upgrade %>[\W\w]*?<% \/supported_with_upgrade %>/', '', $html);
$html = preg_replace('/\s*<% unsupported %>[\W\w]*?<% \/unsupported %>/', '', $html); $html = preg_replace('/\s*<% unsupported %>[\W\w]*?<% \/unsupported %>/', '', $html);
$html = preg_replace('/\s*<% partial %>[\W\w]*?<% \/partial %>/', '', $html);
} else if ($return_array['supported']) { } else if ($return_array['supported']) {
$html = preg_replace('/\s*<% noagent %>[\W\w]*?<% \/noagent %>/', '', $html); $html = preg_replace('/\s*<% noagent %>[\W\w]*?<% \/noagent %>/', '', $html);
$html = preg_replace('/\s*<% supported %>|<% \/supported %>/', '', $html); $html = preg_replace('/\s*<% supported %>|<% \/supported %>/', '', $html);
$html = preg_replace('/\s*<% supported_with_upgrade %>[\W\w]*?<% \/supported_with_upgrade %>/', '', $html); $html = preg_replace('/\s*<% supported_with_upgrade %>[\W\w]*?<% \/supported_with_upgrade %>/', '', $html);
$html = preg_replace('/\s*<% unsupported %>[\W\w]*?<% \/unsupported %>/', '', $html); $html = preg_replace('/\s*<% unsupported %>[\W\w]*?<% \/unsupported %>/', '', $html);
$html = preg_replace('/\s*<% partial %>[\W\w]*?<% \/partial %>/', '', $html);
} elseif ($return_array['upgradable']) { } elseif ($return_array['upgradable']) {
$html = preg_replace('/\s*<% noagent %>[\W\w]*?<% \/noagent %>/', '', $html); $html = preg_replace('/\s*<% noagent %>[\W\w]*?<% \/noagent %>/', '', $html);
$html = preg_replace('/\s*<% supported %>[\W\w]*?<% \/supported %>/', '', $html); $html = preg_replace('/\s*<% supported %>[\W\w]*?<% \/supported %>/', '', $html);
$html = preg_replace('/\s*<% supported_with_upgrade %>|<% \/supported_with_upgrade %>/', '', $html); $html = preg_replace('/\s*<% supported_with_upgrade %>|<% \/supported_with_upgrade %>/', '', $html);
$html = preg_replace('/\s*<% unsupported %>[\W\w]*?<% \/unsupported %>/', '', $html); $html = preg_replace('/\s*<% unsupported %>[\W\w]*?<% \/unsupported %>/', '', $html);
$html = preg_replace('/\s*<% partial %>[\W\w]*?<% \/partial %>/', '', $html);
} elseif ($return_array['partial']) {
$html = preg_replace('/\s*<% noagent %>[\W\w]*?<% \/noagent %>/', '', $html);
$html = preg_replace('/\s*<% supported %>[\W\w]*?<% \/supported %>/', '', $html);
$html = preg_replace('/\s*<% supported_with_upgrade %>[\W\w]*?<% \/supported_with_upgrade %>/', '', $html);
$html = preg_replace('/\s*<% unsupported %>[\W\w]*?<% \/unsupported %>/', '', $html);
$html = preg_replace('/\s*<% partial %>|<% \/partial %>/', '', $html);
} }
else { else {
$html = preg_replace('/\s*<% noagent %>[\W\w]*?<% \/noagent %>/', '', $html); $html = preg_replace('/\s*<% noagent %>[\W\w]*?<% \/noagent %>/', '', $html);
$html = preg_replace('/\s*<% supported %>[\W\w]*?<% \/supported %>/', '', $html); $html = preg_replace('/\s*<% supported %>[\W\w]*?<% \/supported %>/', '', $html);
$html = preg_replace('/\s*<% supported_with_upgrade %>[\W\w]*?<% \/supported_with_upgrade %>/', '', $html); $html = preg_replace('/\s*<% supported_with_upgrade %>[\W\w]*?<% \/supported_with_upgrade %>/', '', $html);
$html = preg_replace('/\s*<% unsupported %>|<% \/unsupported %>/', '', $html); $html = preg_replace('/\s*<% unsupported %>|<% \/unsupported %>/', '', $html);
$html = preg_replace('/\s*<% partial %>[\W\w]*?<% \/partial %>/', '', $html);
} }
$html = preg_replace('/<%= browserid %>/', $return_array['agent']['id'], $html); $html = preg_replace('/<%= browserid %>/', $return_array['agent']['id'], $html);
Expand Down
15 changes: 14 additions & 1 deletion handler.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -26,11 +26,24 @@
$support_array['supported'] = isset($support_array['results'][$useragent_array['id']]) && version_compare($useragent_array['version'], $support_array['results'][$useragent_array['id']]) > -1; $support_array['supported'] = isset($support_array['results'][$useragent_array['id']]) && version_compare($useragent_array['version'], $support_array['results'][$useragent_array['id']]) > -1;


$support_array['upgradable'] = !$support_array['supported'] && isset($support_array['results'][$useragent_array['id']]); $support_array['upgradable'] = !$support_array['supported'] && isset($support_array['results'][$useragent_array['id']]);

$support_array['partial'] = '';

if (empty($support_array['supported'])) {
$partial_array = filter_supportmetrics($option_features, $agents_array, $data_array, 'partial');

$support_array['partial'] = isset($partial_array['results'][$useragent_array['id']]) && version_compare($useragent_array['version'], $partial_array['results'][$useragent_array['id']]) > -1;

$support_array['results'] = $partial_array['results'];
$support_array['agents'] = $partial_array['agents'];
}



if ($option_barebones) { if ($option_barebones) {
$support_array = array( $support_array = array(
'supported' => $support_array['supported'], 'supported' => $support_array['supported'],
'upgradable' => $support_array['upgradable'] 'upgradable' => $support_array['upgradable'],
'partial' => $support_array['partial']
); );
} }
} }
Expand Down
62 changes: 55 additions & 7 deletions index.html
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
<link rel="shortcut icon" href="http://html5please.com/favicon.ico" /> <link rel="shortcut icon" href="http://html5please.com/favicon.ico" />
<link href='http://fonts.googleapis.com/css?family=Alfa+Slab+One|Droid+Serif:700italic,400italic' rel='stylesheet' type='text/css'> <link href='http://fonts.googleapis.com/css?family=Alfa+Slab+One|Droid+Serif:700italic,400italic' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="site/css/style.css"> <link rel="stylesheet" href="site/css/style.css">

<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head> </head>
<body> <body>
<header> <header>
Expand All @@ -23,7 +27,7 @@ <h1 class="logo">
</div> </div>
</header> </header>
<div id="about"> <div id="about">
<p>If you've created a demo or site that requires Canvas or WebSQL DB, you've been in the awkward situation of telling some of your visitors that their browser isn't good enough. But you can't just recommend they get a browser with those features; for example, "Get a WebRTC capable browser" is pretty much useless to everyone. <p>If you've created a demo or site that requires Canvas or WebSQL DB, you've been in the awkward situation of telling some of your visitors that their browser doesn't support those features. But you can't just recommend they get a browser with those features; for example, "Get a WebRTC capable browser" is pretty much useless to everyone.


<p>The HTML5 Please API translates developer language (features) to user language (browsers). Call the API and you get back some HTML to show the user or a JSON object of the relevant data (with browser logos and all), so you can customize what you show to users. <p>The HTML5 Please API translates developer language (features) to user language (browsers). Call the API and you get back some HTML to show the user or a JSON object of the relevant data (with browser logos and all), so you can customize what you show to users.
</p> </p>
Expand Down Expand Up @@ -56,15 +60,47 @@ <h3>Enter features you use</h3>
<div class="options"> <div class="options">
<h3>How do you want to show this?</h3> <h3>How do you want to show this?</h3>
<div class="options-content"> <div class="options-content">
<p>with browser <b><input type="radio" name="skin" value="icon" checked><label>logos</label></b> <b><input type="radio" name="skin" value="text"><label>names</label></b> <b><input type="radio" name="skin" value="texticon" checked><label>both logos &amp; names</label></b></p> <p>with browser
<p><b><input type="checkbox" name="style" value="nocss"><label>without style</label></b></p> <b>
<input type="radio" name="skin" value="icon" id="options-logo">
<label for="options-logo">logos</label>
</b>
<b>
<input type="radio" name="skin" value="text" id="options-names">
<label for="options-names">names</label>
</b>
<b>
<input type="radio" name="skin" value="texticon" id="options-both" checked>
<label for="options-both">both logos &amp; names</label>
</b>
</p>
<p>
<b>
<input type="checkbox" name="style" value="nocss" id="options-style">
<label for="options-style">without style</label>
</b>
</p>
</div> </div>
</div> </div>
</form> </form>
<div id="api-result"> <div id="api-result">
<div class="use"> <div class="use">
<h3>Here is your widget</h3> <h3>Here is your widget</h3>
<h4><b><input type="radio" name="widgetformat" checked id="widget-modernizr" value="0"><label for="modernizr">with Modernizr <u>(recommended)</u></label></b> <b><input type="radio" name="widgetformat" id="widget-js" value = "1"><label for="pure-js">just JS</label></b><b><input type="radio" name="widgetformat" id="widget-uri" value="2"><label for="widget-uri">URI</label></b></h4> <h4>
<b>
<input type="radio" name="widgetformat" checked id="widget-modernizr" value="0">
<label for="widget-modernizr">with Modernizr <u>(recommended)</u></label>
</b>
<b>
<input type="radio" name="widgetformat" id="widget-js" value="1">
<label for="widget-js">just JS</label>
</b>

<b>
<input type="radio" name="widgetformat" id="widget-uri" value="2">
<label for="widget-uri">URI</label>
</b>
</h4>
<div id="widget"> <div id="widget">
</div> </div>
<div id="widget-message" class="help"></div> <div id="widget-message" class="help"></div>
Expand Down Expand Up @@ -98,7 +134,7 @@ <h2>Reference</h2>


<section id="contribute"> <section id="contribute">
<h2> Contribute </h2> <h2> Contribute </h2>
<p> This is a community project. You can <a href="https://github.com/h5bp/html5please-api">help by forking caniuse</a> and making it better. Please also file a ticket to start a discussion. </p> <p> This is a community project. You can <a href="https://github.com/h5bp/html5please-api">help by forking html5please-api</a> and making it better. Please also file a ticket to start a discussion. </p>
</section> </section>
<footer> <footer>
<div class="builders"> <div class="builders">
Expand Down Expand Up @@ -130,15 +166,27 @@ <h3>With</h3>
<img src="http://api.twitter.com/1/users/profile_image/drublic?size=normal" alt="Hans Christian Reinl"> <img src="http://api.twitter.com/1/users/profile_image/drublic?size=normal" alt="Hans Christian Reinl">
<b>Hans Chr.</b> Reinl <b>Hans Chr.</b> Reinl
</a> </a>

<a href="http://twitter.com/addyosmani">
<img src="http://api.twitter.com/1/users/profile_image/addyosmani?size=normal" alt="Addy Osmani">
<b>Addy</b> Osmani
</a>
</div> </div>
<p> <a href="https://github.com/h5bp/html5please-api/contributors">&amp; more</a> </p> <p> <a href="https://github.com/h5bp/html5please-api/contributors">&amp; more</a> </p>
<p>This project was inspired by <a href="//get.webgl.org/">get.webgl.org</a> and was initiated over at <a href="https://github.com/paulirish/lazyweb-requests/issues/39">github:paulirish/lazyweb-requests#39</a>. Much thanks to <a href="//twitter.com/fyrd">Alexis Deveria</a> for the generous sharing of <a href="http://caniuse.com/">caniuse</a> data. </p> <p>This project was inspired by <a href="//get.webgl.org/">get.webgl.org</a> and was initiated over at <a href="https://github.com/paulirish/lazyweb-requests/issues/39">github:paulirish/lazyweb-requests#39</a>. <br>
Much thanks to <a href="//twitter.com/fyrd">Alexis Deveria</a> for the generous sharing of <a href="http://caniuse.com/">caniuse</a> data. </p>
</footer> </footer>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="site/js/jquery-1.7.1.min.js"><\/script>')</script> <script>window.jQuery || document.write('<script src="site/js/jquery-1.7.1.min.js"><\/script>')</script>


<script src="site/js/jquery-ui-1.8.17.custom.min.js"></script> <script src="site/js/jquery-ui-1.8.17.custom.min.js"></script>
<script src="site/js/script.js"></script> <script src="site/js/script.js"></script>

<script>
var _gaq=[['_setAccount','UA-17904194-3'],['_trackPageview'],['_trackPageLoadTime']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src=('https:'==location.protocol?'//ssl':'//www')+'.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>

</body> </body>
</html> </html>
Loading

0 comments on commit 5fd5c65

Please sign in to comment.