1 | <script>
|
2 |
|
3 |
|
4 | import * as Babel from '@babel/standalone';
|
5 | import BootstrapVue from 'bootstrap-vue';
|
6 | import copyToClipboard from 'copy-to-clipboard';
|
7 | import hljs from 'highlight.js';
|
8 | import { html } from 'js-beautify';
|
9 | import Vue from 'vue';
|
10 | import { parseComponent } from 'vue-template-compiler';
|
11 | import 'highlight.js/styles/monokai.css';
|
12 | import { gitlabComponents } from '../all_components';
|
13 | import * as Documentation from '../components_documentation';
|
14 |
|
15 |
|
16 |
|
17 | Vue.use(BootstrapVue);
|
18 | Object.keys(gitlabComponents).forEach((comp) => {
|
19 | if (!comp.includes('Directive')) {
|
20 | Vue.component(comp, gitlabComponents[comp]);
|
21 | }
|
22 | });
|
23 |
|
24 |
|
25 | Vue.directive('gl-tooltip', gitlabComponents.GlTooltipDirective);
|
26 | Vue.directive('gl-modal-directive', gitlabComponents.GlModalDirective);
|
27 | Vue.directive('gl-resize-observer-directive', gitlabComponents.GlResizeObserverDirective);
|
28 | Vue.directive('gl-safe-html-directive', gitlabComponents.GlSafeHtmlDirective);
|
29 | Vue.directive('gl-collapse-toggle', gitlabComponents.GlCollapseToggleDirective);
|
30 |
|
31 | function findComponentExample(exampleName) {
|
32 |
|
33 |
|
34 | for (const component of Object.values(Documentation)) {
|
35 | if (component.examples) {
|
36 |
|
37 | for (const exampleGroup of component.examples) {
|
38 | const foundExample = exampleGroup.items.find((example) => example.id === exampleName);
|
39 | if (foundExample) {
|
40 | return foundExample;
|
41 | }
|
42 | }
|
43 | }
|
44 | }
|
45 |
|
46 | return null;
|
47 | }
|
48 |
|
49 | const animationTimeout = 2000;
|
50 |
|
51 | export default {
|
52 | props: {
|
53 | exampleName: {
|
54 | type: String,
|
55 | required: true,
|
56 | },
|
57 | },
|
58 | data() {
|
59 | return {
|
60 | source: '',
|
61 | renderedHtml: '',
|
62 | copiedSource: false,
|
63 | copiedOutput: false,
|
64 | };
|
65 | },
|
66 | computed: {
|
67 |
|
68 | currentExampleComponent() {
|
69 |
|
70 | const foundExample = findComponentExample(this.exampleName);
|
71 |
|
72 |
|
73 |
|
74 | if (foundExample && foundExample !== undefined) {
|
75 | const base = {
|
76 | name: '',
|
77 | template: '<div></div>',
|
78 | };
|
79 | try {
|
80 |
|
81 | const parsed = parseComponent(foundExample.component);
|
82 |
|
83 | let compiled = {};
|
84 | if (parsed.script) {
|
85 |
|
86 | const { code } = Babel.transform(parsed.script.content, {
|
87 | presets: ['es2015', ['stage-2', { decoratorsBeforeExport: false }]],
|
88 | });
|
89 | compiled = eval(`const exports = {};${code}`);
|
90 | }
|
91 |
|
92 |
|
93 | compiled.template = parsed.template.content;
|
94 |
|
95 | this.source = compiled.template;
|
96 |
|
97 | return { ...base, ...compiled };
|
98 | } catch (e) {
|
99 |
|
100 | console.log('ERR : ', e);
|
101 | return base;
|
102 | }
|
103 | }
|
104 | return null;
|
105 | },
|
106 | exampleHTMLOutput() {
|
107 | return this.$refs.exampleComponent || '';
|
108 | },
|
109 | sourceFormatted() {
|
110 | if (this.source) {
|
111 | return hljs.fixMarkup(hljs.highlight('html', this.source).value);
|
112 | }
|
113 | return '';
|
114 | },
|
115 | renderedHtmlFormatted() {
|
116 | if (this.renderedHtml) {
|
117 | return hljs.fixMarkup(hljs.highlight('html', this.renderedHtml).value);
|
118 | }
|
119 | return '';
|
120 | },
|
121 | },
|
122 | watch: {
|
123 | currentExampleComponent() {
|
124 | Vue.nextTick(() => {
|
125 | this.setHtml();
|
126 | });
|
127 | },
|
128 | },
|
129 | created() {
|
130 |
|
131 | hljs.configure({ tabReplace: ' ', useBR: true });
|
132 | },
|
133 | mounted() {
|
134 | this.setHtml();
|
135 | },
|
136 | methods: {
|
137 | setHtml() {
|
138 | if (this.$refs.compiled) {
|
139 | const markup = this.$refs.compiled.$el.outerHTML;
|
140 | if (markup) {
|
141 |
|
142 | const preFormattedHTML = markup.replace(/><(?!\/i|\/label|\/span|option)/g, '>\n<');
|
143 | this.renderedHtml = html(preFormattedHTML, {
|
144 | indent_size: 2,
|
145 | indent_char: ' ',
|
146 | wrap_attributes: 'auto',
|
147 | wrap_attributes_indent_size: 2,
|
148 | end_with_newline: false,
|
149 | });
|
150 | }
|
151 | }
|
152 | },
|
153 | copySource() {
|
154 | copyToClipboard(this.source);
|
155 | this.copiedSource = true;
|
156 | setTimeout(() => {
|
157 | this.copiedSource = false;
|
158 | }, animationTimeout);
|
159 | },
|
160 | copyHtml() {
|
161 | copyToClipboard(this.renderedHtml);
|
162 | this.copiedOutput = true;
|
163 | setTimeout(() => {
|
164 | this.copiedOutput = false;
|
165 | }, animationTimeout);
|
166 | },
|
167 | },
|
168 | };
|
169 | </script>
|
170 |
|
171 | <template>
|
172 | <div>
|
173 | <div v-if="currentExampleComponent">
|
174 | <b-card no-body>
|
175 | <div slot="header">
|
176 | <b-row>
|
177 | <b-col>
|
178 | <strong>{{ exampleName }}</strong>
|
179 | </b-col>
|
180 | <b-col class="text-right">
|
181 | <b-button-group size="sm" class="mx-1">
|
182 | <b-btn v-b-toggle.collapseSource>Source</b-btn>
|
183 | <b-btn v-b-toggle.collapseHTML>HTML</b-btn>
|
184 | </b-button-group>
|
185 | </b-col>
|
186 | </b-row>
|
187 | </div>
|
188 | <b-card-body>
|
189 | <div :is="currentExampleComponent" ref="compiled" />
|
190 | </b-card-body>
|
191 | <b-list-group flush>
|
192 | <b-collapse id="collapseSource" class="mt-2">
|
193 | <b-list-group-item>
|
194 | <b-row>
|
195 | <b-col cols="8"><h6>Source</h6></b-col>
|
196 | <b-col class="text-right">
|
197 | <template v-if="copiedSource">Copied!</template>
|
198 | <b-button-group size="sm">
|
199 | <b-button :disabled="copiedSource" @click="copySource">Copy</b-button>
|
200 | </b-button-group>
|
201 | </b-col>
|
202 | </b-row>
|
203 | <code class="hljs html" v-html="sourceFormatted"></code>
|
204 | </b-list-group-item>
|
205 | </b-collapse>
|
206 | <b-collapse id="collapseHTML" class="mt-2">
|
207 | <b-list-group-item>
|
208 | <b-row>
|
209 | <b-col cols="8"><h6>HTML Output</h6></b-col>
|
210 | <b-col class="text-right">
|
211 | <template v-if="copiedOutput">Copied!</template>
|
212 | <b-button-group size="sm">
|
213 | <b-button :disabled="copiedOutput" @click="copyHtml">Copy</b-button>
|
214 | </b-button-group>
|
215 | </b-col>
|
216 | </b-row>
|
217 | <code class="hljs html" v-html="renderedHtmlFormatted"></code>
|
218 | </b-list-group-item>
|
219 | </b-collapse>
|
220 | </b-list-group>
|
221 | </b-card>
|
222 | </div>
|
223 | <b-alert v-else-if="exampleName" show variant="warning"
|
224 | >No Example found with the name "{{ exampleName }}"</b-alert
|
225 | >
|
226 | </div>
|
227 | </template>
|