From 9325c01fec04807d05a4b8ff4c03ce4522ebaa8c Mon Sep 17 00:00:00 2001
From: Miguel Rincon <mrincon@gitlab.com>
Date: Wed, 8 Feb 2023 15:42:51 +0100
Subject: [PATCH] Render SVG images with "?path" in an <img> tag

Previously we always loaded all the svg files using the raw-loader
which fetches the entire svg body to add it inline inside an our HTML.
This a very flexible way to load them that has the advantage of allowing our client side code to manipulate the SVGs (such as adding styles).

However, this requires us to use v-safe-html to place the SVG inside
our markup, and makes SVG images work differently from other like PNG
and JPG.

This MR has our SVGs loaded as before by default, but allows us to
opt-in by adding a ?path query at the end of the import so it can be
loaded as any old image.
---
 .../ci/runner/admin_new_runner/index.js       |  7 +------
 .../runner_platforms_radio_group.vue          | 19 +++++++++++++++----
 app/views/admin/runners/new.html.haml         |  6 +-----
 config/webpack.config.js                      | 14 +++++++++++++-
 jest.config.base.js                           |  1 +
 .../runner_platforms_radio_group_spec.js      |  6 +++---
 6 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/app/assets/javascripts/ci/runner/admin_new_runner/index.js b/app/assets/javascripts/ci/runner/admin_new_runner/index.js
index 7aca19572b357..502d9d33b4d4a 100644
--- a/app/assets/javascripts/ci/runner/admin_new_runner/index.js
+++ b/app/assets/javascripts/ci/runner/admin_new_runner/index.js
@@ -12,7 +12,7 @@ export const initAdminNewRunner = (selector = '#js-admin-new-runner') => {
     return null;
   }
 
-  const { legacyRegistrationToken, awsImgPath, dockerImgPath, kubernetesImgPath } = el.dataset;
+  const { legacyRegistrationToken } = el.dataset;
 
   const apolloProvider = new VueApollo({
     defaultClient: createDefaultClient(),
@@ -21,11 +21,6 @@ export const initAdminNewRunner = (selector = '#js-admin-new-runner') => {
   return new Vue({
     el,
     apolloProvider,
-    provide: {
-      awsImgPath,
-      dockerImgPath,
-      kubernetesImgPath,
-    },
     render(h) {
       return h(AdminNewRunnerApp, {
         props: {
diff --git a/app/assets/javascripts/ci/runner/components/runner_platforms_radio_group.vue b/app/assets/javascripts/ci/runner/components/runner_platforms_radio_group.vue
index 304fdadbca23e..273226141d2c7 100644
--- a/app/assets/javascripts/ci/runner/components/runner_platforms_radio_group.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_platforms_radio_group.vue
@@ -1,5 +1,9 @@
 <script>
+import AWS_LOGO_URL from '@gitlab/svgs/dist/illustrations/logos/aws.svg?url';
+import DOCKER_LOGO_URL from '@gitlab/svgs/dist/illustrations/third-party-logos/ci_cd-template-logos/docker.png';
+import KUBERNETES_LOGO_URL from '@gitlab/svgs/dist/illustrations/logos/kubernetes.svg?url';
 import { GlFormRadioGroup, GlIcon, GlLink } from '@gitlab/ui';
+
 import {
   LINUX_PLATFORM,
   MACOS_PLATFORM,
@@ -18,7 +22,6 @@ export default {
     GlIcon,
     RunnerPlatformsRadio,
   },
-  inject: ['awsImgPath', 'dockerImgPath', 'kubernetesImgPath'],
   props: {
     value: {
       type: String,
@@ -39,9 +42,13 @@ export default {
   LINUX_PLATFORM,
   MACOS_PLATFORM,
   WINDOWS_PLATFORM,
+
   AWS_PLATFORM,
+  AWS_LOGO_URL,
   DOCKER_HELP_URL,
+  DOCKER_LOGO_URL,
   KUBERNETES_HELP_URL,
+  KUBERNETES_LOGO_URL,
 };
 </script>
 
@@ -68,7 +75,11 @@ export default {
       <label>{{ s__('Runners|Cloud templates') }}</label>
       <!-- eslint-disable @gitlab/vue-require-i18n-strings -->
       <div class="gl-display-flex gl-flex-wrap gl-gap-5">
-        <runner-platforms-radio v-model="model" :image="awsImgPath" :value="$options.AWS_PLATFORM">
+        <runner-platforms-radio
+          v-model="model"
+          :image="$options.AWS_LOGO_URL"
+          :value="$options.AWS_PLATFORM"
+        >
           AWS
         </runner-platforms-radio>
       </div>
@@ -79,13 +90,13 @@ export default {
 
       <div class="gl-display-flex gl-flex-wrap gl-gap-5">
         <!-- eslint-disable @gitlab/vue-require-i18n-strings -->
-        <runner-platforms-radio :image="dockerImgPath">
+        <runner-platforms-radio :image="$options.DOCKER_LOGO_URL">
           <gl-link :href="$options.DOCKER_HELP_URL" target="_blank">
             Docker
             <gl-icon name="external-link" />
           </gl-link>
         </runner-platforms-radio>
-        <runner-platforms-radio :image="kubernetesImgPath">
+        <runner-platforms-radio :image="$options.KUBERNETES_LOGO_URL">
           <gl-link :href="$options.KUBERNETES_HELP_URL" target="_blank">
             Kubernetes
             <gl-icon name="external-link" />
diff --git a/app/views/admin/runners/new.html.haml b/app/views/admin/runners/new.html.haml
index cf5638d0294e0..12a569862e6e8 100644
--- a/app/views/admin/runners/new.html.haml
+++ b/app/views/admin/runners/new.html.haml
@@ -2,8 +2,4 @@
 - breadcrumb_title s_('Runner|New')
 - page_title s_('Runners|Create an instance runner')
 
-#js-admin-new-runner{ data: {
-  legacy_registration_token: Gitlab::CurrentSettings.runners_registration_token,
-  aws_img_path: image_path('illustrations/logos/aws.svg'),
-  kubernetes_img_path: image_path('illustrations/logos/kubernetes.svg'),
-  docker_img_path: image_path('illustrations/third-party-logos/ci_cd-template-logos/docker.png') } }
+#js-admin-new-runner{ data: { legacy_registration_token: Gitlab::CurrentSettings.runners_registration_token } }
diff --git a/config/webpack.config.js b/config/webpack.config.js
index fd58e22bb996c..8ae803ca738f2 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -380,7 +380,19 @@ module.exports = {
       {
         test: /\.svg$/,
         exclude: /icons\.svg$/,
-        loader: 'raw-loader',
+        oneOf: [
+          {
+            resourceQuery: /url/,
+            loader: 'file-loader',
+            options: {
+              name: '[name].[contenthash:8].[ext]',
+              esModule: false,
+            },
+          },
+          {
+            loader: 'raw-loader',
+          },
+        ],
       },
       {
         test: /\.(gif|png|mp4)$/,
diff --git a/jest.config.base.js b/jest.config.base.js
index 05967b51b88d5..26e7c8e8d1825 100644
--- a/jest.config.base.js
+++ b/jest.config.base.js
@@ -60,6 +60,7 @@ module.exports = (path, options = {}) => {
     [TEST_FIXTURES_PATTERN]: '<rootDir>/tmp/tests/frontend/fixtures$1',
     '^test_fixtures_static(/.*)$': '<rootDir>/spec/frontend/fixtures/static$1',
     '\\.(jpg|jpeg|png|svg|css)$': '<rootDir>/spec/frontend/__mocks__/file_mock.js',
+    '\\.svg\\?url$': '<rootDir>/spec/frontend/__mocks__/file_mock.js',
     '^public(/.*)$': '<rootDir>/public$1',
     'emojis(/.*).json': '<rootDir>/fixtures/emojis$1.json',
     '^spec/test_constants$': '<rootDir>/spec/frontend/__helpers__/test_constants',
diff --git a/spec/frontend/ci/runner/components/runner_platforms_radio_group_spec.js b/spec/frontend/ci/runner/components/runner_platforms_radio_group_spec.js
index 12c9afe97583d..db6fd2c369bd8 100644
--- a/spec/frontend/ci/runner/components/runner_platforms_radio_group_spec.js
+++ b/spec/frontend/ci/runner/components/runner_platforms_radio_group_spec.js
@@ -51,9 +51,9 @@ describe('RunnerPlatformsRadioGroup', () => {
       ['Linux', null],
       ['macOS', null],
       ['Windows', null],
-      ['AWS', mockProvide.awsImgPath],
-      ['Docker', mockProvide.dockerImgPath],
-      ['Kubernetes', mockProvide.kubernetesImgPath],
+      ['AWS', expect.any(String)],
+      ['Docker', expect.any(String)],
+      ['Kubernetes', expect.any(String)],
     ]);
   });
 
-- 
GitLab