j1-template 2022.0.2 → 2022.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/_includes/themes/j1/modules/connectors/analytic/google-analytics.html +3 -13
  3. data/_includes/themes/j1/modules/connectors/comment/hyvor.html +4 -5
  4. data/_includes/themes/j1/procedures/global/create_bs_button.proc +4 -4
  5. data/assets/data/private.json +1 -5
  6. data/assets/themes/j1/adapter/js/cookieConsent.js +12 -9
  7. data/assets/themes/j1/adapter/js/j1.js +17 -17
  8. data/assets/themes/j1/adapter/js/translator.js +4 -2
  9. data/assets/themes/j1/core/js/template.js +59 -0
  10. data/assets/themes/j1/core/js/template.min.js +5 -5
  11. data/assets/themes/j1/core/js/template.min.js.map +1 -1
  12. data/assets/themes/j1/modules/cryptoJS/js/aes.js +35 -0
  13. data/assets/themes/j1/modules/cryptoJS/js/aes.min.js +35 -0
  14. data/assets/themes/j1/modules/cryptoJS/js/hmac-md5.js +21 -0
  15. data/assets/themes/j1/modules/cryptoJS/js/hmac-ripemd160.js +31 -0
  16. data/assets/themes/j1/modules/cryptoJS/js/hmac-sha1.js +17 -0
  17. data/assets/themes/j1/modules/cryptoJS/js/hmac-sha224.js +19 -0
  18. data/assets/themes/j1/modules/cryptoJS/js/hmac-sha256.js +18 -0
  19. data/assets/themes/j1/modules/cryptoJS/js/hmac-sha3.js +21 -0
  20. data/assets/themes/j1/modules/cryptoJS/js/hmac-sha384.js +27 -0
  21. data/assets/themes/j1/modules/cryptoJS/js/hmac-sha512.js +25 -0
  22. data/assets/themes/j1/modules/cryptoJS/js/md5.js +19 -0
  23. data/assets/themes/j1/modules/cryptoJS/js/pbkdf2.js +19 -0
  24. data/assets/themes/j1/modules/cryptoJS/js/rabbit-legacy.js +36 -0
  25. data/assets/themes/j1/modules/cryptoJS/js/rabbit.js +36 -0
  26. data/assets/themes/j1/modules/cryptoJS/js/rc4.js +33 -0
  27. data/assets/themes/j1/modules/cryptoJS/js/ripemd160.js +29 -0
  28. data/assets/themes/j1/modules/cryptoJS/js/sha1.js +15 -0
  29. data/assets/themes/j1/modules/cryptoJS/js/sha224.js +17 -0
  30. data/assets/themes/j1/modules/cryptoJS/js/sha256.js +16 -0
  31. data/assets/themes/j1/modules/cryptoJS/js/sha3.js +19 -0
  32. data/assets/themes/j1/modules/cryptoJS/js/sha384.js +25 -0
  33. data/assets/themes/j1/modules/cryptoJS/js/sha512.js +23 -0
  34. data/assets/themes/j1/modules/cryptoJS/js/tripledes.js +51 -0
  35. data/assets/themes/j1/modules/deeplAPI/js/deeplAPI.2.js +460 -0
  36. data/assets/themes/j1/modules/deeplAPI/js/deeplAPI.js +379 -353
  37. data/assets/themes/j1/modules/deeplAPI/js/deeplAPI.min.js +1 -1
  38. data/assets/themes/j1/modules/gtag-opt-in/js/gtag-opt-in.js +93 -1
  39. data/assets/themes/j1/modules/scroller/js/scroller.js +6 -6
  40. data/assets/themes/j1/modules/scroller/js/scroller.min.js +1 -1
  41. data/exe/j1 +6 -7
  42. data/lib/j1/commands/generate.rb +15 -16
  43. data/lib/j1/version.rb +1 -1
  44. data/lib/starter_web/Gemfile +7 -1
  45. data/lib/starter_web/_config.yml +1 -1
  46. data/lib/starter_web/_data/_defaults/private.yml +3 -2
  47. data/lib/starter_web/_data/builder/defaults/_blog_navigator.yml +396 -0
  48. data/lib/starter_web/_data/builder/defaults/blog_navigator.yml +48 -42
  49. data/lib/starter_web/_data/modules/translator.yml +3 -3
  50. data/lib/starter_web/_data/private.yml +3 -2
  51. data/lib/starter_web/_data/resources.yml +27 -2
  52. data/lib/starter_web/_includes/attributes.asciidoc +1 -1
  53. data/lib/starter_web/_plugins/encodeBase64.rb +46 -0
  54. data/lib/starter_web/_plugins/encryptAES.rb +53 -0
  55. data/lib/starter_web/_plugins/filters.rb +2 -1
  56. data/lib/starter_web/_plugins/lunr_index.rb +1 -1
  57. data/lib/starter_web/_plugins/minifyJSON.rb +2 -2
  58. data/lib/starter_web/package.json +1 -1
  59. data/lib/starter_web/pages/public/asciidoc_skeletons/documentation/documentation.adoc +1 -1
  60. data/lib/starter_web/pages/public/asciidoc_skeletons/multi-document/multi.adoc +1 -1
  61. data/lib/starter_web/pages/public/asciidoc_skeletons/simple-document/simple.adoc +1 -1
  62. data/lib/starter_web/pages/public/blog/navigator/archive/categoryview.html +0 -21
  63. data/lib/starter_web/pages/public/blog/navigator/archive/dateview.html +1 -1
  64. data/lib/starter_web/pages/public/blog/navigator/archive/tagview.html +1 -0
  65. data/lib/starter_web/pages/public/blog/navigator/archive.html +1 -1
  66. data/lib/starter_web/pages/public/learn/quickstart.adoc +1 -1
  67. data/lib/starter_web/pages/public/learn/where_to_go.adoc +1 -1
  68. data/lib/starter_web/pages/public/legal/de/100_copyright.adoc +1 -1
  69. data/lib/starter_web/pages/public/legal/de/100_impress.adoc +1 -1
  70. data/lib/starter_web/pages/public/legal/de/300_privacy.adoc +1 -1
  71. data/lib/starter_web/pages/public/legal/de/400_comment_policy.adoc +1 -1
  72. data/lib/starter_web/pages/public/legal/en/100_copyright.adoc +1 -1
  73. data/lib/starter_web/pages/public/legal/en/200_impress.adoc +1 -1
  74. data/lib/starter_web/pages/public/legal/en/300_privacy.adoc +1 -1
  75. data/lib/starter_web/pages/public/legal/en/400_comment_policy.adoc +1 -1
  76. data/lib/starter_web/utilsrv/_defaults/package.json +1 -1
  77. data/lib/starter_web/utilsrv/package.json +1 -1
  78. metadata +30 -5
  79. data/lib/j1/commands/help.rb +0 -32
  80. data/lib/j1/commands/module.rb +0 -69
@@ -0,0 +1,460 @@
1
+ /*
2
+ # -----------------------------------------------------------------------------
3
+ # ~/assets/themes/j1/modules/deeplAPI/js/deeplAPI.js
4
+ # J1 core module for deeplAPI
5
+ #
6
+ # Product/Info:
7
+ # https://jekyll.one
8
+ #
9
+ # Copyright (C) 2021 Juergen Adams
10
+ #
11
+ # J1 Template is licensed under the MIT License.
12
+ # For details, see https://jekyll.one
13
+ # -----------------------------------------------------------------------------
14
+ # NOTE: Based on https://github.com/jquery-boilerplate/jquery-boilerplate
15
+ # See: https://www.dotnetcurry.com/jquery/1069/authoring-jquery-plugins
16
+ # -----------------------------------------------------------------------------
17
+ */
18
+
19
+ // the semi-colon before function invocation is a SAFETY method against
20
+ // concatenated scripts and/or other plugins which may NOT be closed
21
+ // properly.
22
+ //
23
+ ;(function($, window, document, undefined) {
24
+
25
+ 'use strict';
26
+
27
+ // Create the defaults
28
+ var pluginName = 'deeplAPI',
29
+ defaults = {
30
+ api: 'free', // free (default) | pro
31
+ auth_key: '', // API authorization key
32
+ source_lang: 'auto', // autodetection (default: auto)|supported language. Specifies the language for the input text.
33
+ target_lang: 'DE', // language to be tranlasted in.
34
+ max_chars: false, // false (unlimited) or number. Number of chars from the source text passed for translation.
35
+ split_sentences: '1', // enabled (1, default)|disabled (0)|nonewlines. Sets the translation engine to first split the input text into sentences.
36
+ preserve_formatting: '0', // disabled (0, default)|enabled (1). Sets the translation engine to respect the original formatting.
37
+ formality: 'default', // default|more|less. Sets the translated text should lean towards formal or informal language.
38
+ tag_handling: false, // false (value=0)|xml. Sets which kind of tags should be handled. If set, API is able to process structured XML content.
39
+ outline_detection: true, // false (value=0) or true (NO value passed). Controls the automatic mechanism on XML tags for splitting. If disabled, all splitting_tags are to be specified.
40
+ non_splitting_tags: false, // false or comma-separated list of XML tags. Disable automated splitting on the tags specified.
41
+ splitting_tags: false, // false or comma-separated list of XML tags which always cause splitting.
42
+ ignore_tags: false, // false or comma-separated list of XML tags that indicate text NOT to be translated.
43
+ onInit: function (){}, // callback after plugin has initialized.
44
+ onBeforeTranslation: function (){}, // callback before translation started.
45
+ onAfterTranslation: function (){} // callback after translation finished.
46
+ };
47
+
48
+ // -------------------------------------------------------------------------
49
+ // plugin constructor
50
+ // create the jquery plugin
51
+ // -------------------------------------------------------------------------
52
+ function Plugin (element, options) {
53
+ this.element = element;
54
+ this.settings = $.extend( {}, defaults, options);
55
+ this.settings.elementID = '#' + this.element.id;
56
+ this.xhr = new XMLHttpRequest();
57
+
58
+ // call the plugin initializer
59
+ this.init(this.settings);
60
+ }
61
+
62
+ // Avoid plugin prototype conflicts
63
+ $.extend(Plugin.prototype, {
64
+ // -----------------------------------------------------------------------
65
+ // init()
66
+ // initialize|run the translation
67
+ // -----------------------------------------------------------------------
68
+ init: function(options) {
69
+ var _this = this;
70
+ var logger = log4javascript.getLogger('deeplAPI.init');
71
+ var data_url = '/assets/data/private.json';
72
+ var settings = options;
73
+ var auth_key;
74
+ var encodedString;
75
+ var encryptedString;
76
+ var jsonObject;
77
+
78
+ logger.info('\n' + 'initializing plugin: started');
79
+
80
+ // loading private data (auth key)
81
+ $.ajax({
82
+ url: data_url,
83
+ dataType: 'text',
84
+ success: function (data) {
85
+ encodedString = atob(data);
86
+ encryptedString = _this.decryptData(data, '8c841fc2e3aa2bd5', '0000000000000000' );
87
+ jsonObject = JSON.parse(encryptedString);
88
+ auth_key = jsonObject.translators.deepl.auth_key;
89
+ },
90
+ error: function (jqXHR, textStatus, errorThrown) {
91
+ logger.error('\n' + 'failed to retrieve JSON data from: ' + data_url);
92
+ }
93
+ });
94
+
95
+ // run the translation (if private data loaded)
96
+ var dependencies_met_page_ready = setInterval (function () {
97
+ if (typeof auth_key !== 'undefined' ) {
98
+ settings.auth_key = auth_key;
99
+ _this.translate(settings);
100
+ logger.info('\n' + 'translation: in progress');
101
+ clearInterval(dependencies_met_page_ready);
102
+ }
103
+ });
104
+ },
105
+
106
+ encryptData: function (message = '', key = '') {
107
+ var message = CryptoJS.AES.encrypt(message, key);
108
+
109
+ return message.toString();
110
+ },
111
+
112
+ decryptData: function (message = '', key = '', iv = '') {
113
+ // var test_key_32 = "2e35f242a46d67eeb74aabc37d5e5d05";
114
+ // var data = CryptoJS.AES.encrypt("Message", test_key_32); // Encryption Part
115
+ // var decrypted = CryptoJS.AES.decrypt(data, test_key_32).toString(CryptoJS.enc.Utf8);
116
+
117
+ // 1. Separate ciphertext and salt
118
+ var encryptedWA = CryptoJS.enc.Base64.parse(message);
119
+ var prefixWA = CryptoJS.lib.WordArray.create(encryptedWA.words.slice(0, 8/4)); // Salted__ prefix
120
+ // var saltWA = CryptoJS.lib.WordArray.create(encryptedWA.words.slice(8/4, 16/4)); // 8 bytes salt: 0x0123456789ABCDEF
121
+ var ciphertextWA = CryptoJS.lib.WordArray.create(encryptedWA.words.slice(16/4, encryptedWA.words.length)); // ciphertext
122
+
123
+ // 2. Determine key and IV using PBKDF2
124
+ // var password = 'mypassword'
125
+ // var keyIvWA = CryptoJS.PBKDF2(
126
+ // password,
127
+ // saltWA,
128
+ // {
129
+ // keySize: (32+16)/4, // key and IV
130
+ // iterations: 10000,
131
+ // hasher: CryptoJS.algo.SHA256
132
+ // }
133
+ // );
134
+ // var keyWA = CryptoJS.lib.WordArray.create(keyIvWA.words.slice(0, 32/4));
135
+ // var ivWA = CryptoJS.lib.WordArray.create(keyIvWA.words.slice(32/4, (32+16)/4));
136
+
137
+ // 3. Decrypt
138
+ var decryptedWA = CryptoJS.AES.decrypt(
139
+ {ciphertext: ciphertextWA},
140
+ key,
141
+ {iv: iv}
142
+ );
143
+ var decrypted = decryptedWA.toString(CryptoJS.enc.Utf8)
144
+ return decrypted;
145
+ },
146
+
147
+ // -----------------------------------------------------------------------
148
+ // prepareXHR
149
+ // Prepare a XHR request according to DeepL API specification
150
+ // for the required HTTP header settings
151
+ // See: https://www.deepl.com/de/docs-api/simulator/
152
+ // -----------------------------------------------------------------------
153
+ // NOTE: "User-Agent" NOT used as the use is qualified UNSECURE
154
+ // -----------------------------------------------------------------------
155
+ prepareXHR: function (settings) {
156
+ if (settings.api === 'free') {
157
+ this.xhr.open("POST", "https://api-free.deepl.com/v2/translate", true);
158
+ } else if (settings.api === 'pro') {
159
+ this.xhr.open("POST", "https://api.deepl.com/v2/translate", true);
160
+ } else {
161
+ this.xhr.open("POST", "https://api-free.deepl.com/v2/translate", true);
162
+ }
163
+ // Set required header parameters
164
+ this.xhr.setRequestHeader("Accept", "*/*");
165
+ this.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
166
+ },
167
+
168
+ // -----------------------------------------------------------------------
169
+ // prepareText
170
+ // Prepare text function used to parse, or arrange text, designed as
171
+ // a module. Currently it splits all text whenever a newline ("\n")
172
+ // is met, so that it preserves the original layout of the text, which
173
+ // would have otherwise been lost because of the way DeepL accepts
174
+ // multiple sentences.
175
+ // -----------------------------------------------------------------------
176
+ prepareText: function (source_text) {
177
+ return source_text.split("\n");
178
+ },
179
+
180
+ // -----------------------------------------------------------------------
181
+ // translate
182
+ // Translate text function which uses all the other modules, in order to
183
+ // create a request, which is sent to the DeepL API to translate, and
184
+ // then display the result, designed as a module.
185
+ // -----------------------------------------------------------------------
186
+ translate: function (settings) {
187
+ const logger = log4javascript.getLogger('deeplAPI.translate');
188
+ const READYSTATE_DONE = 4;
189
+ const STATUS_OK = 200;
190
+ const SUPPORTED_LANG = ['BG', 'CS', 'DA', 'DE', 'EL', 'EN-GB', 'EN-US', 'EN', 'ES', 'ET', 'FI', 'FR', 'HU', 'IT', 'JA', 'LT', 'LV', 'NL', 'PL', 'PT-PT', 'PT-BR', 'PT', 'RO', 'RU', 'SK', 'SL', 'SV', 'ZH'];
191
+ const ALLOWED_FORMALITY_LANG = ['DE', 'FR', 'IT', 'ES', 'NL', 'PL', 'PT', 'PT-BR', 'RU'];
192
+ const ALLOWED_TAG_HANDLING = ['xml'];
193
+ const TARGET_ELEMENT = settings.targetElement;
194
+ const TARGET_ELEMENT_EXISTS = $(TARGET_ELEMENT).length;
195
+ const ERROR_TEXT = 'Translation failed.' + '\n' + 'Reason: ';
196
+ const WARNING_TEXT = 'Translation skipped.' + '\n' + 'Reason: ';
197
+
198
+ var BASE_TARGET_ELEMENT;
199
+ var ELEMENT_TYPE;
200
+ var SOURCE_TEXT_FOUND;
201
+
202
+ var API_RESPONSE = {};
203
+ API_RESPONSE['400'] = 'Bad request. Please check error message and your parameters.';
204
+ API_RESPONSE['401'] = 'Authorization failed. Please supply a valid DeepL-Auth-Key.';
205
+ API_RESPONSE['403'] = 'Forbidden. The access to the requested resource is denied, because of insufficient access rights.';
206
+ API_RESPONSE['404'] = 'The requested resource could not be found.';
207
+ API_RESPONSE['413'] = 'The request size exceeds the limit.';
208
+ API_RESPONSE['415'] = 'The requested entries format specified in the Accept header is not supported.';
209
+ API_RESPONSE['429'] = 'Too many requests. Please wait and resend your request.';
210
+ API_RESPONSE['456'] = 'Quota exceeded. The maximum amount of glossaries has been reached.';
211
+ API_RESPONSE['500'] = 'Internal server error';
212
+ API_RESPONSE['503'] = 'Resource currently unavailable. Try again later.';
213
+ API_RESPONSE['529'] = 'Too many requests. Please wait and resend your request.';
214
+
215
+ var reason_text;
216
+ var request = '';
217
+ var element = '';
218
+ var source_text = '';
219
+ var source_text_lines = '';
220
+ var source_lang;
221
+ var target_lang;
222
+
223
+ // check if passed HTML element or ID exists
224
+ if (TARGET_ELEMENT_EXISTS) {
225
+ BASE_TARGET_ELEMENT = (TARGET_ELEMENT.includes('.')||TARGET_ELEMENT.includes('#')) ? TARGET_ELEMENT.substring(1) : TARGET_ELEMENT;
226
+ ELEMENT_TYPE = $(TARGET_ELEMENT).get(0).nodeName;
227
+
228
+ // Read the text to be translated from the given HTML element
229
+ if (ELEMENT_TYPE === 'TEXTAREA') {
230
+ source_text = this.element.value;
231
+ } else if (ELEMENT_TYPE === 'P') {
232
+ element = this.element;
233
+ source_text = $(TARGET_ELEMENT).text();
234
+ }
235
+ SOURCE_TEXT_FOUND = source_text.length;
236
+ } else {
237
+ logger.error('\n' + 'target element does not exists: ' + TARGET_ELEMENT);
238
+ return false;
239
+ }
240
+
241
+ // limit the source text if required
242
+ if (settings.max_char && source_text.length > settings.max_char ) {
243
+ var source_text_limited = source_text.substring(0, settings.max_char -3);
244
+ source_text = source_text_limited + ' ...';
245
+ logger.info('\n' + 'limit for source text ' + '(max: ' + settings.max_char + ')' + ' reached: ' + source_text.length);
246
+ }
247
+ source_text_lines = this.prepareText(source_text);
248
+
249
+ // prepare the XHR request for the API (free/pro) requested
250
+ this.prepareXHR(settings);
251
+
252
+ // Makes a request with every line, as a new text to translate
253
+ var source_text_request = "";
254
+ for(var i = 0; i < source_text_lines.length; i++) {
255
+ source_text_request += "&text=" + source_text_lines[i];
256
+ }
257
+
258
+ this.xhr.onload = function () {
259
+ if (this.readyState === READYSTATE_DONE) {
260
+ if (this.status === STATUS_OK) {
261
+ // JSON parse the response
262
+ var result = JSON.parse(this.responseText);
263
+
264
+ // recreate the response as one text to keep its original layout
265
+ var translated_text = "";
266
+ for(var i = 0; i < result.translations.length; i++) {
267
+ translated_text += result.translations[i].text;
268
+ translated_text += "\n";
269
+ }
270
+ logger.info('\n' + 'translation: finished');
271
+
272
+ // update the HTM element (content) by the tranlation
273
+ if (ELEMENT_TYPE === 'TEXTAREA') {
274
+ $(TARGET_ELEMENT).val(translated_text);
275
+ } else if (ELEMENT_TYPE === 'P') {
276
+ $(TARGET_ELEMENT).text(translated_text);
277
+ }
278
+ } else {
279
+ logger.error('\n' + 'API returned ' + this.status + ': ' + API_RESPONSE[this.status]);
280
+ }
281
+ }
282
+ };
283
+
284
+ // ---------------------------------------------------------------------
285
+ // preflight (validity check) on given parameters
286
+ // ---------------------------------------------------------------------
287
+
288
+ // Check for SUPPORTED language by option source_lang|target_lang
289
+ source_lang = this.settings.source_lang;
290
+ target_lang = this.settings.target_lang;
291
+
292
+ if (this.settings.source_lang !== 'auto') {
293
+ this.settings.source_lang = (SUPPORTED_LANG.indexOf(this.settings.source_lang) > -1) ? this.settings.source_lang : false;
294
+ }
295
+ this.settings.target_lang = (SUPPORTED_LANG.indexOf(this.settings.target_lang) > -1) ? this.settings.target_lang : false;
296
+
297
+ // stop processing if invalid language or NO AUTH key passed
298
+ if (!this.settings.auth_key || !this.settings.source_lang || !this.settings.target_lang) {
299
+ if (!this.settings.auth_key) {
300
+ reason_text = 'NO AUTH key passed.';
301
+ logger.error('\n' + 'invalid option found. ' + reason_text);
302
+ }
303
+ if (!this.settings.source_lang) {
304
+ reason_text = 'WRONG source language passed: ' + source_lang;
305
+ logger.error('\n' + 'invalid option found. ' + reason_text);
306
+ }
307
+ if (!this.settings.target_lang) {
308
+ reason_text = 'WRONG target language passed: ' + target_lang;
309
+ logger.error('\n' + 'invalid option found. ' + reason_text);
310
+ }
311
+
312
+ // update the HTML element (content) by an error text
313
+ if (ELEMENT_TYPE === 'TEXTAREA') {
314
+ $(TARGET_ELEMENT).val(ERROR_TEXT + reason_text);
315
+ } else if (ELEMENT_TYPE === 'P') {
316
+ $(TARGET_ELEMENT).text(ERROR_TEXT + reason_text);
317
+ }
318
+ return false;
319
+ }
320
+
321
+ if(!SOURCE_TEXT_FOUND) {
322
+ reason_text = 'NO text found for translation';
323
+ // update the HTML element (content) by an error text
324
+ if (ELEMENT_TYPE === 'TEXTAREA') {
325
+ $(TARGET_ELEMENT).val(WARNING_TEXT + reason_text);
326
+ } else if (ELEMENT_TYPE === 'P') {
327
+ $(TARGET_ELEMENT).text(WARNING_TEXT + reason_text);
328
+ }
329
+ logger.warn('\n' + 'no text found for translation');
330
+ return false;
331
+ }
332
+
333
+ // Check for VALID language supported by option 'formality'
334
+ if (this.settings.formality !== 'default' ) {
335
+ if (!(ALLOWED_FORMALITY_LANG.indexOf(this.settings.target_lang) > -1)) {
336
+ logger.warn('\n' + 'wrong language found for formality setting: ' + this.settings.target_lang);
337
+ }
338
+ this.settings.formality = (ALLOWED_FORMALITY_LANG.indexOf(this.settings.target_lang) > -1) ? this.settings.formality : 'default';
339
+ }
340
+
341
+ // Check for VALID tag handling and options
342
+ if (this.settings.tag_handling) {
343
+ var tag_handling = this.settings.tag_handling;
344
+ // check for VALID method
345
+ this.settings.tag_handling = (ALLOWED_TAG_HANDLING.indexOf(this.settings.tag_handling) > -1) ? this.settings.tag_handling : false;
346
+ if (this.settings.tag_handling) {
347
+ this.settings.non_splitting_tags = this.settings.non_splitting_tags ? encodeURIComponent(this.settings.non_splitting_tags) : false;
348
+ this.settings.splitting_tags = this.settings.splitting_tags ? encodeURIComponent(this.settings.splitting_tags) : false;
349
+ this.settings.ignore_tags = this.settings.ignore_tags ? encodeURIComponent(this.settings.ignore_tags) : false;
350
+ } else {
351
+ logger.error('\n' + 'invalid option found for tag handling : ' + tag_handling);
352
+ logger.warn('\n' + 'disable option: ' + 'tag_handling');
353
+ // reset to defaults if WRONG method detected
354
+ if (this.settings.non_splitting_tags) {
355
+ logger.warn('\n' + 'disable option: ' + this.settings.non_splitting_tags);
356
+ this.settings.non_splitting_tags = false;
357
+ }
358
+ if (this.settings.splitting_tags) {
359
+ logger.warn('\n' + 'disable option : ' + this.settings.splitting_tags);
360
+ this.settings.splitting_tags = false;
361
+ }
362
+ if (this.settings.ignore_tags) {
363
+ logger.warn('\n' + 'disable option: ' + this.settings.ignore_tags);
364
+ this.settings.ignore_tags = false;
365
+ }
366
+ }
367
+ } else {
368
+ // reset tags to their defaults if NO tag_handling is enabled but settings passed
369
+ if (this.settings.non_splitting_tags) {
370
+ logger.warn('\n' + 'invalid option found: ' + this.settings.non_splitting_tags);
371
+ this.settings.non_splitting_tags = false;
372
+ }
373
+ if (this.settings.splitting_tags) {
374
+ logger.warn('\n' + 'invalid option found: ' + this.settings.splitting_tags);
375
+ this.settings.splitting_tags = false;
376
+ }
377
+ if (this.settings.ignore_tags) {
378
+ logger.warn('\n' + 'invalid option found: ' + this.settings.ignore_tags);
379
+ this.settings.ignore_tags = false;
380
+ }
381
+ }
382
+
383
+ // ---------------------------------------------------------------------
384
+ // construct the API request body
385
+ // ---------------------------------------------------------------------
386
+ request = "auth_key=" + this.settings.auth_key;
387
+ request += (this.settings.source_lang !== 'auto' ) ? "&source_lang=" + this.settings.source_lang : '';
388
+ request += "&target_lang=" + this.settings.target_lang;
389
+ request += (this.settings.formality !== 'default' ) ? "&formality=" + this.settings.formality : '';
390
+ request += (this.settings.split_sentences) ? "&split_sentences=" + this.settings.formality : '';
391
+ request += (this.settings.tag_handling) ? "&tag_handling=" + this.settings.tag_handling : "&tag_handling=0";
392
+ request += (this.settings.tag_handling && this.settings.non_splitting_tags) ? "&non_splitting_tags=" + this.settings.non_splitting_tags : '';
393
+ request += (this.settings.tag_handling && this.settings.splitting_tags) ? "&splitting_tags=" + this.settings.splitting_tags : '';
394
+ request += (this.settings.tag_handling && this.settings.ignore_tags) ? "&ignore_tags=" + this.settings.ignore_tags : '';
395
+ request += source_text_request;
396
+
397
+ // Send the constructed request to the API for translation
398
+ this.xhr.send(request);
399
+ } // END translate
400
+
401
+ }); // END prototype
402
+
403
+ // ---------------------------------------------------------------------------
404
+ // plugin wrapper
405
+ // A really lightweight plugin wrapper around the constructor,
406
+ // wrapper around the constructor to prevent multiple instantiations
407
+ // preventing against multiple instantiations and allowing any
408
+ // public function (ie. a function whose name doesn't start
409
+ // with an underscore) to be called via the jQuery plugin,
410
+ // e.g. $(element).defaultPluginName('functionName', arg1, arg2)
411
+ // ---------------------------------------------------------------------------
412
+ $.fn[pluginName] = function ( options ) {
413
+ var args = arguments;
414
+
415
+ // Is the first parameter an object (options), or was omitted,
416
+ // instantiate a new instance of the plugin.
417
+ //
418
+ if (options === undefined || typeof options === 'object') {
419
+ return this.each(function () {
420
+ // Only allow the plugin to be instantiated once,
421
+ // so we check that the element has no plugin instantiation yet
422
+ if (!$.data(this, 'plugin_' + pluginName)) {
423
+ // if it has no instance, create a new one, pass options to the
424
+ // plugin constructor, and store the plugin instance in the
425
+ // elements jQuery data object.
426
+ $.data(this, 'plugin_' + pluginName, new Plugin( this, options ));
427
+ }
428
+ });
429
+ } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
430
+ // If the first parameter is a string and it doesn't start
431
+ // with an underscore or "contains" the `init`-function,
432
+ // treat this as a call to a public method.
433
+
434
+ // Cache the method call to make it possible to return a value
435
+ var returns;
436
+
437
+ this.each(function () {
438
+ var instance = $.data(this, 'plugin_' + pluginName);
439
+
440
+ // Tests that there's already a plugin-instance
441
+ // and checks that the requested public method exists
442
+ if (instance instanceof Plugin && typeof instance[options] === 'function') {
443
+ // Call the method of our plugin instance,
444
+ // and pass it the supplied arguments.
445
+ returns = instance[options].apply( instance, Array.prototype.slice.call( args, 1 ) );
446
+ }
447
+
448
+ // Allow instances to be destroyed via the 'destroy' method
449
+ if (options === 'destroy') {
450
+ $.data(this, 'plugin_' + pluginName, null);
451
+ }
452
+ });
453
+
454
+ // If the earlier cached method gives a value back return the value,
455
+ // otherwise return "this" to preserve chainability.
456
+ return returns !== undefined ? returns : this;
457
+ }
458
+ }; // END plugin wrapper
459
+
460
+ })(jQuery, window, document);