mihari 5.2.4 → 5.3.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.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/README.md +0 -10
- data/Rakefile +7 -1
- data/build_frontend.sh +1 -1
- data/frontend/.eslintrc.cjs +22 -0
- data/frontend/.gitignore +18 -12
- data/frontend/.prettierrc.json +8 -0
- data/frontend/env.d.ts +5 -0
- data/frontend/package-lock.json +5095 -9661
- data/frontend/package.json +34 -24
- data/frontend/src/App.vue +5 -5
- data/frontend/src/api-helper.ts +38 -40
- data/frontend/src/api.ts +40 -40
- data/frontend/src/components/ErrorMessage.vue +8 -8
- data/frontend/src/components/Loading.vue +3 -3
- data/frontend/src/components/Navbar.vue +10 -27
- data/frontend/src/components/Pagination.vue +35 -42
- data/frontend/src/components/alert/Alert.vue +21 -26
- data/frontend/src/components/alert/Alerts.vue +23 -25
- data/frontend/src/components/alert/AlertsWithPagination.vue +34 -34
- data/frontend/src/components/alert/AlertsWrapper.vue +42 -49
- data/frontend/src/components/alert/Form.vue +39 -40
- data/frontend/src/components/artifact/AS.vue +7 -7
- data/frontend/src/components/artifact/Artifact.vue +66 -83
- data/frontend/src/components/artifact/ArtifactTag.vue +21 -27
- data/frontend/src/components/artifact/ArtifactTags.vue +8 -8
- data/frontend/src/components/artifact/ArtifactWrapper.vue +22 -25
- data/frontend/src/components/artifact/CPEs.vue +6 -6
- data/frontend/src/components/artifact/DnsRecords.vue +9 -9
- data/frontend/src/components/artifact/Ports.vue +6 -6
- data/frontend/src/components/artifact/ReverseDnsNames.vue +7 -7
- data/frontend/src/components/artifact/Tags.vue +6 -6
- data/frontend/src/components/artifact/WhoisRecord.vue +7 -9
- data/frontend/src/components/config/Configs.vue +7 -10
- data/frontend/src/components/config/ConfigsWrapper.vue +14 -20
- data/frontend/src/components/link/Link.vue +7 -7
- data/frontend/src/components/link/Links.vue +16 -21
- data/frontend/src/components/rule/EditRule.vue +22 -22
- data/frontend/src/components/rule/EditRuleWrapper.vue +22 -28
- data/frontend/src/components/rule/Form.vue +28 -28
- data/frontend/src/components/rule/InputForm.vue +31 -25
- data/frontend/src/components/rule/NewRule.vue +18 -18
- data/frontend/src/components/rule/Rule.vue +25 -27
- data/frontend/src/components/rule/RuleWrapper.vue +24 -31
- data/frontend/src/components/rule/Rules.vue +26 -30
- data/frontend/src/components/rule/RulesWrapper.vue +39 -42
- data/frontend/src/components/rule/YAML.vue +19 -22
- data/frontend/src/components/tag/Tag.vue +24 -32
- data/frontend/src/components/tag/Tags.vue +11 -11
- data/frontend/src/countries.ts +23 -23
- data/frontend/src/index.ts +9 -12
- data/frontend/src/links/anyrun.ts +10 -10
- data/frontend/src/links/base.ts +3 -3
- data/frontend/src/links/censys.ts +10 -10
- data/frontend/src/links/crtsh.ts +10 -10
- data/frontend/src/links/dnslytics.ts +18 -18
- data/frontend/src/links/greynoise.ts +10 -10
- data/frontend/src/links/index.ts +15 -15
- data/frontend/src/links/intezer.ts +10 -10
- data/frontend/src/links/otx.ts +14 -14
- data/frontend/src/links/securitytrails.ts +15 -15
- data/frontend/src/links/shodan.ts +10 -10
- data/frontend/src/links/urlscan.ts +19 -19
- data/frontend/src/links/virustotal.ts +27 -27
- data/frontend/src/main.ts +8 -8
- data/frontend/src/router/index.ts +20 -20
- data/frontend/src/rule.ts +6 -6
- data/frontend/src/shims-vue.d.ts +2 -2
- data/frontend/src/types.ts +91 -91
- data/frontend/src/utils.ts +23 -29
- data/frontend/src/views/Alerts.vue +7 -7
- data/frontend/src/views/Artifact.vue +17 -17
- data/frontend/src/views/Configs.vue +7 -7
- data/frontend/src/views/EditRule.vue +17 -17
- data/frontend/src/views/NewRule.vue +10 -10
- data/frontend/src/views/Rule.vue +17 -17
- data/frontend/src/views/Rules.vue +7 -7
- data/frontend/tests/utils.spec.ts +9 -0
- data/frontend/tsconfig.app.json +21 -0
- data/frontend/tsconfig.json +10 -36
- data/frontend/tsconfig.node.json +13 -0
- data/frontend/tsconfig.vitest.json +12 -0
- data/frontend/vite.config.ts +24 -0
- data/frontend/vitest.config.ts +21 -0
- data/lefthook.yml +4 -2
- data/lib/mihari/analyzers/base.rb +48 -14
- data/lib/mihari/analyzers/binaryedge.rb +10 -15
- data/lib/mihari/analyzers/censys.rb +12 -15
- data/lib/mihari/analyzers/circl.rb +10 -10
- data/lib/mihari/analyzers/crtsh.rb +10 -6
- data/lib/mihari/analyzers/dnstwister.rb +6 -8
- data/lib/mihari/analyzers/feed.rb +21 -10
- data/lib/mihari/analyzers/greynoise.rb +10 -20
- data/lib/mihari/analyzers/onyphe.rb +9 -14
- data/lib/mihari/analyzers/otx.rb +8 -9
- data/lib/mihari/analyzers/passivetotal.rb +10 -10
- data/lib/mihari/analyzers/pulsedive.rb +21 -31
- data/lib/mihari/analyzers/securitytrails.rb +8 -6
- data/lib/mihari/analyzers/shodan.rb +8 -13
- data/lib/mihari/analyzers/urlscan.rb +15 -20
- data/lib/mihari/analyzers/virustotal.rb +16 -26
- data/lib/mihari/analyzers/virustotal_intelligence.rb +11 -17
- data/lib/mihari/analyzers/zoomeye.rb +12 -17
- data/lib/mihari/config.rb +133 -0
- data/lib/mihari/constants.rb +3 -0
- data/lib/mihari/emitters/slack.rb +13 -3
- data/lib/mihari/errors.rb +1 -1
- data/lib/mihari/http.rb +2 -3
- data/lib/mihari/schemas/analyzer.rb +2 -0
- data/lib/mihari/type_checker.rb +6 -6
- data/lib/mihari/version.rb +1 -1
- data/lib/mihari/web/endpoints/configs.rb +5 -1
- data/lib/mihari/web/public/assets/{index-eed1bcd8.css → index-2ba8f0a6.css} +1 -1
- data/lib/mihari/web/public/assets/{index-ac4e5ffa.js → index-71285b15.js} +16 -16
- data/lib/mihari/web/public/index.html +2 -2
- data/lib/mihari/web/public/redoc-static.html +388 -2193
- data/lib/mihari.rb +9 -59
- data/mihari.gemspec +8 -8
- metadata +24 -62
- data/frontend/.browserslistrc +0 -3
- data/frontend/.eslintrc.js +0 -33
- data/frontend/babel.config.js +0 -3
- data/frontend/jest.config.js +0 -9
- data/frontend/tests/unit/utils.spec.ts +0 -7
- data/frontend/vite.config.js +0 -24
|
@@ -1,62 +1,55 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Loading v-if="getRuleTask.isRunning"></Loading>
|
|
3
3
|
|
|
4
|
-
<ErrorMessage
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
></ErrorMessage>
|
|
8
|
-
|
|
9
|
-
<Rule
|
|
10
|
-
:rule="getRuleTask.last.value"
|
|
11
|
-
@refresh="refresh"
|
|
12
|
-
v-if="getRuleTask.last?.value"
|
|
13
|
-
></Rule>
|
|
4
|
+
<ErrorMessage v-if="getRuleTask.isError" :error="getRuleTask.last?.error"></ErrorMessage>
|
|
5
|
+
|
|
6
|
+
<Rule :rule="getRuleTask.last.value" @refresh="refresh" v-if="getRuleTask.last?.value"></Rule>
|
|
14
7
|
</template>
|
|
15
8
|
|
|
16
9
|
<script lang="ts">
|
|
17
|
-
import { defineComponent, onMounted, watch } from "vue"
|
|
10
|
+
import { defineComponent, onMounted, watch } from "vue"
|
|
18
11
|
|
|
19
|
-
import { generateGetRuleTask } from "@/api-helper"
|
|
20
|
-
import ErrorMessage from "@/components/ErrorMessage.vue"
|
|
21
|
-
import Loading from "@/components/Loading.vue"
|
|
22
|
-
import Rule from "@/components/rule/Rule.vue"
|
|
12
|
+
import { generateGetRuleTask } from "@/api-helper"
|
|
13
|
+
import ErrorMessage from "@/components/ErrorMessage.vue"
|
|
14
|
+
import Loading from "@/components/Loading.vue"
|
|
15
|
+
import Rule from "@/components/rule/Rule.vue"
|
|
23
16
|
|
|
24
17
|
export default defineComponent({
|
|
25
18
|
name: "RuleWrapper",
|
|
26
19
|
components: {
|
|
27
20
|
Rule,
|
|
28
21
|
Loading,
|
|
29
|
-
ErrorMessage
|
|
22
|
+
ErrorMessage
|
|
30
23
|
},
|
|
31
24
|
props: {
|
|
32
25
|
id: {
|
|
33
26
|
type: String,
|
|
34
|
-
required: true
|
|
35
|
-
}
|
|
27
|
+
required: true
|
|
28
|
+
}
|
|
36
29
|
},
|
|
37
30
|
setup(props) {
|
|
38
|
-
const getRuleTask = generateGetRuleTask()
|
|
31
|
+
const getRuleTask = generateGetRuleTask()
|
|
39
32
|
|
|
40
33
|
const getRule = async () => {
|
|
41
|
-
await getRuleTask.perform(props.id)
|
|
42
|
-
}
|
|
34
|
+
await getRuleTask.perform(props.id)
|
|
35
|
+
}
|
|
43
36
|
|
|
44
37
|
const refresh = async () => {
|
|
45
|
-
await getRule()
|
|
46
|
-
}
|
|
38
|
+
await getRule()
|
|
39
|
+
}
|
|
47
40
|
|
|
48
41
|
onMounted(async () => {
|
|
49
|
-
await getRule()
|
|
50
|
-
})
|
|
42
|
+
await getRule()
|
|
43
|
+
})
|
|
51
44
|
|
|
52
45
|
watch(props, async () => {
|
|
53
|
-
await getRule()
|
|
54
|
-
})
|
|
46
|
+
await getRule()
|
|
47
|
+
})
|
|
55
48
|
|
|
56
49
|
return {
|
|
57
50
|
getRuleTask,
|
|
58
|
-
refresh
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
})
|
|
51
|
+
refresh
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
})
|
|
62
55
|
</script>
|
|
@@ -9,9 +9,7 @@
|
|
|
9
9
|
</tr>
|
|
10
10
|
<tr v-for="rule in rules.rules" :key="rule.id">
|
|
11
11
|
<td>
|
|
12
|
-
<router-link :to="{ name: 'Rule', params: { id: rule.id } }">{{
|
|
13
|
-
rule.id
|
|
14
|
-
}}</router-link>
|
|
12
|
+
<router-link :to="{ name: 'Rule', params: { id: rule.id } }">{{ rule.id }}</router-link>
|
|
15
13
|
</td>
|
|
16
14
|
<td>
|
|
17
15
|
{{ rule.title }}
|
|
@@ -31,58 +29,56 @@
|
|
|
31
29
|
:pageSize="rules.pageSize"
|
|
32
30
|
@update-page="updatePage"
|
|
33
31
|
></Pagination>
|
|
34
|
-
<p class="help">
|
|
35
|
-
({{ rules.total }} results in total, {{ rules.rules.length }} shown)
|
|
36
|
-
</p>
|
|
32
|
+
<p class="help">({{ rules.total }} results in total, {{ rules.rules.length }} shown)</p>
|
|
37
33
|
</template>
|
|
38
34
|
|
|
39
35
|
<script lang="ts">
|
|
40
|
-
import { computed, defineComponent, PropType } from "vue"
|
|
36
|
+
import { computed, defineComponent, type PropType } from "vue"
|
|
41
37
|
|
|
42
|
-
import Pagination from "@/components/Pagination.vue"
|
|
43
|
-
import Tags from "@/components/tag/Tags.vue"
|
|
44
|
-
import { Rules } from "@/types"
|
|
38
|
+
import Pagination from "@/components/Pagination.vue"
|
|
39
|
+
import Tags from "@/components/tag/Tags.vue"
|
|
40
|
+
import type { Rules } from "@/types"
|
|
45
41
|
|
|
46
42
|
export default defineComponent({
|
|
47
43
|
name: "RulesItem",
|
|
48
44
|
props: {
|
|
49
45
|
rules: {
|
|
50
46
|
type: Object as PropType<Rules>,
|
|
51
|
-
required: true
|
|
52
|
-
}
|
|
47
|
+
required: true
|
|
48
|
+
}
|
|
53
49
|
},
|
|
54
50
|
components: {
|
|
55
51
|
Pagination,
|
|
56
|
-
Tags
|
|
52
|
+
Tags
|
|
57
53
|
},
|
|
58
54
|
emits: ["update-page", "refresh-page", "update-tag"],
|
|
59
55
|
setup(props, context) {
|
|
60
56
|
const scrollToTop = () => {
|
|
61
57
|
window.scrollTo({
|
|
62
|
-
top: 0
|
|
63
|
-
})
|
|
64
|
-
}
|
|
58
|
+
top: 0
|
|
59
|
+
})
|
|
60
|
+
}
|
|
65
61
|
|
|
66
62
|
const updatePage = (page: number) => {
|
|
67
|
-
scrollToTop()
|
|
68
|
-
context.emit("update-page", page)
|
|
69
|
-
}
|
|
63
|
+
scrollToTop()
|
|
64
|
+
context.emit("update-page", page)
|
|
65
|
+
}
|
|
70
66
|
|
|
71
67
|
const refreshPage = () => {
|
|
72
|
-
scrollToTop()
|
|
73
|
-
context.emit("refresh-page")
|
|
74
|
-
}
|
|
68
|
+
scrollToTop()
|
|
69
|
+
context.emit("refresh-page")
|
|
70
|
+
}
|
|
75
71
|
|
|
76
72
|
const updateTag = (tag: string) => {
|
|
77
|
-
scrollToTop()
|
|
78
|
-
context.emit("update-tag", tag)
|
|
79
|
-
}
|
|
73
|
+
scrollToTop()
|
|
74
|
+
context.emit("update-tag", tag)
|
|
75
|
+
}
|
|
80
76
|
|
|
81
77
|
const hasRules = computed(() => {
|
|
82
|
-
return props.rules.rules.length > 0
|
|
83
|
-
})
|
|
78
|
+
return props.rules.rules.length > 0
|
|
79
|
+
})
|
|
84
80
|
|
|
85
|
-
return { updatePage, refreshPage, updateTag, hasRules }
|
|
86
|
-
}
|
|
87
|
-
})
|
|
81
|
+
return { updatePage, refreshPage, updateTag, hasRules }
|
|
82
|
+
}
|
|
83
|
+
})
|
|
88
84
|
</script>
|
|
@@ -28,10 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
<Loading v-if="getRulesTask.isRunning"></Loading>
|
|
30
30
|
|
|
31
|
-
<ErrorMessage
|
|
32
|
-
v-if="getRulesTask.isError"
|
|
33
|
-
:error="getRulesTask.last?.error"
|
|
34
|
-
></ErrorMessage>
|
|
31
|
+
<ErrorMessage v-if="getRulesTask.isError" :error="getRulesTask.last?.error"></ErrorMessage>
|
|
35
32
|
|
|
36
33
|
<Rules
|
|
37
34
|
:rules="getRulesTask.last.value"
|
|
@@ -44,14 +41,14 @@
|
|
|
44
41
|
</template>
|
|
45
42
|
|
|
46
43
|
<script lang="ts">
|
|
47
|
-
import { defineComponent, nextTick, onMounted, ref, watch } from "vue"
|
|
44
|
+
import { defineComponent, nextTick, onMounted, ref, watch } from "vue"
|
|
48
45
|
|
|
49
|
-
import { generateGetRulesTask, generateGetTagsTask } from "@/api-helper"
|
|
50
|
-
import ErrorMessage from "@/components/ErrorMessage.vue"
|
|
51
|
-
import Loading from "@/components/Loading.vue"
|
|
52
|
-
import FormComponent from "@/components/rule/Form.vue"
|
|
53
|
-
import Rules from "@/components/rule/Rules.vue"
|
|
54
|
-
import { RuleSearchParams } from "@/types"
|
|
46
|
+
import { generateGetRulesTask, generateGetTagsTask } from "@/api-helper"
|
|
47
|
+
import ErrorMessage from "@/components/ErrorMessage.vue"
|
|
48
|
+
import Loading from "@/components/Loading.vue"
|
|
49
|
+
import FormComponent from "@/components/rule/Form.vue"
|
|
50
|
+
import Rules from "@/components/rule/Rules.vue"
|
|
51
|
+
import type { RuleSearchParams } from "@/types"
|
|
55
52
|
|
|
56
53
|
export default defineComponent({
|
|
57
54
|
name: "RulesWrapper",
|
|
@@ -59,60 +56,60 @@ export default defineComponent({
|
|
|
59
56
|
Rules,
|
|
60
57
|
Loading,
|
|
61
58
|
FormComponent,
|
|
62
|
-
ErrorMessage
|
|
59
|
+
ErrorMessage
|
|
63
60
|
},
|
|
64
61
|
setup() {
|
|
65
|
-
const page = ref(1)
|
|
66
|
-
const tag = ref<string | undefined>(undefined)
|
|
67
|
-
const form = ref<InstanceType<typeof FormComponent>>()
|
|
62
|
+
const page = ref(1)
|
|
63
|
+
const tag = ref<string | undefined>(undefined)
|
|
64
|
+
const form = ref<InstanceType<typeof FormComponent>>()
|
|
68
65
|
|
|
69
|
-
const getRulesTask = generateGetRulesTask()
|
|
70
|
-
const getTagsTask = generateGetTagsTask()
|
|
66
|
+
const getRulesTask = generateGetRulesTask()
|
|
67
|
+
const getTagsTask = generateGetTagsTask()
|
|
71
68
|
|
|
72
69
|
const getRules = async () => {
|
|
73
|
-
const params = form.value?.getSearchParams() as RuleSearchParams
|
|
74
|
-
return await getRulesTask.perform(params)
|
|
75
|
-
}
|
|
70
|
+
const params = form.value?.getSearchParams() as RuleSearchParams
|
|
71
|
+
return await getRulesTask.perform(params)
|
|
72
|
+
}
|
|
76
73
|
|
|
77
74
|
const updatePage = (newPage: number) => {
|
|
78
|
-
page.value = newPage
|
|
79
|
-
}
|
|
75
|
+
page.value = newPage
|
|
76
|
+
}
|
|
80
77
|
|
|
81
78
|
const resetPage = () => {
|
|
82
|
-
page.value = 1
|
|
83
|
-
}
|
|
79
|
+
page.value = 1
|
|
80
|
+
}
|
|
84
81
|
|
|
85
82
|
const search = async () => {
|
|
86
83
|
// reset page
|
|
87
|
-
resetPage()
|
|
84
|
+
resetPage()
|
|
88
85
|
|
|
89
|
-
await getRules()
|
|
90
|
-
}
|
|
86
|
+
await getRules()
|
|
87
|
+
}
|
|
91
88
|
|
|
92
89
|
const updateTag = (newTag: string | undefined) => {
|
|
93
90
|
if (tag.value === newTag) {
|
|
94
|
-
tag.value = undefined
|
|
91
|
+
tag.value = undefined
|
|
95
92
|
} else {
|
|
96
|
-
tag.value = newTag
|
|
93
|
+
tag.value = newTag
|
|
97
94
|
}
|
|
98
95
|
|
|
99
|
-
nextTick(async () => await search())
|
|
100
|
-
}
|
|
96
|
+
nextTick(async () => await search())
|
|
97
|
+
}
|
|
101
98
|
|
|
102
99
|
const refreshPage = async () => {
|
|
103
100
|
// it is just an alias of search
|
|
104
101
|
// this function will be invoked when a rule is deleted
|
|
105
|
-
await search()
|
|
106
|
-
}
|
|
102
|
+
await search()
|
|
103
|
+
}
|
|
107
104
|
|
|
108
105
|
onMounted(async () => {
|
|
109
|
-
getTagsTask.perform()
|
|
110
|
-
await getRules()
|
|
111
|
-
})
|
|
106
|
+
getTagsTask.perform()
|
|
107
|
+
await getRules()
|
|
108
|
+
})
|
|
112
109
|
|
|
113
110
|
watch([page, tag], async () => {
|
|
114
|
-
nextTick(async () => await getRules())
|
|
115
|
-
})
|
|
111
|
+
nextTick(async () => await getRules())
|
|
112
|
+
})
|
|
116
113
|
|
|
117
114
|
return {
|
|
118
115
|
form,
|
|
@@ -123,8 +120,8 @@ export default defineComponent({
|
|
|
123
120
|
refreshPage,
|
|
124
121
|
search,
|
|
125
122
|
updatePage,
|
|
126
|
-
updateTag
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
})
|
|
123
|
+
updateTag
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
})
|
|
130
127
|
</script>
|
|
@@ -1,47 +1,44 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<pre
|
|
3
|
-
ref="pre"
|
|
4
|
-
class="line-numbers"
|
|
5
|
-
><code class="language-yaml">{{ yaml }}</code></pre>
|
|
2
|
+
<pre ref="pre" class="line-numbers"><code class="language-yaml">{{ yaml }}</code></pre>
|
|
6
3
|
</template>
|
|
7
4
|
|
|
8
5
|
<script lang="ts">
|
|
9
6
|
// eslint-disable-next-line simple-import-sort/imports
|
|
10
|
-
import { defineComponent, onMounted, ref } from "vue"
|
|
7
|
+
import { defineComponent, onMounted, ref } from "vue"
|
|
11
8
|
|
|
12
|
-
import Prism from "prismjs"
|
|
9
|
+
import Prism from "prismjs"
|
|
13
10
|
|
|
14
|
-
import "prismjs/components/prism-yaml"
|
|
15
|
-
import "prismjs/plugins/custom-class/prism-custom-class"
|
|
16
|
-
import "prismjs/plugins/line-numbers/prism-line-numbers.css"
|
|
17
|
-
import "prismjs/plugins/line-numbers/prism-line-numbers"
|
|
18
|
-
import "prismjs/themes/prism-twilight.css"
|
|
11
|
+
import "prismjs/components/prism-yaml"
|
|
12
|
+
import "prismjs/plugins/custom-class/prism-custom-class"
|
|
13
|
+
import "prismjs/plugins/line-numbers/prism-line-numbers.css"
|
|
14
|
+
import "prismjs/plugins/line-numbers/prism-line-numbers"
|
|
15
|
+
import "prismjs/themes/prism-twilight.css"
|
|
19
16
|
|
|
20
17
|
export default defineComponent({
|
|
21
18
|
name: "YAML",
|
|
22
19
|
props: {
|
|
23
20
|
yaml: {
|
|
24
21
|
type: String,
|
|
25
|
-
required: true
|
|
26
|
-
}
|
|
22
|
+
required: true
|
|
23
|
+
}
|
|
27
24
|
},
|
|
28
25
|
setup() {
|
|
29
|
-
const pre = ref<HTMLElement | undefined>(undefined)
|
|
26
|
+
const pre = ref<HTMLElement | undefined>(undefined)
|
|
30
27
|
|
|
31
28
|
Prism.plugins.customClass.map({
|
|
32
29
|
number: "prism-number",
|
|
33
|
-
tag: "prism-tag"
|
|
34
|
-
})
|
|
30
|
+
tag: "prism-tag"
|
|
31
|
+
})
|
|
35
32
|
|
|
36
33
|
onMounted(() => {
|
|
37
34
|
if (pre.value) {
|
|
38
35
|
pre.value.querySelectorAll("code").forEach((elem) => {
|
|
39
|
-
Prism.highlightElement(elem)
|
|
40
|
-
})
|
|
36
|
+
Prism.highlightElement(elem)
|
|
37
|
+
})
|
|
41
38
|
}
|
|
42
|
-
})
|
|
39
|
+
})
|
|
43
40
|
|
|
44
|
-
return { pre }
|
|
45
|
-
}
|
|
46
|
-
})
|
|
41
|
+
return { pre }
|
|
42
|
+
}
|
|
43
|
+
})
|
|
47
44
|
</script>
|
|
@@ -5,60 +5,52 @@
|
|
|
5
5
|
v-on:mouseover="showDeleteButton"
|
|
6
6
|
v-on:mouseleave="hideDeleteButton"
|
|
7
7
|
>
|
|
8
|
-
<span class="tag is-info is-light" @click="updateTag">{{
|
|
9
|
-
|
|
10
|
-
}}</span>
|
|
11
|
-
<a
|
|
12
|
-
class="tag is-delete"
|
|
13
|
-
v-if="isDeleteButtonEnabled"
|
|
14
|
-
@click="deleteTag"
|
|
15
|
-
></a>
|
|
8
|
+
<span class="tag is-info is-light" @click="updateTag">{{ tag.name }}</span>
|
|
9
|
+
<a class="tag is-delete" v-if="isDeleteButtonEnabled" @click="deleteTag"></a>
|
|
16
10
|
</div>
|
|
17
11
|
</div>
|
|
18
12
|
</template>
|
|
19
13
|
|
|
20
14
|
<script lang="ts">
|
|
21
|
-
import { defineComponent, PropType, ref } from "vue"
|
|
15
|
+
import { defineComponent, type PropType, ref } from "vue"
|
|
22
16
|
|
|
23
|
-
import { generateDeleteTagTask } from "@/api-helper"
|
|
24
|
-
import { Tag } from "@/types"
|
|
17
|
+
import { generateDeleteTagTask } from "@/api-helper"
|
|
18
|
+
import type { Tag } from "@/types"
|
|
25
19
|
|
|
26
20
|
export default defineComponent({
|
|
27
21
|
name: "TagItem",
|
|
28
22
|
props: {
|
|
29
23
|
tag: {
|
|
30
24
|
type: Object as PropType<Tag>,
|
|
31
|
-
required: true
|
|
32
|
-
}
|
|
25
|
+
required: true
|
|
26
|
+
}
|
|
33
27
|
},
|
|
34
28
|
setup(props, context) {
|
|
35
|
-
const isDeleted = ref(false)
|
|
36
|
-
const isDeleteButtonEnabled = ref(false)
|
|
29
|
+
const isDeleted = ref(false)
|
|
30
|
+
const isDeleteButtonEnabled = ref(false)
|
|
37
31
|
|
|
38
|
-
const deleteTagTask = generateDeleteTagTask()
|
|
32
|
+
const deleteTagTask = generateDeleteTagTask()
|
|
39
33
|
|
|
40
34
|
const deleteTag = async () => {
|
|
41
|
-
const result = window.confirm(
|
|
42
|
-
`Are you sure you want to delete ${props.tag.name}?`
|
|
43
|
-
);
|
|
35
|
+
const result = window.confirm(`Are you sure you want to delete ${props.tag.name}?`)
|
|
44
36
|
|
|
45
37
|
if (result) {
|
|
46
|
-
await deleteTagTask.perform(props.tag.name)
|
|
47
|
-
isDeleted.value = true
|
|
38
|
+
await deleteTagTask.perform(props.tag.name)
|
|
39
|
+
isDeleted.value = true
|
|
48
40
|
}
|
|
49
|
-
}
|
|
41
|
+
}
|
|
50
42
|
|
|
51
43
|
const showDeleteButton = () => {
|
|
52
|
-
isDeleteButtonEnabled.value = true
|
|
53
|
-
}
|
|
44
|
+
isDeleteButtonEnabled.value = true
|
|
45
|
+
}
|
|
54
46
|
|
|
55
47
|
const hideDeleteButton = () => {
|
|
56
|
-
isDeleteButtonEnabled.value = false
|
|
57
|
-
}
|
|
48
|
+
isDeleteButtonEnabled.value = false
|
|
49
|
+
}
|
|
58
50
|
|
|
59
51
|
const updateTag = () => {
|
|
60
|
-
context.emit("update-tag", props.tag.name)
|
|
61
|
-
}
|
|
52
|
+
context.emit("update-tag", props.tag.name)
|
|
53
|
+
}
|
|
62
54
|
|
|
63
55
|
return {
|
|
64
56
|
updateTag,
|
|
@@ -66,8 +58,8 @@ export default defineComponent({
|
|
|
66
58
|
deleteTag,
|
|
67
59
|
showDeleteButton,
|
|
68
60
|
hideDeleteButton,
|
|
69
|
-
isDeleteButtonEnabled
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
})
|
|
61
|
+
isDeleteButtonEnabled
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
})
|
|
73
65
|
</script>
|
|
@@ -10,28 +10,28 @@
|
|
|
10
10
|
</template>
|
|
11
11
|
|
|
12
12
|
<script lang="ts">
|
|
13
|
-
import { defineComponent, PropType } from "vue"
|
|
13
|
+
import { defineComponent, type PropType } from "vue"
|
|
14
14
|
|
|
15
|
-
import TagComponent from "@/components/tag/Tag.vue"
|
|
16
|
-
import { Tag } from "@/types"
|
|
15
|
+
import TagComponent from "@/components/tag/Tag.vue"
|
|
16
|
+
import type { Tag } from "@/types"
|
|
17
17
|
|
|
18
18
|
export default defineComponent({
|
|
19
19
|
name: "TagsItem",
|
|
20
20
|
components: {
|
|
21
|
-
TagComponent
|
|
21
|
+
TagComponent
|
|
22
22
|
},
|
|
23
23
|
props: {
|
|
24
24
|
tags: {
|
|
25
25
|
type: Array as PropType<Tag[]>,
|
|
26
|
-
required: true
|
|
27
|
-
}
|
|
26
|
+
required: true
|
|
27
|
+
}
|
|
28
28
|
},
|
|
29
29
|
setup(_, context) {
|
|
30
30
|
const updateTag = (tag: string) => {
|
|
31
|
-
context.emit("update-tag", tag)
|
|
32
|
-
}
|
|
31
|
+
context.emit("update-tag", tag)
|
|
32
|
+
}
|
|
33
33
|
|
|
34
|
-
return { updateTag }
|
|
35
|
-
}
|
|
36
|
-
})
|
|
34
|
+
return { updateTag }
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
37
|
</script>
|