renusify 2.3.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,13 @@
1
1
  <template>
2
- <div class="d-flex flex-wrap">
3
- <r-btn v-for="i in 12"
2
+ <div class="d-flex flex-wrap h-space-around">
3
+ <r-btn v-for="i in ls"
4
4
  :key="i"
5
5
  outlined
6
- class="w-30 ma-2"
7
- :class="{'color-one-text':i+p===modelValue}"
8
- @click.prevent="emit(i+p)">
6
+ class="w-25 ma-1"
7
+ :class="{'color-one':i===modelValue}"
8
+ @click.prevent="emit(i)">
9
9
  {{
10
- $d(new Date(year, i + p, 1, 0, timezoneOffset), 'month', locale)
10
+ $d(new Date(year, i, 1, 0, timezoneOffset), 'month', locale)
11
11
  }}
12
12
  </r-btn>
13
13
  </div>
@@ -22,17 +22,41 @@ export default {
22
22
  month: Number,
23
23
  year: Number
24
24
  },
25
- emits:['update:modelValue'],
25
+ emits: ['update:modelValue'],
26
26
  data() {
27
27
  return {
28
- p: 0
28
+ ls: []
29
29
  }
30
30
  },
31
31
  beforeMount() {
32
- const c = this.$d(new Date(this.year, 1, 1, 0, this.timezoneOffset), 'me', this.locale)
33
- if (c > 1) {
34
- this.p = (1 - c)
32
+ const year = this.$d(new Date(this.year, this.month, 5, 0, this.timezoneOffset), 'ye', this.locale)
33
+ let ls = []
34
+ let first = 0
35
+ let n = 0
36
+ while (true) {
37
+ n++
38
+ if (n > 100) {
39
+ break
40
+ }
41
+ const y = this.$d(new Date(this.year, first, 5, 0, this.timezoneOffset), 'ye', this.locale)
42
+ const m = parseInt(this.$d(new Date(this.year, first, 5, 0, this.timezoneOffset), 'me', this.locale))
43
+ if (y === year && m === 1) {
44
+ break
45
+ }
46
+ if (y > year) {
47
+ first--
48
+ } else if (y < year) {
49
+ first++
50
+ } else if (m > 1) {
51
+ first--
52
+ } else {
53
+ first++
54
+ }
35
55
  }
56
+ for (let i = 0; i < 12; i++) {
57
+ ls.push(first + i)
58
+ }
59
+ this.ls = ls
36
60
  },
37
61
  methods: {
38
62
  emit(n) {
@@ -1,13 +1,13 @@
1
1
  <template>
2
- <div class="d-flex flex-wrap">
3
- <r-btn v-for="i in 12"
2
+ <div class="date-picker-year d-flex flex-wrap h-space-around">
3
+ <r-btn v-for="i in 200"
4
4
  :key="i"
5
- class="w-30 ma-2"
6
- :class="{'color-one-text':modelValue+i-6===modelValue}"
5
+ class="w-25 ma-1"
6
+ :class="{'color-one year-select':modelValue+i-100===modelValue}"
7
7
  outlined
8
- @click.prevent="emit(modelValue+i-6)">
8
+ @click.prevent="emit(modelValue+i-100)">
9
9
  {{
10
- $d(new Date(modelValue + i - 6, 1, 1, 0, timezoneOffset), 'year', locale)
10
+ $d(new Date(modelValue + i - 100, month, 5, 0, timezoneOffset), 'year', locale)
11
11
  }}
12
12
  </r-btn>
13
13
  </div>
@@ -22,10 +22,16 @@ export default {
22
22
  month: Number
23
23
  },
24
24
  emits:['update:modelValue'],
25
+ mounted() {
26
+ let el = document.querySelector('.year-select')
27
+ if (el) {
28
+ el.scrollIntoView(true)
29
+ }
30
+ },
25
31
  methods: {
26
32
  emit(n) {
27
- this.$emit('update:modelValue', n)
33
+ this.$emit('update:modelValue', n - this.modelValue)
28
34
  }
29
35
  }
30
36
  }
31
- </script>
37
+ </script>
@@ -1,4 +1,5 @@
1
1
  export * as rGroupInput from './index.vue'
2
2
 
3
3
  export * as l_btn from '../../button/index.js'
4
- export * as l_icon from '../../icon/index.js'
4
+ export * as l_icon from '../../icon/index.js'
5
+ export * as d_sortable from '../../../directive/sortable/index.js'
@@ -4,6 +4,7 @@
4
4
  hide>
5
5
  <div class="w-full">
6
6
  <span v-if="label" class="group-input-label">{{ label }}</span>
7
+ <div :key="key" v-sortable="{grab:'.grab-btn-group-input',end:end}">
7
8
  <div class="group-holder" v-for="(item,i) in modelValue" :key="i">
8
9
  <div class="group-slot">
9
10
  <slot :item="item" :index="i" :disableDel="disDel">
@@ -17,18 +18,15 @@
17
18
  </slot>
18
19
  </div>
19
20
  <div class="group-action">
20
- <r-btn icon text>
21
- <r-icon v-html="$r.icons.chevron_up" :class="{'icon-disabled':i===0}" @click.prevent="up(i)"></r-icon>
22
- </r-btn>
23
- <r-btn icon text>
24
- <r-icon v-html="$r.icons.chevron_down" :class="{'icon-disabled':i===modelValue.length-1}"
25
- @click.prevent="down(i)"></r-icon>
21
+ <r-btn icon text class="grab-btn-group-input">
22
+ <r-icon v-html="$r.icons.drag"></r-icon>
26
23
  </r-btn>
27
24
  <r-btn v-if="!disableItems.includes(itemKey?item[itemKey]:'')" icon text @click.prevent="del(i)">
28
25
  <r-icon v-html="$r.icons.delete" class="color-error-text"></r-icon>
29
26
  </r-btn>
30
27
  </div>
31
28
  </div>
29
+ </div>
32
30
  <div class="mt-5" :class="addBtnClass">
33
31
  <transition name="scale">
34
32
  <r-btn v-if="show_add" class="color-success" icon @click.prevent="add">
@@ -55,6 +53,7 @@ export default {
55
53
  emits:['update:modelValue','add','delete'],
56
54
  data() {
57
55
  return {
56
+ key: 0,
58
57
  disabledDel: {}
59
58
  }
60
59
  },
@@ -71,6 +70,14 @@ export default {
71
70
  }
72
71
  },
73
72
  methods: {
73
+ end(e) {
74
+ let a = []
75
+ for (let i = 0; i < e.length; i++) {
76
+ a.push(this.modelValue[parseInt(e[i])])
77
+ }
78
+ this.$emit('update:modelValue', a)
79
+ this.key++
80
+ },
74
81
  t(k) {
75
82
  if (this.translate) {
76
83
  return this.$t(k)
@@ -104,32 +111,6 @@ export default {
104
111
  this.$emit('delete', i)
105
112
  this.$emit('update:modelValue', a)
106
113
  },
107
- up(i) {
108
- if (i === 0) {
109
- return
110
- }
111
- let a = this.modelValue || []
112
- a = this.array_move(a, i, i - 1)
113
- this.$emit('update:modelValue', a)
114
- },
115
- down(i) {
116
- if (i === this.modelValue.length - 1) {
117
- return
118
- }
119
- let a = this.modelValue || []
120
- a = this.array_move(a, i, i + 1)
121
- this.$emit('update:modelValue', a)
122
- },
123
- array_move(arr, old_index, new_index) {
124
- if (new_index >= arr.length) {
125
- let k = new_index - arr.length + 1;
126
- while (k--) {
127
- arr.push(undefined);
128
- }
129
- }
130
- arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
131
- return arr;
132
- }
133
114
  }
134
115
  }
135
116
  </script>
@@ -65,13 +65,13 @@
65
65
  :rows="modelValue?Object.keys(modelValue).length+5:5"
66
66
  @keydown="setTab"
67
67
  ></textarea>
68
- <div class="text-preview" v-html="build"></div>
68
+ <div class="text-preview" v-html="code"></div>
69
69
  </div>
70
70
  </div>
71
71
  </template>
72
72
  <script>
73
73
  import {defineAsyncComponent} from 'vue'
74
- import mixin from '../../codeEditor/mixin.js'
74
+ import mixin from '../../highlight/mixin.js'
75
75
 
76
76
  export default {
77
77
  name: 'r-json',
@@ -105,9 +105,15 @@ export default {
105
105
  modeForm: true,
106
106
  error: false,
107
107
  show: false,
108
+ code: "",
108
109
  info: {}
109
110
  }
110
111
  },
112
+ async created() {
113
+ if (this.modelValue) {
114
+ await this.build_code()
115
+ }
116
+ },
111
117
  watch: {
112
118
  modeForm: function () {
113
119
  this.lazyValue = JSON.stringify(this.modelValue || {}, null, 4)
@@ -123,9 +129,10 @@ export default {
123
129
  }
124
130
 
125
131
  },
126
- lazyValue: function () {
132
+ lazyValue: async function () {
127
133
  try {
128
134
  this.error = false
135
+ await this.build_code()
129
136
  this.$emit('update:modelValue', JSON.parse(this.lazyValue))
130
137
  } catch (er) {
131
138
  this.error = true
@@ -139,17 +146,6 @@ export default {
139
146
  }
140
147
  return this.tile
141
148
  },
142
- build() {
143
- if (!this.lazyValue) {
144
- return "";
145
- }
146
- let res = this.lazyValue
147
- res = this.re_quote(res);
148
- res = this.re_words(res, [true, false, null]);
149
- res = this.re_number(res);
150
- res = this.re_special(res, /([{},:\[\]])/g, 'color-orange');
151
- return res;
152
- },
153
149
  is_array() {
154
150
  if (this.baseArray) {
155
151
  return true
@@ -158,6 +154,9 @@ export default {
158
154
  }
159
155
  },
160
156
  methods: {
157
+ async build_code() {
158
+ this.code = await this.highlight(this.lazyValue, "json", true)
159
+ },
161
160
  open() {
162
161
  if (this.template) {
163
162
  let d = this.modelValue
@@ -288,18 +287,29 @@ export default {
288
287
  overflow: hidden;
289
288
  }
290
289
 
291
- .color-orange {
290
+
291
+ .highlight-syn-deleted,
292
+ .highlight-syn-err,
293
+ .highlight-syn-var {
292
294
  color: var(--color-error);
293
295
  }
294
296
 
295
- .color-green {
296
- color: var(--color-success);
297
- }
298
297
 
298
+ .highlight-syn-insert,
299
+ .highlight-syn-type,
300
+ .highlight-syn-func,
301
+ .highlight-syn-bool {
302
+ color: var(--color-warning);
303
+ }
299
304
 
300
- .color-blue {
305
+ .highlight-syn-num, .highlight-numbers {
301
306
  color: var(--color-info);
302
307
  }
308
+
309
+
310
+ .highlight-syn-str {
311
+ color: var(--color-success);
312
+ }
303
313
  }
304
314
  }
305
315
  </style>
@@ -68,7 +68,7 @@
68
68
  <r-icon v-html="$r.icons.delete"></r-icon>
69
69
  </r-btn>
70
70
  <r-img
71
- :src="'/'+img"
71
+ :src="img"
72
72
  alt="img"
73
73
  height="100"></r-img>
74
74
  </div>
@@ -117,6 +117,7 @@
117
117
  :headers="headers"
118
118
  :label="$t('image','renusify')"
119
119
  :size="1"
120
+ :rules="['required']"
120
121
  :upload-link="uploadLink"
121
122
  accept="image/*"></r-file-input>
122
123
  <r-text-input v-model="img_alt"
@@ -124,8 +125,6 @@
124
125
  :rules="['required']"></r-text-input>
125
126
  <r-number-input v-model="img_width" :label="$t('width','renusify')"
126
127
  :rules="['required']"></r-number-input>
127
- <r-number-input v-model="img_height" :label="$t('height','renusify')"
128
- :rules="['required']"></r-number-input>
129
128
  <r-row class="h-end">
130
129
  <r-col class="col-auto">
131
130
  <r-btn class="color-error-text"
@@ -153,6 +152,7 @@
153
152
  :headers="headers"
154
153
  :label="$t('video','renusify')"
155
154
  :size="1"
155
+ :rules="['required']"
156
156
  :upload-link="uploadLink"
157
157
  accept="video/mp4,video/webm"></r-file-input>
158
158
  <r-number-input v-model="img_width" :label="$t('width','renusify')"
@@ -177,16 +177,46 @@
177
177
  </r-container>
178
178
  </r-form>
179
179
  </r-modal>
180
+ <r-modal v-model="showPre"
181
+ :closable="false"
182
+ :closebtn="false">
183
+ <r-form v-model="valid2">
184
+ <r-container>
185
+ <r-select-input v-model="lang" :items="langs"
186
+ :label="$t('lang','renusify')"
187
+ :rules="['required']"
188
+ just-value></r-select-input>
189
+ <r-text-area v-model="code"
190
+ :label="$t('code','renusify')"
191
+ :rules="['required']"
192
+ ltr></r-text-area>
193
+ <div class="text-end my-3">
194
+ <r-btn class="color-error-text"
195
+ outlined
196
+ @click.prevent="showPre=false">{{ $t('cancel', 'renusify') }}
197
+ </r-btn>
198
+ <r-btn :disabled="!valid2"
199
+ class="color-success-text ms-2"
200
+ outlined
201
+ @click.prevent="handlePreForm()">{{ $t('send', 'renusify') }}
202
+ </r-btn>
203
+ </div>
204
+ </r-container>
205
+ </r-form>
206
+ </r-modal>
180
207
 
181
208
  </r-container>
182
209
  </template>
183
210
 
184
211
  <script>
185
212
  import './style.scss'
213
+ import '../../highlight/style.scss'
214
+ import mixin from "../../highlight/mixin";
186
215
 
187
216
  export default {
188
217
  name: 'r-text-editor',
189
218
  inheritAttrs: false,
219
+ mixins: [mixin],
190
220
  props: {
191
221
  uploadLink: {type: String, default: '/storage'},
192
222
  modelValue: {
@@ -221,12 +251,15 @@ export default {
221
251
  preSelected: null,
222
252
  currentPath: [],
223
253
  selectElm: null,
254
+ code: '',
255
+ lang: null,
256
+ showPre: false,
257
+ langs: ['asm', 'bash', 'bf', 'c', 'css', 'csv', 'diff', 'docker', 'git', 'go', 'html', 'http', 'ini', 'java', 'js', 'jsdoc', 'json', 'log', 'lua', 'make', 'pl', 'plain', 'py', 'regex', 'rs', 'sql', 'todo', 'toml', 'ts', 'uri', 'xml', 'yaml'],
224
258
  items_undo: {
225
259
  'undo': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M12.5 8c-2.65 0-5.05 1-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88c3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8Z"/></svg>',
226
260
  'redo': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M18.4 10.6C16.55 9 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16a8.002 8.002 0 0 1 7.6-5.5c1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6 3.6Z"/></svg>',
227
261
  },
228
262
  items_handle: {
229
- 'DIV': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M13 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4h-2v6H9V4h4m0 6a2 2 0 0 0 2-2a2 2 0 0 0-2-2h-2v4h2Z"/></svg>',
230
263
  'insertDIV': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M4 6v13h16V6H4m14 11H6V8h12v9Z"/></svg>',
231
264
  'insertLINE': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M9 7h2v8h4v2H9V7m3-5a10 10 0 0 1 10 10a10 10 0 0 1-10 10A10 10 0 0 1 2 12A10 10 0 0 1 12 2m0 2a8 8 0 0 0-8 8a8 8 0 0 0 8 8a8 8 0 0 0 8-8a8 8 0 0 0-8-8Z"/></svg>',
232
265
  'BLOCKQUOTE': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4Z"/></svg>',
@@ -320,7 +353,7 @@ export default {
320
353
  document.execCommand('enableInlineTableEditing', false, true);
321
354
  document.execCommand('enableAbsolutePositionEditor', false, true) */
322
355
 
323
- this.format('defaultParagraphSeparator', 'div')
356
+ this.format('defaultParagraphSeparator', '\n')
324
357
  this.element.addEventListener('paste', function (e) {
325
358
  e.preventDefault()
326
359
  const text = (e.originalEvent || e).clipboardData.getData('text/plain')
@@ -421,7 +454,7 @@ export default {
421
454
  let sel = this.getSelection()
422
455
  sel.removeAllRanges()
423
456
  sel.addRange(this.preSelected)
424
- let url = '<img src="/' + this.image[0] + '?w=' + this.img_width + '&h=' + this.img_height + '" alt="' + this.img_alt + '" width="' + this.img_width + '" height="' + this.img_height + '"/>'
457
+ let url = '<img src="' + this.image[0] + '?w=' + this.img_width + '" alt="' + this.img_alt + '" width="' + this.img_width + '" />'
425
458
  this.files.push(this.image[0])
426
459
  document.execCommand('insertHTML', true, url)
427
460
  this.showImg = false
@@ -434,11 +467,23 @@ export default {
434
467
  let sel = this.getSelection()
435
468
  sel.removeAllRanges()
436
469
  sel.addRange(this.preSelected)
437
- let url = '<video controls="1" src="/' + this.video[0] + '" width="' + this.img_width + '" height="' + this.img_height + '"></video>'
470
+ let url = '<video controls="1" src="' + this.video[0] + '" width="' + this.img_width + '" height="' + this.img_height + '"></video>'
438
471
  this.files.push(this.video[0])
439
472
  document.execCommand('insertHTML', true, url)
440
473
  this.showVideo = false
441
474
  },
475
+ async handlePreForm() {
476
+ if (!this.getSelection() || !this.code || !this.lang) {
477
+ this.$toast(this.$t('invalid_data', 'renusify'), {type: 'error'})
478
+ return
479
+ }
480
+ let sel = this.getSelection()
481
+ sel.removeAllRanges()
482
+ sel.addRange(this.preSelected)
483
+ let url = `<div class="${this.$r.prefix}highlight highlight-lang-${this.lang}" >${await this.highlight(this.code, this.lang)}</div>`
484
+ document.execCommand('insertHTML', true, url)
485
+ this.showPre = false
486
+ },
442
487
  handleForm() {
443
488
  if (!this.getSelection() || !this.link) {
444
489
  this.$toast(this.$t('invalid_data', 'renusify'), {type: 'error'})
@@ -449,7 +494,7 @@ export default {
449
494
  sel.addRange(this.preSelected)
450
495
  let url = '<a href="' + this.link.trim() + '"'
451
496
  if (this.target) {
452
- url += 'target="_blank"'
497
+ url += 'target="_blank" rel="nofollow"'
453
498
  }
454
499
  if (this.link.startsWith('#')) {
455
500
  url += `id="${this.link.replace('#', '')}"`
@@ -518,6 +563,11 @@ export default {
518
563
  this.target = false
519
564
  this.handleOpen(true)
520
565
  this.show = true
566
+ } else if (e === 'PRE') {
567
+ this.code = ''
568
+ this.lang = null
569
+ this.handleOpen(true)
570
+ this.showPre = true
521
571
  } else if (e === 'insertImage') {
522
572
  this.image = []
523
573
  this.img_alt = null
@@ -51,6 +51,12 @@
51
51
  min-height: 20px;
52
52
  border: 1px solid rgba(150, 150, 150, 0.6);
53
53
  }
54
+
55
+ .r-highlight div {
56
+ min-width: unset;
57
+ min-height: unset;
58
+ border: unset;
59
+ }
54
60
  }
55
61
 
56
62
  .img-holder {
@@ -0,0 +1 @@
1
+ export * as rHighlight from './index.vue'
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <div :class="`${$r.prefix}highlight highlight-lang-${lang}`" v-html='txt'></div>
3
+ </template>
4
+ <script>
5
+ import './style.scss'
6
+ import mixin from "./mixin";
7
+
8
+ export default {
9
+ name: 'highlight',
10
+ mixins: [mixin],
11
+ props: {
12
+ src: String,
13
+ hideLineNumbers: Boolean,
14
+ lang: {
15
+ type: String,
16
+ validator: function (value) {
17
+ return ['asm', 'bash', 'bf', 'c', 'css', 'csv', 'diff', 'docker', 'git', 'go', 'html', 'http', 'ini', 'java', 'js', 'jsdoc', 'json', 'log', 'lua', 'make', 'pl', 'plain', 'py', 'regex', 'rs', 'sql', 'todo', 'toml', 'ts', 'uri', 'xml', 'yaml'].indexOf(value) !== -1
18
+ }
19
+ }
20
+ },
21
+ data() {
22
+ return {
23
+ txt: '',
24
+ }
25
+ },
26
+ async created() {
27
+ this.txt = await this.highlight(this.src, this.lang, this.hideLineNumbers);
28
+ }
29
+ }
30
+ </script>
31
+