diff options
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/bg/background.html | 1 | ||||
| -rw-r--r-- | ext/bg/data/anki-field-templates-upgrade-v8.handlebars | 105 | ||||
| -rw-r--r-- | ext/bg/data/default-anki-field-templates.handlebars | 53 | ||||
| -rw-r--r-- | ext/bg/js/options.js | 40 | ||||
| -rw-r--r-- | ext/bg/js/template-patcher.js | 92 | ||||
| -rw-r--r-- | ext/bg/settings.html | 1 | ||||
| -rw-r--r-- | ext/bg/settings2.html | 1 | ||||
| -rw-r--r-- | ext/sw.js | 1 | 
8 files changed, 239 insertions, 55 deletions
| diff --git a/ext/bg/background.html b/ext/bg/background.html index e139514d..29cae072 100644 --- a/ext/bg/background.html +++ b/ext/bg/background.html @@ -40,6 +40,7 @@          <script src="/bg/js/profile-conditions.js"></script>          <script src="/bg/js/request-builder.js"></script>          <script src="/bg/js/native-simple-dom-parser.js"></script> +        <script src="/bg/js/template-patcher.js"></script>          <script src="/bg/js/text-source-map.js"></script>          <script src="/bg/js/translator.js"></script> diff --git a/ext/bg/data/anki-field-templates-upgrade-v8.handlebars b/ext/bg/data/anki-field-templates-upgrade-v8.handlebars index a5056364..32c61343 100644 --- a/ext/bg/data/anki-field-templates-upgrade-v8.handlebars +++ b/ext/bg/data/anki-field-templates-upgrade-v8.handlebars @@ -12,3 +12,108 @@          {{~/if~}}      {{~/scope~}}  {{/inline}} + +{{<<<<<<<}} +{{#*inline "glossary-single"}} +    {{~#unless brief~}} +        {{~#scope~}} +            {{~#set "any" false}}{{/set~}} +            {{~#if definitionTags~}}{{#each definitionTags~}} +                {{~#if (op "||" (op "!" ../data.compactTags) (op "!" redundant))~}} +                    {{~#if (get "any")}}, {{else}}<i>({{/if~}} +                    {{name}} +                    {{~#set "any" true}}{{/set~}} +                {{~/if~}} +            {{~/each~}} +            {{~#if (get "any")}})</i> {{/if~}} +            {{~/if~}} +        {{~/scope~}} +        {{~#if only~}}({{#each only}}{{{.}}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}} +    {{~/unless~}} +    {{~#if glossary.[1]~}} +        {{~#if compactGlossaries~}} +            {{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{#unless @last}} | {{/unless}}{{/each}} +        {{~else~}} +            <ul>{{#each glossary}}<li>{{#multiLine}}{{.}}{{/multiLine}}</li>{{/each}}</ul> +        {{~/if~}} +    {{~else~}} +        {{~#multiLine}}{{glossary.[0]}}{{/multiLine~}} +    {{~/if~}} +{{/inline}} +{{=======}} +{{#*inline "glossary-single"}} +    {{~#unless brief~}} +        {{~#scope~}} +            {{~#set "any" false}}{{/set~}} +            {{~#each definitionTags~}} +                {{~#if (op "||" (op "!" @root.compactTags) (op "!" redundant))~}} +                    {{~#if (get "any")}}, {{else}}<i>({{/if~}} +                    {{name}} +                    {{~#set "any" true}}{{/set~}} +                {{~/if~}} +            {{~/each~}} +            {{~#if (get "any")}})</i> {{/if~}} +        {{~/scope~}} +        {{~#if only~}}({{#each only}}{{.}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}} +    {{~/unless~}} +    {{~#if (op "<=" glossary.length 1)~}} +        {{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{/each}} +    {{~else if @root.compactGlossaries~}} +        {{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{#unless @last}} | {{/unless}}{{/each}} +    {{~else~}} +        <ul>{{#each glossary}}<li>{{#multiLine}}{{.}}{{/multiLine}}</li>{{/each}}</ul> +    {{~/if~}} +{{/inline}} +{{>>>>>>>}} + +{{<<<<<<<}} +{{#*inline "glossary"}} +    <div style="text-align: left;"> +    {{~#if modeKanji~}} +        {{~#if definition.glossary.[1]~}} +            <ol>{{#each definition.glossary}}<li>{{.}}</li>{{/each}}</ol> +        {{~else~}} +            {{definition.glossary.[0]}} +        {{~/if~}} +    {{~else~}} +        {{~#if group~}} +            {{~#if definition.definitions.[1]~}} +                <ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries data=../.}}</li>{{/each}}</ol> +            {{~else~}} +                {{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries data=.~}} +            {{~/if~}} +        {{~else if merge~}} +            {{~#if definition.definitions.[1]~}} +                <ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries data=../.}}</li>{{/each}}</ol> +            {{~else~}} +                {{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries data=.~}} +            {{~/if~}} +        {{~else~}} +            {{~> glossary-single definition brief=brief compactGlossaries=compactGlossaries data=.~}} +        {{~/if~}} +    {{~/if~}} +    </div> +{{/inline}} +{{=======}} +{{~#*inline "glossary"~}} +    <div style="text-align: left;"> +    {{~#scope~}} +        {{~#if (op "===" definition.type "term")~}} +            {{~> glossary-single definition brief=brief ~}} +        {{~else if (op "||" (op "===" definition.type "termGrouped") (op "===" definition.type "termMerged"))~}} +            {{~#if (op ">" definition.definitions.length 1)~}} +                <ol>{{~#each definition.definitions~}}<li>{{~> glossary-single . brief=../brief ~}}</li>{{~/each~}}</ol> +            {{~else~}} +                {{~#each definition.definitions~}}{{~> glossary-single . brief=../brief ~}}{{~/each~}} +            {{~/if~}} +        {{~else if (op "===" definition.type "kanji")~}} +            {{~#if (op ">" definition.glossary.length 1)~}} +                <ol>{{#each definition.glossary}}<li>{{.}}</li>{{/each}}</ol> +            {{~else~}} +                {{~#each definition.glossary~}}{{.}}{{~/each~}} +            {{~/if~}} +        {{~/if~}} +    {{~/scope~}} +    </div> +{{~/inline~}} +{{>>>>>>>}} diff --git a/ext/bg/data/default-anki-field-templates.handlebars b/ext/bg/data/default-anki-field-templates.handlebars index a0aff5d2..94553183 100644 --- a/ext/bg/data/default-anki-field-templates.handlebars +++ b/ext/bg/data/default-anki-field-templates.handlebars @@ -2,26 +2,23 @@      {{~#unless brief~}}          {{~#scope~}}              {{~#set "any" false}}{{/set~}} -            {{~#if definitionTags~}}{{#each definitionTags~}} -                {{~#if (op "||" (op "!" ../data.compactTags) (op "!" redundant))~}} +            {{~#each definitionTags~}} +                {{~#if (op "||" (op "!" @root.compactTags) (op "!" redundant))~}}                      {{~#if (get "any")}}, {{else}}<i>({{/if~}}                      {{name}}                      {{~#set "any" true}}{{/set~}}                  {{~/if~}}              {{~/each~}}              {{~#if (get "any")}})</i> {{/if~}} -            {{~/if~}}          {{~/scope~}} -        {{~#if only~}}({{#each only}}{{{.}}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}} +        {{~#if only~}}({{#each only}}{{.}}{{#unless @last}}, {{/unless}}{{/each}} only) {{/if~}}      {{~/unless~}} -    {{~#if glossary.[1]~}} -        {{~#if compactGlossaries~}} -            {{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{#unless @last}} | {{/unless}}{{/each}} -        {{~else~}} -            <ul>{{#each glossary}}<li>{{#multiLine}}{{.}}{{/multiLine}}</li>{{/each}}</ul> -        {{~/if~}} +    {{~#if (op "<=" glossary.length 1)~}} +        {{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{/each}} +    {{~else if @root.compactGlossaries~}} +        {{#each glossary}}{{#multiLine}}{{.}}{{/multiLine}}{{#unless @last}} | {{/unless}}{{/each}}      {{~else~}} -        {{~#multiLine}}{{glossary.[0]}}{{/multiLine~}} +        <ul>{{#each glossary}}<li>{{#multiLine}}{{.}}{{/multiLine}}</li>{{/each}}</ul>      {{~/if~}}  {{/inline}} @@ -92,33 +89,27 @@      {{~/if~}}  {{/inline}} -{{#*inline "glossary"}} +{{~#*inline "glossary"~}}      <div style="text-align: left;"> -    {{~#if modeKanji~}} -        {{~#if definition.glossary.[1]~}} -            <ol>{{#each definition.glossary}}<li>{{.}}</li>{{/each}}</ol> -        {{~else~}} -            {{definition.glossary.[0]}} -        {{~/if~}} -    {{~else~}} -        {{~#if group~}} -            {{~#if definition.definitions.[1]~}} -                <ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries data=../.}}</li>{{/each}}</ol> +    {{~#scope~}} +        {{~#if (op "===" definition.type "term")~}} +            {{~> glossary-single definition brief=brief ~}} +        {{~else if (op "||" (op "===" definition.type "termGrouped") (op "===" definition.type "termMerged"))~}} +            {{~#if (op ">" definition.definitions.length 1)~}} +                <ol>{{~#each definition.definitions~}}<li>{{~> glossary-single . brief=../brief ~}}</li>{{~/each~}}</ol>              {{~else~}} -                {{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries data=.~}} +                {{~#each definition.definitions~}}{{~> glossary-single . brief=../brief ~}}{{~/each~}}              {{~/if~}} -        {{~else if merge~}} -            {{~#if definition.definitions.[1]~}} -                <ol>{{#each definition.definitions}}<li>{{> glossary-single brief=../brief compactGlossaries=../compactGlossaries data=../.}}</li>{{/each}}</ol> +        {{~else if (op "===" definition.type "kanji")~}} +            {{~#if (op ">" definition.glossary.length 1)~}} +                <ol>{{#each definition.glossary}}<li>{{.}}</li>{{/each}}</ol>              {{~else~}} -                {{~> glossary-single definition.definitions.[0] brief=brief compactGlossaries=compactGlossaries data=.~}} +                {{~#each definition.glossary~}}{{.}}{{~/each~}}              {{~/if~}} -        {{~else~}} -            {{~> glossary-single definition brief=brief compactGlossaries=compactGlossaries data=.~}}          {{~/if~}} -    {{~/if~}} +    {{~/scope~}}      </div> -{{/inline}} +{{~/inline~}}  {{#*inline "glossary-brief"}}      {{~> glossary brief=true ~}} diff --git a/ext/bg/js/options.js b/ext/bg/js/options.js index 02caa5a2..9e0e9cf0 100644 --- a/ext/bg/js/options.js +++ b/ext/bg/js/options.js @@ -17,11 +17,13 @@  /* global   * JsonSchemaValidator + * TemplatePatcher   */  class OptionsUtil {      constructor() {          this._schemaValidator = new JsonSchemaValidator(); +        this._templatePatcher = null;          this._optionsSchema = null;      } @@ -381,32 +383,22 @@ class OptionsUtil {      // Private -    async _addFieldTemplatesToOptions(options, additionSourceUrl) { -        let addition = null; +    async _applyAnkiFieldTemplatesPatch(options, modificationsUrl) { +        let patch = null;          for (const {options: profileOptions} of options.profiles) {              const fieldTemplates = profileOptions.anki.fieldTemplates; -            if (fieldTemplates !== null) { -                if (addition === null) { -                    addition = await this._fetchAsset(additionSourceUrl); +            if (fieldTemplates === null) { continue; } + +            if (patch === null) { +                const content = await this._fetchAsset(modificationsUrl); +                if (this._templatePatcher === null) { +                    this._templatePatcher = new TemplatePatcher();                  } -                profileOptions.anki.fieldTemplates = this._addFieldTemplatesBeforeEnd(fieldTemplates, addition); +                patch = this._templatePatcher.parsePatch(content);              } -        } -    } -    _addFieldTemplatesBeforeEnd(fieldTemplates, addition) { -        const pattern = /[ \t]*\{\{~?>\s*\(\s*lookup\s*\.\s*"marker"\s*\)\s*~?\}\}/g; -        const newline = '\n'; -        let replaced = false; -        fieldTemplates = fieldTemplates.replace(pattern, (g0) => { -            replaced = true; -            return `${addition}${newline}${g0}`; -        }); -        if (!replaced) { -            fieldTemplates += newline; -            fieldTemplates += addition; +            profileOptions.anki.fieldTemplates = this._templatePatcher.applyPatch(fieldTemplates, patch);          } -        return fieldTemplates;      }      async _fetchAsset(url, json=false) { @@ -495,7 +487,7 @@ class OptionsUtil {      async _updateVersion3(options) {          // Version 3 changes:          //  Pitch accent Anki field templates added. -        await this._addFieldTemplatesToOptions(options, '/bg/data/anki-field-templates-upgrade-v2.handlebars'); +        await this._applyAnkiFieldTemplatesPatch(options, '/bg/data/anki-field-templates-upgrade-v2.handlebars');          return options;      } @@ -580,7 +572,7 @@ class OptionsUtil {              });              profileOptions.scanning.inputs = scanningInputs;          } -        await this._addFieldTemplatesToOptions(options, '/bg/data/anki-field-templates-upgrade-v4.handlebars'); +        await this._applyAnkiFieldTemplatesPatch(options, '/bg/data/anki-field-templates-upgrade-v4.handlebars');          return options;      } @@ -600,7 +592,7 @@ class OptionsUtil {          //  Added global option useSettingsV2.          //  Added anki.checkForDuplicates.          //  Added general.glossaryLayoutMode; removed general.compactGlossaries. -        await this._addFieldTemplatesToOptions(options, '/bg/data/anki-field-templates-upgrade-v6.handlebars'); +        await this._applyAnkiFieldTemplatesPatch(options, '/bg/data/anki-field-templates-upgrade-v6.handlebars');          options.global.showPopupPreview = false;          options.global.useSettingsV2 = false;          for (const profile of options.profiles) { @@ -673,7 +665,7 @@ class OptionsUtil {          //  Moved general.enableClipboardMonitor => clipboard.enableSearchPageMonitor. Forced value to false due to a bug which caused its value to not be read.          //  Moved general.maximumClipboardSearchLength => clipboard.maximumSearchLength.          //  Added clipboard.autoSearchContent. -        await this._addFieldTemplatesToOptions(options, '/bg/data/anki-field-templates-upgrade-v8.handlebars'); +        await this._applyAnkiFieldTemplatesPatch(options, '/bg/data/anki-field-templates-upgrade-v8.handlebars');          options.global.useSettingsV2 = true;          for (const profile of options.profiles) {              profile.options.translation.textReplacements = { diff --git a/ext/bg/js/template-patcher.js b/ext/bg/js/template-patcher.js new file mode 100644 index 00000000..57178957 --- /dev/null +++ b/ext/bg/js/template-patcher.js @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2021  Yomichan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <https://www.gnu.org/licenses/>. + */ + +class TemplatePatcher { +    constructor() { +        this._diffPattern1 = /\n?\{\{<<<<<<<\}\}\n/g; +        this._diffPattern2 = /\n\{\{=======\}\}\n/g; +        this._diffPattern3 = /\n\{\{>>>>>>>\}\}\n*/g; +        this._lookupMarkerPattern = /[ \t]*\{\{~?>\s*\(\s*lookup\s*\.\s*"marker"\s*\)\s*~?\}\}/g; +    } + +    parsePatch(content) { +        const diffPattern1 = this._diffPattern1; +        const diffPattern2 = this._diffPattern2; +        const diffPattern3 = this._diffPattern3; +        const modifications = []; +        let index = 0; + +        while (true) { +            // Find modification boundaries +            diffPattern1.lastIndex = index; +            const m1 = diffPattern1.exec(content); +            if (m1 === null) { break; } + +            diffPattern2.lastIndex = m1.index + m1[0].length; +            const m2 = diffPattern2.exec(content); +            if (m2 === null) { break; } + +            diffPattern3.lastIndex = m2.index + m2[0].length; +            const m3 = diffPattern3.exec(content); +            if (m3 === null) { break; } + +            // Construct +            const current = content.substring(m1.index + m1[0].length, m2.index); +            const replacement = content.substring(m2.index + m2[0].length, m3.index); + +            if (current.length > 0) { +                modifications.push({current, replacement}); +            } + +            // Update +            content = content.substring(0, m1.index) + content.substring(m3.index + m3[0].length); +            index = m1.index; +        } + +        return {addition: content, modifications}; +    } + +    applyPatch(template, patch) { +        for (const {current, replacement} of patch.modifications) { +            let fromIndex = 0; +            while (true) { +                const index = template.indexOf(current, fromIndex); +                if (index < 0) { break; } +                template = template.substring(0, index) + replacement + template.substring(index + current.length); +                fromIndex = index + replacement.length; +            } +        } +        template = this._addFieldTemplatesBeforeEnd(template, patch.addition); +        return template; +    } + +    // Private + +    _addFieldTemplatesBeforeEnd(template, addition) { +        const newline = '\n'; +        let replaced = false; +        template = template.replace(this._lookupMarkerPattern, (g0) => { +            replaced = true; +            return `${addition}${newline}${g0}`; +        }); +        if (!replaced) { +            template += newline; +            template += addition; +        } +        return template; +    } +} diff --git a/ext/bg/settings.html b/ext/bg/settings.html index e09a180e..2ccb7a1e 100644 --- a/ext/bg/settings.html +++ b/ext/bg/settings.html @@ -1305,6 +1305,7 @@          <script src="/bg/js/dictionary-importer.js"></script>          <script src="/bg/js/json-schema.js"></script>          <script src="/bg/js/media-utility.js"></script> +        <script src="/bg/js/template-patcher.js"></script>          <script src="/bg/js/template-renderer-proxy.js"></script>          <script src="/bg/js/settings/keyboard-mouse-input-field.js"></script> diff --git a/ext/bg/settings2.html b/ext/bg/settings2.html index 63498020..d557d366 100644 --- a/ext/bg/settings2.html +++ b/ext/bg/settings2.html @@ -3208,6 +3208,7 @@  <script src="/bg/js/dictionary-importer.js"></script>  <script src="/bg/js/json-schema.js"></script>  <script src="/bg/js/media-utility.js"></script> +<script src="/bg/js/template-patcher.js"></script>  <script src="/bg/js/template-renderer-proxy.js"></script>  <script src="/bg/js/settings/keyboard-mouse-input-field.js"></script> @@ -39,6 +39,7 @@ self.importScripts(      '/bg/js/profile-conditions.js',      '/bg/js/request-builder.js',      '/bg/js/simple-dom-parser.js', +    '/bg/js/template-patcher.js',      '/bg/js/text-source-map.js',      '/bg/js/translator.js',      '/bg/js/backend.js', |