Skip to content

Commit

Permalink
feat: add strategy setting for post slug generation (#4551)
Browse files Browse the repository at this point in the history
#### What type of PR is this?

/kind improvement

#### What this PR does / why we need it:

添加文章别名自动生成策略

#### Which issue(s) this PR fixes:

Fixes #1790

#### Special notes for your reviewer:

需要后端提供支持在globalInfo里面添加`gSlugMode`字段。它的类型为(后续可能会支持更多的模式)
<img width="582" alt="image" src="https://github.com/halo-dev/halo/assets/110895612/586c4742-6172-4bbc-a601-ca04c2a9a281">

#### Does this PR introduce a user-facing change?


```release-note
文章支持多别名生成策略。
```
  • Loading branch information
GodlessLiu authored Sep 10, 2023
1 parent 31675db commit e13563b
Show file tree
Hide file tree
Showing 15 changed files with 123 additions and 19 deletions.
1 change: 1 addition & 0 deletions api/src/main/java/run/halo/app/infra/SystemSetting.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public static class Post {
Integer categoryPageSize;
Integer tagPageSize;
Boolean review;
String slugGenerationStrategy;
}

@Data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public GlobalInfo globalInfo() {
handleCommentSetting(info, configMap);
handleUserSetting(info, configMap);
handleBasicSetting(info, configMap);
handlePostSlugGenerationStrategy(info, configMap);
}));

return info;
Expand Down Expand Up @@ -81,6 +82,8 @@ public static class GlobalInfo {

private boolean dataInitialized;

private String postSlugGenerationStrategy;

private List<SocialAuthProvider> socialAuthProviders;
}

Expand Down Expand Up @@ -123,6 +126,13 @@ private void handleUserSetting(GlobalInfo info, ConfigMap configMap) {
}
}

private void handlePostSlugGenerationStrategy(GlobalInfo info, ConfigMap configMap) {
var post = SystemSetting.get(configMap, SystemSetting.Post.GROUP, SystemSetting.Post.class);
if (post != null) {
info.setPostSlugGenerationStrategy(post.getSlugGenerationStrategy());
}
}

private void handleBasicSetting(GlobalInfo info, ConfigMap configMap) {
var basic = SystemSetting.get(configMap, Basic.GROUP, Basic.class);
if (basic != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ data:
"postPageSize": 10,
"archivePageSize": 10,
"categoryPageSize": 10,
"tagPageSize": 10
"tagPageSize": 10,
"slugGenerationStrategy": "generateByTitle"
}
comment: |
{
Expand All @@ -42,4 +43,4 @@ data:
menu: |
{
"primary": "primary"
}
}
13 changes: 13 additions & 0 deletions application/src/main/resources/extensions/system-setting.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,19 @@ spec:
min: 1
max: 100
validation: required
- $formkit: select
label: "别名生成策略"
name: slugGenerationStrategy
value: 'generateByTitle'
options:
- label: '根据标题'
value: 'generateByTitle'
- label: '时间戳'
value: 'timestamp'
- label: 'Short UUID'
value: 'shortUUID'
- label: 'UUID'
value: 'UUID'
- group: seo
label: SEO 设置
formSchema:
Expand Down
1 change: 1 addition & 0 deletions console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"pinia": "^2.1.6",
"pretty-bytes": "^6.0.0",
"qs": "^6.11.1",
"short-unique-id": "^5.0.2",
"transliteration": "^2.3.5",
"vue": "^3.3.4",
"vue-demi": "^0.14.5",
Expand Down
23 changes: 23 additions & 0 deletions console/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 44 additions & 7 deletions console/src/composables/use-slugify.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,63 @@
import { slugify } from "transliteration";
import { watch, type Ref } from "vue";
import ShortUniqueId from "short-unique-id";
import { FormType } from "@/types/slug";
import { useGlobalInfoStore } from "@/stores/global-info";
import { randomUUID } from "@/utils/id";
const uid = new ShortUniqueId();
const Strategy = {
generateByTitle: (value: string) => {
if (!value) return "";
return slugify(value, { trim: true });
},
shortUUID: (value: string) => {
if (!value) return "";
return uid.randomUUID(8);
},
UUID: (value: string) => {
if (!value) return "";
return randomUUID();
},
timestamp: (value: string) => {
if (!value) return "";
return new Date().getTime().toString();
},
};

const onceList = ["shortUUID", "UUID", "timestamp"];

export default function useSlugify(
source: Ref<string>,
target: Ref<string>,
auto: Ref<boolean>
auto: Ref<boolean>,
formType: FormType
) {
watch(
() => source.value,
() => {
if (auto.value) {
handleGenerateSlug();
handleGenerateSlug(false, formType);
}
}
);

const handleGenerateSlug = () => {
if (!source.value) {
const handleGenerateSlug = (forceUpdate = false, formType: FormType) => {
const globalInfoStore = useGlobalInfoStore();
const mode = globalInfoStore.globalInfo?.postSlugGenerationStrategy;

if (!mode) {
return;
}
if (formType != FormType.POST) {
target.value = Strategy["generateByTitle"](source.value);
return;
}
if (forceUpdate) {
target.value = Strategy[mode](source.value);
return;
}
target.value = slugify(source.value, {
trim: true,
});
if (onceList.includes(mode) && target.value) return;
target.value = Strategy[mode](source.value);
};

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import AnnotationsForm from "@/components/form/AnnotationsForm.vue";
import useSlugify from "@/composables/use-slugify";
import { useI18n } from "vue-i18n";
import { usePageUpdateMutate } from "../composables/use-page-update-mutate";
import { FormType } from "@/types/slug";
const initialFormState: SinglePage = {
spec: {
Expand Down Expand Up @@ -277,7 +278,8 @@ const { handleGenerateSlug } = useSlugify(
formState.value.spec.slug = value;
},
}),
computed(() => !isUpdateMode.value)
computed(() => !isUpdateMode.value),
FormType.SINGLE_PAGE
);
</script>

Expand Down Expand Up @@ -331,7 +333,7 @@ const { handleGenerateSlug } = useSlugify(
$t('core.page.settings.fields.slug.refresh_message')
"
class="group flex h-full cursor-pointer items-center border-l px-3 transition-all hover:bg-gray-100"
@click="handleGenerateSlug"
@click="handleGenerateSlug(true, FormType.SINGLE_PAGE)"
>
<IconRefreshLine
class="h-4 w-4 text-gray-500 group-hover:text-gray-700"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { useThemeCustomTemplates } from "@/modules/interface/themes/composables/
import AnnotationsForm from "@/components/form/AnnotationsForm.vue";
import useSlugify from "@/composables/use-slugify";
import { useI18n } from "vue-i18n";
import { FormType } from "@/types/slug";
const props = withDefaults(
defineProps<{
Expand Down Expand Up @@ -199,7 +200,8 @@ const { handleGenerateSlug } = useSlugify(
formState.value.spec.slug = value;
},
}),
computed(() => !isUpdateMode.value)
computed(() => !isUpdateMode.value),
FormType.CATEGORY
);
</script>
<template>
Expand Down Expand Up @@ -260,7 +262,7 @@ const { handleGenerateSlug } = useSlugify(
)
"
class="group flex h-full cursor-pointer items-center border-l px-3 transition-all hover:bg-gray-100"
@click="handleGenerateSlug"
@click="handleGenerateSlug(true, FormType.CATEGORY)"
>
<IconRefreshLine
class="h-4 w-4 text-gray-500 group-hover:text-gray-700"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { submitForm } from "@formkit/core";
import useSlugify from "@/composables/use-slugify";
import { useI18n } from "vue-i18n";
import { usePostUpdateMutate } from "../composables/use-post-update-mutate";
import { FormType } from "@/types/slug";
const initialFormState: Post = {
spec: {
Expand Down Expand Up @@ -240,7 +241,8 @@ const { handleGenerateSlug } = useSlugify(
formState.value.spec.slug = value;
},
}),
computed(() => !isUpdateMode.value)
computed(() => !isUpdateMode.value),
FormType.POST
);
</script>
<template>
Expand Down Expand Up @@ -293,7 +295,7 @@ const { handleGenerateSlug } = useSlugify(
$t('core.post.settings.fields.slug.refresh_message')
"
class="group flex h-full cursor-pointer items-center border-l px-3 transition-all hover:bg-gray-100"
@click="handleGenerateSlug"
@click="handleGenerateSlug(true, FormType.POST)"
>
<IconRefreshLine
class="h-4 w-4 text-gray-500 group-hover:text-gray-700"
Expand Down
Loading

0 comments on commit e13563b

Please sign in to comment.