From dc72a375f0a6c594ec1d28a74989103a9b986ad6 Mon Sep 17 00:00:00 2001 From: Mike Mollick Date: Fri, 26 Oct 2018 22:42:50 -0400 Subject: [PATCH] Adding prettier to pre commit hook --- package.json | 4 +- pre-commit | 7 ++ source/js/main.js | 130 +++++++++++----------- source/js/search.js | 144 ++++++++++++------------ source/js/sidebar.js | 195 ++++++++++++++++++--------------- source/styles/_railscasts.scss | 3 +- source/styles/index.scss | 109 ++++++++---------- yarn.lock | 5 + 8 files changed, 308 insertions(+), 289 deletions(-) diff --git a/package.json b/package.json index e1e9b5a..71f7b18 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "css-loader": "^1.0.0", "mini-css-extract-plugin": "^0.4.4", "node-sass": "^4.9.4", + "prettier": "1.14.3", "sass-loader": "^7.1.0", "webpack": "^4.23.0", "webpack-cli": "^3.1.2" @@ -17,6 +18,7 @@ "test": "echo \"Error: no test specified\" && exit 1", "build": "NODE_ENV=production webpack", "dev": "webpack", - "watch": "webpack --watch" + "watch": "webpack --watch", + "prettier": "prettier --write --single-quote source/**/*.{scss,js}" } } diff --git a/pre-commit b/pre-commit index f2ae3d7..79af459 100755 --- a/pre-commit +++ b/pre-commit @@ -3,3 +3,10 @@ ./vendor/bin/phpcbf git add . +# Frontend asset formatting +prettierFiles=$(git diff --cached --name-only --diff-filter=ACM "*.js" "*.scss" | tr '\n' ' ') +if [ -n "$prettierFiles" ] + then + echo "$prettierFiles" | xargs ./node_modules/.bin/prettier --write --single-quote + echo "$prettierFiles" | xargs git add +fi \ No newline at end of file diff --git a/source/js/main.js b/source/js/main.js index b47a7c5..dc0322e 100644 --- a/source/js/main.js +++ b/source/js/main.js @@ -1,75 +1,81 @@ String.prototype.replaceAll = function(search, replacement) { - var target = this; + var target = this; - return target.split(search).join(replacement); + return target.split(search).join(replacement); }; var Main = function() { - function scrollFunction() { - if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) { - document.getElementById('back-to-top').style.display = "block"; - } else { - document.getElementById('back-to-top').style.display = "none"; - } + function scrollFunction() { + if ( + document.body.scrollTop > 20 || + document.documentElement.scrollTop > 20 + ) { + document.getElementById('back-to-top').style.display = 'block'; + } else { + document.getElementById('back-to-top').style.display = 'none'; } + } - window.onscroll = function() { - scrollFunction(); - }; + window.onscroll = function() { + scrollFunction(); + }; - $('#back-to-top').on('click', function() { - document.body.scrollTop = 0; - document.documentElement.scrollTop = 0; + $('#back-to-top').on('click', function() { + document.body.scrollTop = 0; + document.documentElement.scrollTop = 0; + }); + + $(document).ready(function() { + $('div.configuration-block [class^=highlight-]').hide(); + $('div.configuration-block [class^=highlight-]').width( + $('div.configuration-block').width() + ); + + $('div.configuration-block').addClass('jsactive'); + $('div.configuration-block').addClass('clearfix'); + + $('div.configuration-block').each(function() { + var el = $('[class^=highlight-]:first', $(this)); + el.show(); + el.parents('ul').height(el.height() + 40); }); - $(document).ready(function(){ - $('div.configuration-block [class^=highlight-]').hide(); - $('div.configuration-block [class^=highlight-]').width($('div.configuration-block').width()); + // Global + $('div.configuration-block li').each(function() { + var str = $(':first', $(this)).html(); + $(':first ', $(this)).html(''); + $(':first ', $(this)).append('' + str + ''); + $(':first', $(this)).bind('click', function() { + $('[class^=highlight-]', $(this).parents('ul')).hide(); + $('li', $(this).parents('ul')).removeClass('selected'); + $(this) + .parent() + .addClass('selected'); - $('div.configuration-block').addClass('jsactive'); - $('div.configuration-block').addClass('clearfix'); - - $('div.configuration-block').each(function () { - var el = $('[class^=highlight-]:first', $(this)); - el.show(); - el.parents('ul').height(el.height() + 40); - }); - - // Global - $('div.configuration-block li').each(function() { - var str = $(':first', $(this)).html(); - $(':first ', $(this)).html(''); - $(':first ', $(this)).append('' + str + '') - $(':first', $(this)).bind('click', function(){ - $('[class^=highlight-]', $(this).parents('ul')).hide(); - $('li', $(this).parents('ul')).removeClass('selected'); - $(this).parent().addClass('selected'); - - var block = $('[class^=highlight-]', $(this).parent('li')); - block.show(); - block.parents('ul').height(block.height() + 40); - return false; - }); - }); - - $('div.configuration-block').each(function () { - $('li:first', $(this)).addClass('selected'); - }); - - $('[data-toggle="tooltip"]').tooltip(); - - $('button.copy-to-clipboard').on('click', function() { - var copyElementId = $(this).data('copy-element-id'); - - var copyText = $('#' + copyElementId + ' .code-line').text(); - - var element = document.createElement('textarea'); - element.value = copyText; - document.body.appendChild(element); - element.select(); - document.execCommand('copy'); - document.body.removeChild(element); - }); + var block = $('[class^=highlight-]', $(this).parent('li')); + block.show(); + block.parents('ul').height(block.height() + 40); + return false; + }); }); + + $('div.configuration-block').each(function() { + $('li:first', $(this)).addClass('selected'); + }); + + $('[data-toggle="tooltip"]').tooltip(); + + $('button.copy-to-clipboard').on('click', function() { + var copyElementId = $(this).data('copy-element-id'); + + var copyText = $('#' + copyElementId + ' .code-line').text(); + + var element = document.createElement('textarea'); + element.value = copyText; + document.body.appendChild(element); + element.select(); + document.execCommand('copy'); + document.body.removeChild(element); + }); + }); }; - diff --git a/source/js/search.js b/source/js/search.js index 4fa98dc..5e2a0e3 100644 --- a/source/js/search.js +++ b/source/js/search.js @@ -1,79 +1,77 @@ var Search = function(projectSlug, versionSlug, searchBoxSettings) { - var searchParameters = { - tagFilters: [], - hitsPerPage: 5 - }; + var searchParameters = { + tagFilters: [], + hitsPerPage: 5 + }; - if (projectSlug) { - searchParameters.tagFilters.push(projectSlug); + if (projectSlug) { + searchParameters.tagFilters.push(projectSlug); + } + + if (versionSlug) { + searchParameters.tagFilters.push(versionSlug); + } + + var search = instantsearch({ + appId: 'YVYTFT9XMW', + apiKey: 'a6dada5f33f148586b92cc3afefeaaf6', + indexName: 'pages', + autofocus: false, + poweredBy: false, + reset: false, + searchParameters: searchParameters, + searchFunction: function(helper) { + if (helper.state.query === '') { + $('.search-results').hide(); + $('.container-wrapper').css('opacity', '1'); + + return; + } + + helper.search(); + + $('.container-wrapper').css('opacity', '.25'); + $('.search-results').show(); } + }); - if (versionSlug) { - searchParameters.tagFilters.push(versionSlug); + search.addWidget(instantsearch.widgets.searchBox(searchBoxSettings)); + + search.addWidget( + instantsearch.widgets.hits({ + container: '#hits', + templates: { + empty: 'No results', + item: $('#instantsearch-template').html() + } + }) + ); + + search.start(); + + function getParameterByName(name, url) { + if (!url) url = window.location.href; + name = name.replace(/[\[\]]/g, '\\$&'); + var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), + results = regex.exec(url); + if (!results) return null; + if (!results[2]) return ''; + return decodeURIComponent(results[2].replace(/\+/g, ' ')); + } + + $('#search-box input').on('blur', function() { + setTimeout(function() { + $('.container-wrapper').css('opacity', '1'); + $('.search-results').hide(); + }, 200); + }); + + $(function() { + var q = getParameterByName('q', window.location.href); + + if (q) { + $('#search-box input').val(q); + search.helper.setQuery(q).search(); } - - var search = instantsearch({ - appId: 'YVYTFT9XMW', - apiKey: 'a6dada5f33f148586b92cc3afefeaaf6', - indexName: 'pages', - autofocus: false, - poweredBy: false, - reset: false, - searchParameters: searchParameters, - searchFunction: function(helper) { - if (helper.state.query === "") { - $('.search-results').hide(); - $('.container-wrapper').css('opacity', '1'); - - return; - } - - helper.search(); - - $('.container-wrapper').css('opacity', '.25'); - $('.search-results').show(); - } - }); - - search.addWidget( - instantsearch.widgets.searchBox(searchBoxSettings) - ); - - search.addWidget( - instantsearch.widgets.hits({ - container: '#hits', - templates: { - empty: 'No results', - item: $('#instantsearch-template').html() - } - }) - ); - - search.start(); - - function getParameterByName(name, url) { - if (!url) url = window.location.href; - name = name.replace(/[\[\]]/g, "\\$&"); - var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), - results = regex.exec(url); - if (!results) return null; - if (!results[2]) return ''; - return decodeURIComponent(results[2].replace(/\+/g, " ")); - }; - - $('#search-box input').on('blur', function() { - setTimeout(function() { - $('.container-wrapper').css('opacity', '1'); - $('.search-results').hide(); - }, 200); - }); - - $(function() { - var q = getParameterByName('q', window.location.href); - - if (q) { - $('#search-box input').val(q); - search.helper.setQuery(q).search(); - } - }); + }); }; diff --git a/source/js/sidebar.js b/source/js/sidebar.js index a322c94..84ea776 100644 --- a/source/js/sidebar.js +++ b/source/js/sidebar.js @@ -1,149 +1,164 @@ var Sidebar = function() { - this.loadCurrentDocsMenu(); - this.initVersionLinks(); + this.loadCurrentDocsMenu(); + this.initVersionLinks(); - $('[data-toggle="offcanvas"]').click(function () { - $('.row-offcanvas').toggleClass('active') - $('.sidebar').toggle(); - }); + $('[data-toggle="offcanvas"]').click(function() { + $('.row-offcanvas').toggleClass('active'); + $('.sidebar').toggle(); + }); - $('.toc-item').on('click', function() { - $('.toc-toggle').click(); - }); + $('.toc-item').on('click', function() { + $('.toc-toggle').click(); + }); - var self = this; + var self = this; - window.onhashchange = function() { - self.loadCurrentDocsMenu(); - self.initVersionLinks(); - }; + window.onhashchange = function() { + self.loadCurrentDocsMenu(); + self.initVersionLinks(); + }; }; Sidebar.prototype.initVersionLinks = function() { - $('.project-version-switcher').each(function() { - var linkUrl = $(this).attr('href').split('#')[0]; + $('.project-version-switcher').each(function() { + var linkUrl = $(this) + .attr('href') + .split('#')[0]; - $(this).attr('href', linkUrl + window.location.hash); - }); + $(this).attr('href', linkUrl + window.location.hash); + }); }; Sidebar.prototype.getTopLevelParent = function(elem) { - // scroll menu to element - var topLevelParent = elem.parent('ul').prev('li').parent('ul').prev('li'); + // scroll menu to element + var topLevelParent = elem + .parent('ul') + .prev('li') + .parent('ul') + .prev('li'); - if (!topLevelParent.length) { - topLevelParent = elem.parent('ul').prev('li'); - } + if (!topLevelParent.length) { + topLevelParent = elem.parent('ul').prev('li'); + } - if (!topLevelParent.length) { - topLevelParent = elem; - } + if (!topLevelParent.length) { + topLevelParent = elem; + } - return topLevelParent; + return topLevelParent; }; Sidebar.prototype.scrollToElement = function(elem) { - var topLevelParent = this.getTopLevelParent(elem); + var topLevelParent = this.getTopLevelParent(elem); - var topElem = document.getElementById(topLevelParent.attr('id')); + var topElem = document.getElementById(topLevelParent.attr('id')); - if (topElem) { - var offsetTop = topElem.offsetTop; + if (topElem) { + var offsetTop = topElem.offsetTop; - $('.sidebar-sticky').scrollTop(offsetTop); - } + $('.sidebar-sticky').scrollTop(offsetTop); + } }; Sidebar.prototype.removeQueryStringParameter = function(key, url) { - if (!url) url = window.location.href; + if (!url) url = window.location.href; - var hashParts = url.split('#'); + var hashParts = url.split('#'); - var regex = new RegExp("([?&])" + key + "=.*?(&|#|$)", "i"); + var regex = new RegExp('([?&])' + key + '=.*?(&|#|$)', 'i'); - if (hashParts[0].match(regex)) { - //REMOVE KEY AND VALUE - url = hashParts[0].replace(regex, '$1'); + if (hashParts[0].match(regex)) { + //REMOVE KEY AND VALUE + url = hashParts[0].replace(regex, '$1'); - //REMOVE TRAILING ? OR & - url = url.replace(/([?&])$/, ''); + //REMOVE TRAILING ? OR & + url = url.replace(/([?&])$/, ''); - //ADD HASH - if (typeof hashParts[1] !== 'undefined' && hashParts[1] !== null) - url += '#' + hashParts[1]; - } + //ADD HASH + if (typeof hashParts[1] !== 'undefined' && hashParts[1] !== null) + url += '#' + hashParts[1]; + } - return url; + return url; }; Sidebar.prototype.getCurrentDocsMenu = function() { - var currentUrl = this.removeQueryStringParameter('q', window.location.href); - var lastPart = currentUrl.substr(currentUrl.lastIndexOf('/') + 1); - var primaryHash = $('h1.section-header a').attr('href'); + var currentUrl = this.removeQueryStringParameter('q', window.location.href); + var lastPart = currentUrl.substr(currentUrl.lastIndexOf('/') + 1); + var primaryHash = $('h1.section-header a').attr('href'); - if (!lastPart) { - lastPart = 'index.html'; - } + if (!lastPart) { + lastPart = 'index.html'; + } - if (lastPart[0] === '#') { - lastPart = 'index.html' + lastPart; - } + if (lastPart[0] === '#') { + lastPart = 'index.html' + lastPart; + } - if (!window.location.hash) { - lastPart = lastPart + primaryHash; - } + if (!window.location.hash) { + lastPart = lastPart + primaryHash; + } - var id = this.normalize(lastPart); - var lastPartWithPrimaryHash = lastPart.substr(0, lastPart.lastIndexOf('#')) + primaryHash; - var idWithPrimaryHash = this.normalize(lastPartWithPrimaryHash); + var id = this.normalize(lastPart); + var lastPartWithPrimaryHash = + lastPart.substr(0, lastPart.lastIndexOf('#')) + primaryHash; + var idWithPrimaryHash = this.normalize(lastPartWithPrimaryHash); - // try the current link with the hash - var currentDocsMenu = $('#' + id); + // try the current link with the hash + var currentDocsMenu = $('#' + id); - // if we can't find it, open the primary menu item for this page - if (!currentDocsMenu.length) { - currentDocsMenu = $('#' + idWithPrimaryHash); - } + // if we can't find it, open the primary menu item for this page + if (!currentDocsMenu.length) { + currentDocsMenu = $('#' + idWithPrimaryHash); + } - return currentDocsMenu; + return currentDocsMenu; }; Sidebar.prototype.normalize = function(string) { - return string - .replaceAll('../', '') - .replaceAll('#', '-') - .replaceAll('.', '-') - .replaceAll('/', '-') - .replaceAll('_', '-') - ; + return string + .replaceAll('../', '') + .replaceAll('#', '-') + .replaceAll('.', '-') + .replaceAll('/', '-') + .replaceAll('_', '-'); }; Sidebar.prototype.closeAll = function() { - $('.opened').removeClass('opened'); - $('.opened-ul').removeClass('opened-ul'); + $('.opened').removeClass('opened'); + $('.opened-ul').removeClass('opened-ul'); }; Sidebar.prototype.openElement = function(elem) { - elem.addClass('opened'); + elem.addClass('opened'); - // top level clicked, open children - elem.next('ul').addClass('opened-ul').removeClass('closed-ul'); + // top level clicked, open children + elem + .next('ul') + .addClass('opened-ul') + .removeClass('closed-ul'); - // child clicked, open parents - elem.parents('ul').addClass('opened-ul').removeClass('closed-ul'); - elem.parents('ul').prev('li').addClass('opened'); + // child clicked, open parents + elem + .parents('ul') + .addClass('opened-ul') + .removeClass('closed-ul'); + elem + .parents('ul') + .prev('li') + .addClass('opened'); }; Sidebar.prototype.loadCurrentDocsMenu = function() { - var currentDocsMenu = this.getCurrentDocsMenu(); + var currentDocsMenu = this.getCurrentDocsMenu(); - if (!currentDocsMenu.length) { - return; - } + if (!currentDocsMenu.length) { + return; + } - this.closeAll(); + this.closeAll(); - this.openElement(currentDocsMenu); + this.openElement(currentDocsMenu); - this.scrollToElement(currentDocsMenu); + this.scrollToElement(currentDocsMenu); }; diff --git a/source/styles/_railscasts.scss b/source/styles/_railscasts.scss index 529987f..605d36f 100644 --- a/source/styles/_railscasts.scss +++ b/source/styles/_railscasts.scss @@ -44,7 +44,6 @@ color: #da4939; } - .hljs-symbol, .hljs-bullet, .hljs-built_in, @@ -103,4 +102,4 @@ .hljs-link { text-decoration: underline; -} \ No newline at end of file +} diff --git a/source/styles/index.scss b/source/styles/index.scss index 776f399..9369648 100644 --- a/source/styles/index.scss +++ b/source/styles/index.scss @@ -12,7 +12,12 @@ body > .container { margin-top: 20px; } -h1, h2, h3, h4, h5, h6 { +h1, +h2, +h3, +h4, +h5, +h6 { margin-bottom: 1rem; } @@ -53,7 +58,7 @@ h1, h2, h3, h4, h5, h6 { } .navbar { - background: linear-gradient(-90deg, #2C374C, #1F2E4B); + background: linear-gradient(-90deg, #2c374c, #1f2e4b); color: white; padding: 0 10px 0 10px; } @@ -84,7 +89,7 @@ h1, h2, h3, h4, h5, h6 { .sidebar-sticky .toc-section .toc-header { padding: 8px; font-size: 20px; - background-color: #1F2E4B; + background-color: #1f2e4b; margin-bottom: 0; color: #fff; } @@ -129,12 +134,12 @@ h1, h2, h3, h4, h5, h6 { .sidebar-sticky .toc ul ul li a { padding: 2px; - color: #FA6A3C; + color: #fa6a3c; } .sidebar-sticky .toc ul ul li.opened a { background: none; - color: #FA6A3C; + color: #fa6a3c; } /** 3rd Level */ @@ -164,7 +169,7 @@ button.copy-to-clipboard { pre { background-color: #232323; color: white; - padding: .5em; + padding: 0.5em; margin-bottom: 1rem; } @@ -189,14 +194,14 @@ div.console { div.console:before { background-color: #777; border-radius: 50%; - box-shadow: 0 0 0 2px #777,1.5em 0 0 2px #777,3em 0 0 2px #777; - content: ""; + box-shadow: 0 0 0 2px #777, 1.5em 0 0 2px #777, 3em 0 0 2px #777; + content: ''; display: block; - height: .5em; + height: 0.5em; left: 1em; position: absolute; top: -1.25em; - width: .5em; + width: 0.5em; } div.console span.noselect { @@ -269,7 +274,7 @@ em { } .bg-doctrine-orange { - background-color: #FA6A3C; + background-color: #fa6a3c; } .bg-doctrine-light-blue { @@ -277,7 +282,7 @@ em { } .bg-doctrine-dark-blue { - background-color: #1F2E4B; + background-color: #1f2e4b; } .footer { @@ -296,7 +301,7 @@ em { .section-header a i { margin-left: 5px; - color: #FA6A3C; + color: #fa6a3c; opacity: 0.7; font-size: 50%; vertical-align: middle; @@ -310,112 +315,98 @@ em { z-index: 99; border: none; outline: none; - background-color: #1F2E4B; + background-color: #1f2e4b; color: white; cursor: pointer; padding: 15px; border-radius: 10px; font-size: 18px; - box-shadow: 0 0 10px rgba(255, 255, 255, .5); + box-shadow: 0 0 10px rgba(255, 255, 255, 0.5); } #back-to-top:hover { background-color: #555; } -div.configuration-block ul.simple -{ +div.configuration-block ul.simple { margin: 0; padding: 0; } -div.configuration-block ul.simple li -{ +div.configuration-block ul.simple li { margin: 0 !important; margin-right: 5px !important; display: inline; margin-left: 10px; } -div.configuration-block em -{ +div.configuration-block em { margin-bottom: 10px; } -div.configuration-block li -{ +div.configuration-block li { padding: 5px; } -div.configuration-block em -{ +div.configuration-block em { font-style: normal; font-size: 90%; } -div.jsactive -{ +div.jsactive { position: relative; } -div.jsactive ul -{ +div.jsactive ul { list-style: none; } -div.jsactive li -{ +div.jsactive li { float: left; list-style: none; margin-left: 0; - -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; background-color: #ddd; margin-right: 5px; } -div.jsactive .selected -{ +div.jsactive .selected { background-color: #000; } -div.jsactive .selected a -{ +div.jsactive .selected a { color: #fff; text-decoration: none; } -div.jsactive .selected a:hover -{ +div.jsactive .selected a:hover { color: #fff; text-decoration: underline; } -div.jsactive a -{ +div.jsactive a { color: #000; text-decoration: none; } -div.jsactive a:hover -{ +div.jsactive a:hover { color: #000; text-decoration: underline; } -div.jsactive div -{ +div.jsactive div { position: absolute; top: 30px; left: 0; } -div.jsactive div div -{ +div.jsactive div div { position: static; } -div.jsactive pre -{ +div.jsactive pre { margin: 0; } @@ -429,7 +420,7 @@ div.jsactive pre border-radius: 3px; font-weight: 600; text-transform: uppercase; - letter-spacing: .3px; + letter-spacing: 0.3px; text-decoration: none; background-color: #002b36; color: white; @@ -520,9 +511,9 @@ div.jsactive pre @media screen and (max-width: 768px) { .row-offcanvas { position: relative; - -webkit-transition: all .25s ease-out; - -o-transition: all .25s ease-out; - transition: all .25s ease-out; + -webkit-transition: all 0.25s ease-out; + -o-transition: all 0.25s ease-out; + transition: all 0.25s ease-out; } .row-offcanvas-right { @@ -533,23 +524,19 @@ div.jsactive pre left: 0; } - .row-offcanvas-right - .sidebar-offcanvas { + .row-offcanvas-right .sidebar-offcanvas { right: -100%; /* 12 columns */ } - .row-offcanvas-right.active - .sidebar-offcanvas { + .row-offcanvas-right.active .sidebar-offcanvas { right: -80%; /* 6 columns */ } - .row-offcanvas-left - .sidebar-offcanvas { + .row-offcanvas-left .sidebar-offcanvas { left: -100%; /* 12 columns */ } - .row-offcanvas-left.active - .sidebar-offcanvas { + .row-offcanvas-left.active .sidebar-offcanvas { left: -80%; /* 6 columns */ } @@ -568,4 +555,4 @@ div.jsactive pre } } -@import 'railscasts'; \ No newline at end of file +@import 'railscasts'; diff --git a/yarn.lock b/yarn.lock index d4a9947..4ad66e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2731,6 +2731,11 @@ postcss@^6.0.1, postcss@^6.0.23: source-map "^0.6.1" supports-color "^5.4.0" +prettier@1.14.3: + version "1.14.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.3.tgz#90238dd4c0684b7edce5f83b0fb7328e48bd0895" + integrity sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg== + process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"