From 9f4129d5287235b1ac494740915c29a9fd8948e0 Mon Sep 17 00:00:00 2001 From: Sushain Cherivirala Date: Sat, 16 Dec 2017 16:20:33 -0500 Subject: [PATCH] Disentangle JS modules and fix Flow (fixes #80) * [WIP] Disentangle JS modules (#225) * Disentangle JS modules * Fix imports * Use flow on individual files * Declare modules to Flow * Run Flow directly * Cleanup * Fix some import/export issues * Make the build work * Tweak flow decl * Move around the config decl to make build work --- .circleci/config.yml | 3 +- .flowconfig | 2 +- Makefile | 12 +- assets/js/analyzer.js | 6 + assets/js/init.js | 181 +++++++++++++++ assets/js/translator.js | 28 ++- assets/js/util.js | 207 ++---------------- debug-head.html | 1 + .../js/flow.js => interfaces/config.js.flow | 4 +- 9 files changed, 232 insertions(+), 212 deletions(-) create mode 100644 assets/js/init.js rename assets/js/flow.js => interfaces/config.js.flow (95%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 62fea2b62..95d136980 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ jobs: # Install development dependencies - run: sudo apt-get install python3 python3-pip - - run: sudo npm install -g jsonlint eslint htmlhint sass-lint + - run: sudo npm install -g jsonlint eslint flow flow-bin htmlhint sass-lint - run: sudo pip3 install flake8 # Run tests @@ -17,6 +17,7 @@ jobs: - run: htmlhint --config .htmlhintrc.json *.html - run: sass-lint --config assets/css/.sass-lint.yml --verbose --no-exit --max-warnings 0 - run: flake8 --config tools/.flake8.ini *.py **/**.py **/**/*.py + - run: flow check # Build project - run: cp config.conf.example config.conf diff --git a/.flowconfig b/.flowconfig index 28eb81569..d5f5265f9 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,5 +1,5 @@ [ignore] -build/ +.*/build/.* [include] diff --git a/Makefile b/Makefile index 59be3f5dc..988e3f9e0 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ debug: debugjs debugcss build/index.debug.html build/not-found.html fonts build/ prod: js css html fonts build/sitemap.xml build/manifest.json build/strings/locales.json localhtml images js: build/js/min.js build/js/compat.js build/js/jquery.min.js build/js/bootstrap.min.js debugjs -debugjs: build/js/jquery.jsonp-2.4.0.min.js build/js/config.js build/js/util.js build/js/store.js build/js/persistence.js build/js/localization.js build/js/translator.js build/js/analyzer.js build/js/generator.js build/js/sandbox.js +debugjs: build/js/jquery.jsonp-2.4.0.min.js build/js/config.js build/js/util.js build/js/init.js build/js/store.js build/js/persistence.js build/js/localization.js build/js/translator.js build/js/analyzer.js build/js/generator.js build/js/sandbox.js css: build/css/min.css build/css/font-awesome.min.css build/css/bootstrap-rtl.min.css debugcss debugcss: build/css/bootstrap.css build/css/style.css html: build/index.html build/index.debug.html build/not-found.html @@ -31,12 +31,12 @@ check-deps: ### JS ### JSFILES= \ assets/js/strict.js \ - assets/js/flow.js \ assets/js/jquery.jsonp-2.4.0.min.js \ build/js/config.js \ build/js/locales.js \ build/js/listrequests.js \ assets/js/util.js \ + assets/js/init.js \ assets/js/store.js \ assets/js/persistence.js \ assets/js/localization.js \ @@ -102,7 +102,7 @@ build/js/%.js: assets/js/%.js build/js/.d ### MANIFEST ### build/manifest.json: assets/manifest.json build/.d cp $< $@ - + ### HTML ### build/index.debug.html: index.html.in debug-head.html build/l10n-rel.html build/.PIWIK_URL build/.PIWIK_SITEID build/strings/eng.json $(CONFIG) tools/read-conf.py tools/localise-html.py build/.d sed -e '/@include_head@/r debug-head.html' -e '/@include_head@/r build/l10n-rel.html' -e '/@include_head@/d' -e "s%@include_piwik_url@%$(shell cat build/.PIWIK_URL)%" -e "s%@include_piwik_siteid@%$(shell cat build/.PIWIK_SITEID)%" $< > $@ @@ -226,10 +226,6 @@ build/img/%: assets/img/% images: $(IMAGES_BUILD) -### Typechecking ### -# grab the bin from /~https://github.com/facebook/flow/releases -flow: build/js/all.js - grep -Ev '/\*:: *(ex|im)port ' $< | flow check-contents ### Test server ### server: @@ -240,4 +236,4 @@ server: ### Clean ### clean: rm -rf build/ - \ No newline at end of file + diff --git a/assets/js/analyzer.js b/assets/js/analyzer.js index 0542eb711..3efe268fa 100644 --- a/assets/js/analyzer.js +++ b/assets/js/analyzer.js @@ -240,3 +240,9 @@ function formatUnit(unit) { function handleAnalyzeErrorResponse(xOptions, error) { $('#morphAnalyzerOutput').text(error).removeClass('blurred'); } + +/*:: import {config} from "./config.js" */ +/*:: import {modeEnabled, ajaxSend, ajaxComplete, filterLangList, allowedLang, sendEvent, callApy, apyRequestTimeout} from "./util.js" */ +/*:: import {ENTER_KEY_CODE} from "./util.js" */ +/*:: import {localizeInterface, getLangByCode} from "./localization.js" */ +/*:: import {persistChoices, restoreChoices, readCache, cache} from "./persistence.js" */ diff --git a/assets/js/init.js b/assets/js/init.js new file mode 100644 index 000000000..6cb0ab129 --- /dev/null +++ b/assets/js/init.js @@ -0,0 +1,181 @@ +/* global config, persistChoices, iso639Codes, iso639CodesInverse, populateTranslationList, showTranslateWebpageInterface */ +/* global ajaxSend, ajaxComplete, debounce, resizeFooter, synchronizeTextareaHeights */ + +var BACK_TO_TOP_BUTTON_ACTIVATION_HEIGHT = 300; + +$(document).ajaxSend(ajaxSend); +$(document).ajaxComplete(ajaxComplete); +$(document).ajaxError(ajaxComplete); + +$.jsonp.setup({ + callbackParameter: 'callback' +}); + +$(document).ready(function () { + $('#noscript').hide(); + $('.navbar').css('margin-top', '0px'); + $('body > .container').css('margin-top', '0px'); + + if(config.SUBTITLE) { + $('.apertiumSubLogo') + .text(config.SUBTITLE) + .show(); + if(config.SUBTITLE_COLOR) { + $('.apertiumSubLogo').css('color', config.SUBTITLE_COLOR); + } + } + else { + $('.apertiumSubLogo').hide(); + } + + if(config.SHOW_NAVBAR) { + if(config.ENABLED_MODES === null) { + $('.nav a').removeClass('hide'); + } + else { + $.each(config.ENABLED_MODES, function () { + $('.nav a[data-mode=' + this + ']').removeClass('hide'); + }); + } + } + else { + $('.navbar-default .navbar-toggle').hide(); + $('.navbar-default .nav').hide(); + } + + var hash = parent.location.hash; + + try { + if(!hash || !$(hash + 'Container')) { + hash = '#' + config.DEFAULT_MODE; + parent.location.hash = hash; + } + } + catch(e) { + console.error('Invalid hash: ' + e); + hash = '#' + config.DEFAULT_MODE; + parent.location.hash = hash; + } + + try { + if(hash === '#webpageTranslation') { + hash = '#translation'; + showTranslateWebpageInterface(); + } + else if(!hash || !$(hash + 'Container').length) { + hash = '#' + config.DEFAULT_MODE; + parent.location.hash = hash; + } + } + catch(e) { + console.error('Invalid hash: ' + e); + hash = '#' + config.DEFAULT_MODE; + parent.location.hash = hash; + } + + $('.modeContainer' + hash + 'Container').show(); + $('.navbar-default .nav li > a[data-mode=' + hash.substring(1) + ']').parent().addClass('active'); + + $('.navbar-default .nav a').click(function () { + var mode = $(this).data('mode'); + $('.nav li').removeClass('active'); + $(this).parent('li').addClass('active'); + $('.modeContainer:not(#' + mode + 'Container)').stop().hide({ + queue: false + }); + $('#' + mode + 'Container').stop().show({ + queue: false + }); + synchronizeTextareaHeights(); + }); + + resizeFooter(); + $(window) + .on('hashchange', persistChoices) + .resize(debounce(function () { + populateTranslationList(); + resizeFooter(); + })); + + if(config.ALLOWED_LANGS) { + var withIso = []; + $.each(config.ALLOWED_LANGS, function () { + if(iso639Codes[this]) { + withIso.push(iso639Codes[this]); + } + if(iso639CodesInverse[this]) { + withIso.push(iso639CodesInverse[this]); + } + }); + Array.prototype.push.apply(config.ALLOWED_LANGS, withIso); + } + + $('form').submit(function () { + return false; + }); + + $('.modal').on('show.bs.modal', function () { + $('a[data-target=#' + $(this).attr('id') + ']').parents('li').addClass('active'); + $.each($(this).find('img[data-src]'), function () { + $(this).attr('src', $(this).attr('data-src')); + }); + }); + + $('.modal').on('hide.bs.modal', function () { + $('a[data-target=#' + $(this).attr('id') + ']').parents('li').removeClass('active'); + }); + + $('#backToTop').addClass('hide'); + $(window).scroll(function () { + $('#backToTop').toggleClass('hide', $(window).scrollTop() < BACK_TO_TOP_BUTTON_ACTIVATION_HEIGHT); + }); + + $('#backToTop').click(function () { + $('html, body').animate({ + scrollTop: 0 + }, 'fast'); + return false; + }); + + $('#installationNotice').addClass('hide'); +}); + +if(config.PIWIK_SITEID && config.PIWIK_URL) { + var url = config.PIWIK_URL; + if(document.location.protocol === 'https:') { + url = url.replace(/^(http(s)?)?:/, 'https:'); + } + // but if we're on plain http, we keep whatever was in the config + if(url.charAt(url.length - 1) !== '/') { + url += '/'; + } + + /* eslint-disable */ + var _paq = _paq || []; + _paq.push(['trackPageView']); + _paq.push(['enableLinkTracking']); + (function() { + var u=url; + _paq = _paq || []; + _paq.push(['setTrackerUrl', u+'piwik.php']); + _paq.push(['setSiteId', config.PIWIK_SITEID]); + var d=document, + g=d.createElement('script'), + s=d.getElementsByTagName('script')[0]; + g.type='text/javascript'; + g.defer=true; + g.async=true; + g.src=u+'piwik.js'; + if(s.parentNode) { + s.parentNode.insertBefore(g,s); + } + })(); + /* eslint-enable */ +} + +/*:: export {_paq} */ +/*:: import {config} from "./config.js" */ +/*:: import {persistChoices} from "./persistence.js" */ +/*:: import {iso639Codes, iso639CodesInverse} from "./localization.js" */ +/*:: import {populateTranslationList, showTranslateWebpageInterface} from "./translator.js" */ +/*:: import {ajaxSend, ajaxComplete, debounce, resizeFooter, synchronizeTextareaHeights} from "./util.js" */ diff --git a/assets/js/translator.js b/assets/js/translator.js index d137f30f7..5e63087b6 100644 --- a/assets/js/translator.js +++ b/assets/js/translator.js @@ -1,9 +1,9 @@ -/* @flow */ +// @flow var pairs = {}, chainedPairs = {}, originalPairs = pairs; var srcLangs = [], dstLangs = []; -var curSrcLang, curDstLang; -var recentSrcLangs = [], recentDstLangs = []; +var curSrcLang/*: string */, curDstLang/*: string */; +var recentSrcLangs /*: string[] */ = [], recentDstLangs /*: string[] */ = []; var droppedFile; var translateRequest; @@ -24,7 +24,7 @@ var PUNCTUATION_KEY_CODES = [46, 33, 58, 63, 47, 45, 190, 171, 49]; // eslint-di /* global config, modeEnabled, synchronizeTextareaHeights, persistChoices, getLangByCode, sendEvent, onlyUnique, restoreChoices getDynamicLocalization, locale, ajaxSend, ajaxComplete, localizeInterface, filterLangList, cache, readCache, iso639Codes, callApy, apyRequestTimeout, isURL */ -/* global SPACE_KEY_CODE, ENTER_KEY_CODE, HTTP_OK_CODE, XHR_LOADING, XHR_DONE, HTTP_OK_CODE, HTTP_BAD_REQUEST_CODE */ +/* global SPACE_KEY_CODE, ENTER_KEY_CODE, HTTP_OK_CODE, XHR_LOADING, XHR_DONE, HTTP_BAD_REQUEST_CODE */ if(modeEnabled('translation')) { $(document).ready(function () { @@ -421,7 +421,9 @@ function getPairs() { break; } for(var i = 0; i < TRANSLATION_LIST_BUTTONS; i++) { + // $FlowFixMe recentSrcLangs.push(i < srcLangs.length ? srcLangs[i] : undefined); + // $FlowFixMe recentDstLangs.push(i < dstLangs.length ? dstLangs[i] : undefined); } @@ -674,7 +676,9 @@ function translateText(ignoreIfEmpty) { request = {'langpair': curSrcLang + '|' + curDstLang}; } + // $FlowFixMe request.q = originalText; // eslint-disable-line id-length + // $FlowFixMe request.markUnknown = $('#markUnknown').prop('checked') ? 'yes' : 'no'; translateRequest = callApy({ data: request, @@ -725,6 +729,7 @@ function translateDoc() { $('input#fileInput').prop('disabled', true); $('button#translate').prop('disabled', true); + // $FlowFixMe var xhr = new XMLHttpRequest({mozSystem: true}); xhr.addEventListener('progress', updateProgressBar, false); if(xhr.upload) { @@ -758,6 +763,7 @@ function translateDoc() { reader.onload = function () { $('a#fileDownload') .click(function () { + // $FlowFixMe window.location.href = reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;'); }); }; @@ -803,7 +809,7 @@ function translateDoc() { docTranslateError(getDynamicLocalization('Not_Available')); } - function updateProgressBar(ev) { + function updateProgressBar(ev /*: ProgressEvent | any */) { var progress = 0.0; if(ev instanceof ProgressEvent) { progress = ev.loaded / ev.total; @@ -934,7 +940,7 @@ function translateWebpage(ignoreIfEmpty) { } } -function showTranslateWebpageInterface(url, ignoreIfEmpty) { +function showTranslateWebpageInterface(url /*: ?string */, ignoreIfEmpty /*: ?boolean */) { $('#srcLangSelectors').removeClass('col-sm-11').addClass('col-sm-9'); $('div#translateText').fadeOut('fast', function () { @@ -1074,10 +1080,10 @@ function autoSelectDstLang() { } } -/*:: import {synchronizeTextareaHeights, modeEnabled, ajaxSend, ajaxComplete, filterLangList, onlyUnique, getLangByCode, - callApy, apyRequestTimeout} from "./util.js" */ +/*:: export {populateTranslationList, showTranslateWebpageInterface} */ +/*:: import {synchronizeTextareaHeights, modeEnabled, ajaxSend, ajaxComplete, filterLangList, onlyUnique, sendEvent, callApy, + apyRequestTimeout, SPACE_KEY_CODE, ENTER_KEY_CODE, HTTP_OK_CODE, XHR_LOADING, XHR_DONE, HTTP_BAD_REQUEST_CODE} from "./util.js" */ /*:: import {persistChoices, restoreChoices} from "./persistence.js" */ -/*:: import localizeInterface from "./localization.js" */ -/*:: import {readCache,cache} from "./cache.js" */ -/*:: import {config} from "./config.js" */ +/*:: import {localizeInterface, getLangByCode, getDynamicLocalization, locale, iso639Codes} from "./localization.js" */ +/*:: import {readCache, cache} from "./persistence.js" */ /*:: import {isURL} from "./util.js" */ diff --git a/assets/js/util.js b/assets/js/util.js index af135608f..779d74580 100644 --- a/assets/js/util.js +++ b/assets/js/util.js @@ -1,14 +1,15 @@ -/* @flow */ -/* exported sendEvent, modeEnabled, filterLangList, getURLParam, onlyUnique, isSubset, safeRetrieve, callApy, apyRequestTimeout, isURL */ +// @flow + +/* exported debounce, ajaxComplete, sendEvent, modeEnabled, resizeFooter, filterLangList, getURLParam, onlyUnique, isSubset */ +/* exported synchronizeTextareaHeights, callApy, apyRequestTimeout, isURL */ /* exported SPACE_KEY_CODE, ENTER_KEY_CODE, HTTP_OK_CODE, HTTP_BAD_REQUEST_CODE, XHR_LOADING, XHR_DONE */ -/* global config, persistChoices, iso639Codes, iso639CodesInverse, populateTranslationList, showTranslateWebpageInterface */ +/* global _paq, config */ var SPACE_KEY_CODE = 32, ENTER_KEY_CODE = 13, HTTP_OK_CODE = 200, HTTP_BAD_REQUEST_CODE = 400, XHR_LOADING = 3, XHR_DONE = 4; var TEXTAREA_AUTO_RESIZE_MINIMUM_WIDTH = 768, - BACK_TO_TOP_BUTTON_ACTIVATION_HEIGHT = 300, APY_REQUEST_URL_THRESHOLD_LENGTH = 2000, // maintain 48 characters buffer for generated parameters DEFAULT_DEBOUNCE_DELAY = 100; @@ -22,6 +23,7 @@ var apyRequestTimeout, apyRequestStartTime, installationNotificationShown = fals // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill /* eslint-disable */ if (typeof Object.assign != 'function') { + // $FlowFixMe Object.assign = function(target, varArgs) { // .length of function is 2 'use strict'; if (target == null) { // TypeError if undefined or null @@ -47,7 +49,7 @@ if (typeof Object.assign != 'function') { } /* eslint-enable */ -function debounce(func, delay) { // eslint-disable-line no-unused-vars +function debounce(func /*: any */, delay /*: number */) { // eslint-disable-line no-unused-vars var clock = null; return function () { var context = this, args = arguments; @@ -71,178 +73,8 @@ function ajaxComplete() { } } -$(document).ajaxSend(ajaxSend); -$(document).ajaxComplete(ajaxComplete); -$(document).ajaxError(ajaxComplete); - -$.jsonp.setup({ - callbackParameter: 'callback' -}); - -$(document).ready(function () { - $('#noscript').hide(); - $('.navbar').css('margin-top', '0px'); - $('body > .container').css('margin-top', '0px'); - - if(config.SUBTITLE) { - $('.apertiumSubLogo') - .text(config.SUBTITLE) - .show(); - if(config.SUBTITLE_COLOR) { - $('.apertiumSubLogo').css('color', config.SUBTITLE_COLOR); - } - } - else { - $('.apertiumSubLogo').hide(); - } - - if(config.SHOW_NAVBAR) { - if(config.ENABLED_MODES === null) { - $('.nav a').removeClass('hide'); - } - else { - $.each(config.ENABLED_MODES, function () { - $('.nav a[data-mode=' + this + ']').removeClass('hide'); - }); - } - } - else { - $('.navbar-default .navbar-toggle').hide(); - $('.navbar-default .nav').hide(); - } - - var hash = parent.location.hash; - - try { - if(!hash || !$(hash + 'Container')) { - hash = '#' + config.DEFAULT_MODE; - parent.location.hash = hash; - } - } - catch(e) { - console.error('Invalid hash: ' + e); - hash = '#' + config.DEFAULT_MODE; - parent.location.hash = hash; - } - - try { - if(hash === '#webpageTranslation') { - hash = '#translation'; - showTranslateWebpageInterface(); - } - else if(!hash || !$(hash + 'Container').length) { - hash = '#' + config.DEFAULT_MODE; - parent.location.hash = hash; - } - } - catch(e) { - console.error('Invalid hash: ' + e); - hash = '#' + config.DEFAULT_MODE; - parent.location.hash = hash; - } - - $('.modeContainer' + hash + 'Container').show(); - $('.navbar-default .nav li > a[data-mode=' + hash.substring(1) + ']').parent().addClass('active'); - - $('.navbar-default .nav a').click(function () { - var mode = $(this).data('mode'); - $('.nav li').removeClass('active'); - $(this).parent('li').addClass('active'); - $('.modeContainer:not(#' + mode + 'Container)').stop().hide({ - queue: false - }); - $('#' + mode + 'Container').stop().show({ - queue: false - }); - synchronizeTextareaHeights(); - }); - - resizeFooter(); - $(window) - .on('hashchange', persistChoices) - .resize(debounce(function () { - populateTranslationList(); - resizeFooter(); - })); - - if(config.ALLOWED_LANGS) { - var withIso = []; - $.each(config.ALLOWED_LANGS, function () { - if(iso639Codes[this]) { - withIso.push(iso639Codes[this]); - } - if(iso639CodesInverse[this]) { - withIso.push(iso639CodesInverse[this]); - } - }); - Array.prototype.push.apply(config.ALLOWED_LANGS, withIso); - } - - $('form').submit(function () { - return false; - }); - - $('.modal').on('show.bs.modal', function () { - $('a[data-target=#' + $(this).attr('id') + ']').parents('li').addClass('active'); - $.each($(this).find('img[data-src]'), function () { - $(this).attr('src', $(this).attr('data-src')); - }); - }); - - $('.modal').on('hide.bs.modal', function () { - $('a[data-target=#' + $(this).attr('id') + ']').parents('li').removeClass('active'); - }); - - $('#backToTop').addClass('hide'); - $(window).scroll(function () { - $('#backToTop').toggleClass('hide', $(window).scrollTop() < BACK_TO_TOP_BUTTON_ACTIVATION_HEIGHT); - }); - - $('#backToTop').click(function () { - $('html, body').animate({ - scrollTop: 0 - }, 'fast'); - return false; - }); - - $('#installationNotice').addClass('hide'); -}); - -if(config.PIWIK_SITEID && config.PIWIK_URL) { - var url = config.PIWIK_URL; - if(document.location.protocol === 'https:') { - url = url.replace(/^(http(s)?)?:/, 'https:'); - } - // but if we're on plain http, we keep whatever was in the config - if(url.charAt(url.length - 1) !== '/') { - url += '/'; - } - - /* eslint-disable */ - var _paq = _paq || []; - _paq.push(['trackPageView']); - _paq.push(['enableLinkTracking']); - (function() { - var u=url; - _paq = _paq || []; - _paq.push(['setTrackerUrl', u+'piwik.php']); - _paq.push(['setSiteId', config.PIWIK_SITEID]); - var d=document, - g=d.createElement('script'), - s=d.getElementsByTagName('script')[0]; - g.type='text/javascript'; - g.defer=true; - g.async=true; - g.src=u+'piwik.js'; - if(s.parentNode) { - s.parentNode.insertBefore(g,s); - } - })(); - /* eslint-enable */ -} - /* eslint-disable id-blacklist */ -function sendEvent(category, action, label, value) { +function sendEvent(category /*: string */, action /*: string */, label /*: ?string */, value /*: any */) { if(config.PIWIK_SITEID && config.PIWIK_URL && _paq) { var args = [category, action]; if(label !== undefined && value !== undefined) { @@ -257,7 +89,7 @@ function sendEvent(category, action, label, value) { } /* eslint-enable id-blacklist */ -function modeEnabled(mode/*: string*/) { +function modeEnabled(mode /*: string*/) { return config.ENABLED_MODES === null || config.ENABLED_MODES.indexOf(mode) !== -1; } @@ -277,7 +109,7 @@ function allowedLang(code) { } } -function filterLangList(langs/*: Array*/, _filterFn/*: (lang: string) => bool*/) { +function filterLangList(langs /*: Array*/, _filterFn /*: ?(lang: string) => bool*/) { if(config.ALLOWED_LANGS === null && config.ALLOWED_VARIANTS === null) { return langs; } @@ -304,18 +136,18 @@ function getURLParam(name) { /* eslint-disable */ // From: http://stackoverflow.com/a/19696443/1266600 (source: AOSP) -function isURL(text) { +function isURL(text /*: string */) { var re = /^((?:(http|https):\/\/(?:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,64}(?:\:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,25})?\@)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}\.)+(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\:\d{1,5})?)(\/(?:(?:[a-zA-Z0-9\;\/\?\:\@\&\=\#\~\-\.\+\!\*\'\(\)\,\_])|(?:\%[a-fA-F0-9]{2}))*)?(?:\s*$)/i; return text.search(re) === 0; } /* eslint-enable */ // eslint-disable-next-line id-blacklist -function onlyUnique(value, index, self) { +function onlyUnique(value /*: any */, index /*: any */, self /*: any */) { return self.indexOf(value) === index; } -function isSubset(subset, superset) { +function isSubset/*:: */(subset /*: T[] */, superset /*: T[] */) { // eslint-disable-next-line id-blacklist, id-length return subset.every(function (val) { return superset.indexOf(val) >= 0; @@ -336,7 +168,7 @@ function synchronizeTextareaHeights() { $('#translatedText').css('height', originalTextScrollHeight + 'px'); } -function callApy(options, endpoint, useAjax) { +function callApy(options /*: any */, endpoint /*: any */, useAjax /*: any */) { var requestOptions = Object.assign({ url: config.APY_URL + endpoint, beforeSend: ajaxSend, @@ -362,7 +194,7 @@ function callApy(options, endpoint, useAjax) { } function handleAPyRequestCompletion(requestDuration) { - var cumulativeAPyRequestDuration; + var cumulativeAPyRequestDuration = 0; if(lastNAPyRequestDurations.length === INSTALLATION_NOTIFICATION_REQUESTS_BUFFER_LENGTH) { cumulativeAPyRequestDuration = lastNAPyRequestDurations.reduce(function (totalDuration, duration) { @@ -407,9 +239,6 @@ function displayInstallationNotification() { } } -/*:: export {synchronizeTextareaHeights, modeEnabled, ajaxSend, ajaxComplete, filterLangList, onlyUnique, callApy, - SPACE_KEY_CODE, ENTER_KEY_CODE, HTTP_OK_CODE, HTTP_BAD_REQUEST_CODE, XHR_LOADING, XHR_DONE, apyRequestTimeout} */ -/*:: import {config} from "./config.js" */ -/*:: import {persistChoices} from "./persistence.js" */ -/*:: import {iso639Codes, iso639CodesInverse} from "./localization.js" */ -/*:: import {populateTranslationList, showTranslateWebpageInterface} from "./translator.js" */ +/*:: export {debounce, synchronizeTextareaHeights, modeEnabled, resizeFooter, ajaxSend, ajaxComplete, filterLangList, onlyUnique, callApy, + SPACE_KEY_CODE, ENTER_KEY_CODE, HTTP_OK_CODE, HTTP_BAD_REQUEST_CODE, XHR_LOADING, XHR_DONE, apyRequestTimeout, isURL, sendEvent} */ +/*:: import {_paq} from "./init.js" */ diff --git a/debug-head.html b/debug-head.html index 324e970df..fa3a4668c 100644 --- a/debug-head.html +++ b/debug-head.html @@ -3,6 +3,7 @@ + diff --git a/assets/js/flow.js b/interfaces/config.js.flow similarity index 95% rename from assets/js/flow.js rename to interfaces/config.js.flow index 0abfee452..22e51a34a 100644 --- a/assets/js/flow.js +++ b/interfaces/config.js.flow @@ -1,4 +1,4 @@ -/* :: declare var config: { +declare var config: { ALLOWED_LANGS:any, ALLOWED_PAIRS:any, LIST_REQUEST_CACHE_EXPIRY: number, @@ -20,4 +20,4 @@ GENERATORS: {}|null, ANALYZERS: {}|null, TAGGERS: {}|null -} */ +};