Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SyntaxError: Unexpected closing tag "script" Vue-3 #276

Open
SergeyKazarinov opened this issue Dec 21, 2023 · 4 comments
Open

SyntaxError: Unexpected closing tag "script" Vue-3 #276

SergeyKazarinov opened this issue Dec 21, 2023 · 4 comments

Comments

@SergeyKazarinov
Copy link

Hello
I had a problem with a plugin in a vue-3 project.

I have the following config

{
  "plugins": ["@trivago/prettier-plugin-sort-imports"],
  "printWidth": 120,
  "tabWidth": 2,
  "semi": true,
  "singleQuote": true,
  "bracketSpacing": true,
  "bracketSameLine": false,
  "arrowParens": "always",
  "endOfLine": "lf",
  "vueIndentScriptAndStyle": true,
  "importOrder": [
    "<THIRD_PARTY_MODULES>",
    "^@/app/(.*)$",
    "^@/common/(.*)$",
    "^[../]",
    "^[./]"
  ],
  "importOrderSeparation": true,
  "importOrderSortSpecifiers": true,
  "importOrderGroupNamespaceSpecifiers": true
}

when checking it gives me an error

[error] src/app/shared/components/ChartLines.vue: SyntaxError: Unexpected closing tag "script". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags (89:1)
[error]   87 |

If I remove the plugin from the config, the error disappears.

It also gives another similar error

[error] src/app/shared/components/ui/ComponentInput.vue: SyntaxError: Unexpected closing tag "script". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags (303:51)
[error]   301 |       if (fieldType !== 'snils') return true;
[error]   302 |       if (!useValidation) return true;
[error] > 303 |       if (!value || value.length === 0) return true;
[error]       |                                                   ^^^^^^^^^
[error]   304 |       return {
[error]   305 |         $valid: validateSnils(value),
[error]   306 |         extraParams: { scope: scope },

My package.jcon

"dependencies": {
    "@fortawesome/fontawesome-free": "^5.15.3",
    "@vue/compiler-sfc": "^3.3.13",
    "@vueform/multiselect": "^2.3.3",
    "@vuelidate/core": "^2.0.0-alpha.21",
    "@vuelidate/validators": "^2.0.0-alpha.18",
    "apexcharts": "^3.33.2",
    "axios": "^0.21.1",
    "chart.js": "^3.7.1",
    "chartjs-plugin-datalabels": "^2.0.0",
    "click-outside-vue3": "^4.0.1",
    "core-js": "^3.8.3",
    "gitart-vue-dialog": "^2.0.5",
    "html2pdf.js": "^0.10.1",
    "i": "^0.3.7",
    "inputmask": "^5.0.7",
    "jquery": "^3.6.0",
    "leaflet": "^1.7.1",
    "lodash": "^4.17.21",
    "moment": "^2.29.1",
    "npm": "^10.2.5",
    "oidc-client": "^1.11.5",
    "sweetalert2": "11.0.18",
    "vue": "^3.2.41",
    "vue-chart-3": "^3.0.9",
    "vue-chartjs": "^3.5.1",
    "vue-router": "4.1.3",
    "vue-select": "^4.0.0-beta.3",
    "vue-slick-carousel": "^1.0.6",
    "vue3-apexcharts": "^1.4.1",
    "vue3-carousel": "^0.1.36",
    "vue3-datepicker": "^0.2.5",
    "vue3-select2-component": "^0.1.7",
    "vuex": "^4.0.2"
  },
  "devDependencies": {
    "@babel/core": "^7.12.16",
    "@babel/eslint-parser": "^7.12.16",
    "@trivago/prettier-plugin-sort-imports": "^4.3.0",
    "@vue/cli-plugin-babel": "~5.0.0",
    "@vue/cli-plugin-eslint": "~5.0.0",
    "@vue/cli-service": "~5.0.0",
    "eslint": "^7.32.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-vue": "^8.0.3",
    "husky": "^8.0.0",
    "lint-staged": "^15.2.0",
    "prettier": "^3.1.1",
    "sass": "^1.49.9",
    "sass-loader": "^12.6.0",
    "vue-router": "4.1.3",
    "webpack": "^5.70.0"
  },

One of the components with an error

<template>
  <div class="apexchart-lines" :class="{ customLineStyles: customStyles }">
    <apexchart type="line" :height="700" :options="chartOptions" :series="series"> </apexchart>
  </div>
</template>

<script>
  export default {
    name: 'ChartLines',
    props: {
      seriesProp: Array,
      years: Array,
      tooltipSuffix: String,
    },
    data() {
      return {
        chartOptions: {},
      };
    },
    methods: {
      // templates
      createChart() {
        var categories = this.years
          ? this.years
          : []
        this.chartOptions = {
          chart: {
            height: 350,
            type: 'line',
            toolbar: {
              show: false,
            },
          },
          dataLabels: {
            enabled: false,
          },
          stroke: {
            curve: 'straight',
          },
          xaxis: {
            // categories: this.years,
            categories: categories,
          },
          tooltip: {
            theme: 'dark',
            fillSeriesColor: false,
            y: {
              formatter: (value) => {
                value += this.tooltipSuffix ? ' ' + this.tooltipSuffix : ' $';
                return value;
              },
            },
          },
          legend: {
            position: 'bottom',
            horizontalAlign: 'left',
            offsetY: 10,
          },
        };
        this.series = this.seriesProp;
      },
    },
    created() {
      this.createChart();
    },
    watch: {
      years: function () {
        this.createChart();
      },
    },
  };
</script>

There is also a similar component with other options, which does not produce an error

<template>
  <div class="apexchart-donut" :class="{ customDonutStyles: customStyles }">
    <apexchart type="donut" :height="690" :options="chartOptions" :series="series" @dataPointSelection="clickHandler">
    </apexchart>
  </div>
</template>

<script>
  export default {
    name: 'ChartDonut',
    props: {
      seriesProp: Array,
      template: {
        default: 'default',
        type: String,
      },
      customStyles: {
        default: false,
        type: Boolean,
      },
      nn: Number,
      legendTitle: String,
    },
    watch: {
      nn: function (/*newValue*/) {
        this.loadChart();
      },
      seriesProp: function () {
        this.loadChart();
      },
    },
    data() {
      return {
        // data for templates
        labelsArray: [],
        countArray: [],
        // Stock options not used
        chartOptions: {
          legend: {
            position: 'right',
            markers: {
              width: 20,
              height: 20,
              radius: 0,
              offsetY: 5,
            },
            offsetX: 100,
            offsetY: 200,
            itemMargin: {
              horizontal: 0,
              vertical: 8,
            },
          },
          dataLabels: {
            enabled: false,
          },
          stroke: {
            show: true,
            //colors: ['#02E5DD'],
          },
          labels: ['Apples', 'Oranges', 'Berries', 'Grapes'],
          //colors: ['#02E5DD', '#01A39D', '#017A76', '#018F89', '#01524F', '#016662','#002927','#003D3B','#00BFB8'],
        },
      };
    },
    methods: {
      clickHandler(event, chartContext, config) {
        if (config.dataPointIndex >= 0) this.$emit('chartClick', this.seriesProp[config.dataPointIndex].name);
      },
      // templates
      createChart() {
        for (let i = 0; i < this.seriesProp.length; i++) {
          let item = this.seriesProp[i].name;
          this.labelsArray.push(item);
        }
        for (let i = 0; i < this.seriesProp.length; i++) {
          let item = this.seriesProp[i].count;
          this.countArray.push(item);
        }
        this.chartOptions = {
          legend: {
            position: 'right',
            markers: {
              width: 20,
              height: 20,
              radius: 0,
              offsetY: 5,
            },
            offsetX: 100,
            offsetY: 0,
            itemMargin: {
              horizontal: 0,
              vertical: 8,
            },
          },
          dataLabels: {
            enabled: false,
          },
          stroke: {
            show: true,
            colors: undefined,
          },
          labels: this.labelsArray,
          colors: [
            '#00ddff',
            '#06b7e3',
            '#0a6bb1',
            '#0382d7',
            '#0068e0',
            '#004ee0',
            '#0657ed',
            '#21adf9',
            '#21eef0',
            '#24afd0',
            '#00fee1',
            '#01fdf9',
            '#99eeee',
            '#90ffff',
            '#34ead9',
            '#55ddf9',
            '#99eeff',
            '#eeeeee',
            '#3fffef',
            '#3EFFFF',
            '#4431ee',
            '#af99ee',
            '#afee99',
            '#afeeee',
            '#afff99',
            '#99ffff',
          ],
          tooltip: {
            theme: 'dark',
            fillSeriesColor: false,
            y: {
              formatter: function (value) {
                value += ' е.';
                return value;
              },
            },
          },
          responsive: [
            {
              breakpoint: 1130,
              options: {
                legend: {
                  offsetX: 0,
                  offsetY: 100,
                },
              },
            },
            {
              breakpoint: 768,
              options: {
                legend: {
                  position: 'bottom',
                  offsetX: 0,
                  offsetY: 0,
                  markers: {
                    offsetY: 0,
                  },
                  itemMargin: {
                    horizontal: 24,
                    vertical: 0,
                  },
                },
              },
            },
            {
              breakpoint: 475,
              options: {
                legend: {
                  horizontalAlign: 'left',
                  markers: {
                    offsetY: 6,
                  },
                  itemMargin: {
                    horizontal: 8,
                    vertical: 4,
                  },
                },
              },
            },
          ],
          chart: {
            width: '100%',
          },
        };
        this.series = this.countArray;
      },
      createStockChart() {
        for (let i = 0; i < this.seriesProp.length; i++) {
          let item = this.seriesProp[i].name;
          this.labelsArray.push(item);
        }
        for (let i = 0; i < this.seriesProp.length; i++) {
          let item = this.seriesProp[i].count;
          this.countArray.push(item);
        }
        this.chartOptions = {
          dataLabels: {
            enabled: true,
          },
          stroke: {
            show: true,
            colors: undefined,
          },
          labels: this.labelsArray,
          tooltip: {
            theme: 'dark',
            fillSeriesColor: false,
          },
          legend: {
            position: 'bottom',
          },
        };
        this.series = this.countArray;
      },

      // loading templates
      loadChart() {
        if (this.template == 'default') {
          this.createChart();
        } else if (this.template == 'stock') {
          this.createStockChart();
        }
      },
    },
    created() {
      this.loadChart();
    },
    mounted() {
      if (this.legendTitle) {
        setTimeout(() => {
          if (this.nn === 1)
            window.$('.apexcharts-canvas .apexcharts-legend').first().prepend(`<h5>${this.legendTitle}</h5>`);
          else window.$('.apexcharts-canvas .apexcharts-legend').last().prepend(`<h5>${this.legendTitle}</h5>`);
        }, 0);
      }
    },
  };
</script>

<style lang="scss">
  .customDonutStyles {
    .apexcharts-legend.apx-legend-position-bottom .apexcharts-legend-series,
    .apexcharts-legend.apx-legend-position-top .apexcharts-legend-series {
      width: 20%;
    }
  }
  @media (max-width: 425px) {
    .customDonutStyles {
      .apexcharts-legend.apx-legend-position-bottom .apexcharts-legend-series,
      .apexcharts-legend.apx-legend-position-top .apexcharts-legend-series {
        width: 45%;
      }
    }
  }
  @media (max-width: 375px) {
    .customDonutStyles {
      .apexcharts-legend.apx-legend-position-bottom .apexcharts-legend-series,
      .apexcharts-legend.apx-legend-position-top .apexcharts-legend-series {
        width: 100%;
      }
    }
  }
</style>
@michaelhthomas
Copy link

This might be relevant: vuejs/language-tools#1670

@wucdbm
Copy link

wucdbm commented Jan 27, 2024

Happens when we have '$$$' as a value of an object property

When we changed that to `$$$`, it reformatted it as `$<script lang="ts">

@wucdbm
Copy link

wucdbm commented Jan 27, 2024

PS The moment I removed the string literal containing the $ Dollar Signs, it formatted it perfectly

I hope that helps investigating further, I am quite lost on how any of this works

adamDilger added a commit to adamDilger/prettier-plugin-sort-imports that referenced this issue Feb 14, 2024
@adamDilger
Copy link

adamDilger commented Feb 14, 2024

I've stumbled across this issue also, I've tracked it down to dollar sign replacement groups inside the string producing this error, as even this caused the bug

<script setup>
'$';
</script>

PR submitted!

#283

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants