Skip to content

Commit 5b5b3f1

Browse files
authored
Merge pull request #273 from SubtitleEdit/word-censor
Add WordCensor SE5 plugin
2 parents a52cb85 + 596d62b commit 5b5b3f1

14 files changed

Lines changed: 825 additions & 0 deletions

.github/workflows/word-censor.yml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
name: Build WordCensor (SE5)
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'se5/WordCensor/**'
8+
- 'se5/Plugin-Shared/**'
9+
- '.github/workflows/word-censor.yml'
10+
pull_request:
11+
paths:
12+
- 'se5/WordCensor/**'
13+
- 'se5/Plugin-Shared/**'
14+
- '.github/workflows/word-censor.yml'
15+
workflow_dispatch:
16+
inputs:
17+
tag:
18+
description: 'Release tag to publish the zips under (e.g. se5-word-censor-v1.0). Leave empty to build artifacts only.'
19+
required: false
20+
type: string
21+
22+
jobs:
23+
build:
24+
runs-on: ubuntu-latest
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
include:
29+
- rid: win-x64
30+
os: windows
31+
exe: WordCensor.exe
32+
- rid: win-arm64
33+
os: windows
34+
exe: WordCensor.exe
35+
- rid: linux-x64
36+
os: linux
37+
exe: WordCensor
38+
- rid: linux-arm64
39+
os: linux
40+
exe: WordCensor
41+
- rid: osx-x64
42+
os: macos
43+
exe: WordCensor
44+
- rid: osx-arm64
45+
os: macos
46+
exe: WordCensor
47+
48+
steps:
49+
- name: Checkout
50+
uses: actions/checkout@v4
51+
52+
- name: Setup .NET 8
53+
uses: actions/setup-dotnet@v4
54+
with:
55+
dotnet-version: '8.0.x'
56+
57+
- name: Publish self-contained (${{ matrix.rid }})
58+
working-directory: se5/WordCensor
59+
run: |
60+
dotnet publish WordCensor.csproj \
61+
-c Release \
62+
-r ${{ matrix.rid }} \
63+
--self-contained true \
64+
-p:DebugType=None \
65+
-p:DebugSymbols=false \
66+
-o staging/WordCensor
67+
68+
- name: Rewrite plugin.json for ${{ matrix.os }}
69+
working-directory: se5/WordCensor
70+
run: |
71+
jq '
72+
del(.runtime, .entry) |
73+
.executables = { "${{ matrix.os }}": "${{ matrix.exe }}" }
74+
' plugin.json > staging/WordCensor/plugin.json
75+
76+
- name: Package zip
77+
working-directory: se5/WordCensor/staging
78+
run: zip -r "$GITHUB_WORKSPACE/WordCensor-${{ matrix.rid }}.zip" WordCensor
79+
80+
- name: Upload artifact
81+
uses: actions/upload-artifact@v4
82+
with:
83+
name: WordCensor-${{ matrix.rid }}
84+
path: WordCensor-${{ matrix.rid }}.zip
85+
86+
release:
87+
name: Publish GitHub Release
88+
needs: build
89+
if: github.event_name == 'workflow_dispatch' && github.event.inputs.tag != ''
90+
runs-on: ubuntu-latest
91+
permissions:
92+
contents: write
93+
steps:
94+
- name: Download all zips
95+
uses: actions/download-artifact@v4
96+
with:
97+
path: dist
98+
pattern: WordCensor-*
99+
merge-multiple: true
100+
101+
- name: Create release and upload zips
102+
env:
103+
GH_TOKEN: ${{ github.token }}
104+
run: |
105+
gh release create "${{ github.event.inputs.tag }}" dist/WordCensor-*.zip \
106+
--repo "${{ github.repository }}" \
107+
--target "${{ github.sha }}" \
108+
--title "WordCensor ${{ github.event.inputs.tag }}" \
109+
--notes "Self-contained WordCensor plugin builds for win/linux/osx (x64 + arm64)."

se5-plugins.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
{
22
"plugins": [
3+
{
4+
"name": "Word censor",
5+
"description": "Censors offensive words by replacing the first half of each match with random grawlix characters (#@!$%). Optionally highlights censored words in red.",
6+
"version": "1.0.0",
7+
"author": "Subtitle Edit",
8+
"url": "https://github.com/SubtitleEdit/plugins/tree/main/se5/WordCensor",
9+
"date": "2026-05-17",
10+
"minSeVersion": "5.0.0",
11+
"downloads": {
12+
"win-x64": "https://github.com/SubtitleEdit/plugins/releases/download/se5-word-censor-v1.0/WordCensor-win-x64.zip",
13+
"win-arm64": "https://github.com/SubtitleEdit/plugins/releases/download/se5-word-censor-v1.0/WordCensor-win-arm64.zip",
14+
"linux-x64": "https://github.com/SubtitleEdit/plugins/releases/download/se5-word-censor-v1.0/WordCensor-linux-x64.zip",
15+
"linux-arm64": "https://github.com/SubtitleEdit/plugins/releases/download/se5-word-censor-v1.0/WordCensor-linux-arm64.zip",
16+
"osx-x64": "https://github.com/SubtitleEdit/plugins/releases/download/se5-word-censor-v1.0/WordCensor-osx-x64.zip",
17+
"osx-arm64": "https://github.com/SubtitleEdit/plugins/releases/download/se5-word-censor-v1.0/WordCensor-osx-arm64.zip"
18+
}
19+
},
320
{
421
"name": "British to American",
522
"description": "Converts British English spellings to American English in the subtitle. Shows a checkable preview of every proposed change.",

se5/WordCensor/App.axaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Application xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
x:Class="SubtitleEdit.Plugins.WordCensor.App"
4+
RequestedThemeVariant="Default">
5+
<Application.Styles>
6+
<FluentTheme />
7+
</Application.Styles>
8+
</Application>

se5/WordCensor/App.axaml.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Avalonia.Controls;
2+
using Avalonia.Markup.Xaml;
3+
using SubtitleEdit.Plugins.Shared;
4+
5+
namespace SubtitleEdit.Plugins.WordCensor;
6+
7+
public partial class App : PluginApp
8+
{
9+
public override void Initialize() => AvaloniaXamlLoader.Load(this);
10+
11+
protected override Window CreateMainWindow(PluginRequest request) => new MainWindow(request);
12+
}

se5/WordCensor/BadWords.txt

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
anal
2+
anus
3+
arse
4+
ass
5+
ballsack
6+
balls
7+
bastard
8+
bitch
9+
biatch
10+
bloody
11+
blowjob
12+
blow job
13+
bollock
14+
bollok
15+
boner
16+
boob
17+
bugger
18+
bum
19+
butt
20+
buttplug
21+
clitoris
22+
cock
23+
coon
24+
crap
25+
cunt
26+
damn
27+
dick
28+
dildo
29+
dyke
30+
fag
31+
feck
32+
fellate
33+
fellatio
34+
felching
35+
fuck
36+
fucking
37+
fucked
38+
f u c k
39+
fudgepacker
40+
fudge packer
41+
flange
42+
goddamn
43+
god damn
44+
hell
45+
homo
46+
jerk
47+
jizz
48+
knobend
49+
knob end
50+
labia
51+
lmao
52+
lmfao
53+
muff
54+
nigger
55+
nigga
56+
omg
57+
penis
58+
piss
59+
poop
60+
prick
61+
pube
62+
pussy
63+
queer
64+
scrotum
65+
sex
66+
shit
67+
s hit
68+
sh1t
69+
slut
70+
smegma
71+
spunk
72+
tit
73+
tosser
74+
turd
75+
twat
76+
vagina
77+
wank
78+
whore
79+
wtf

se5/WordCensor/ChangeProposal.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using CommunityToolkit.Mvvm.ComponentModel;
2+
3+
namespace SubtitleEdit.Plugins.WordCensor;
4+
5+
public partial class ChangeProposal : ObservableObject
6+
{
7+
[ObservableProperty] private bool _include = true;
8+
[ObservableProperty] private string _censoredText;
9+
10+
public int LineIndex { get; }
11+
public string LineNumber => (LineIndex + 1).ToString();
12+
public string OriginalText { get; }
13+
14+
public ChangeProposal(int lineIndex, string originalText, string censoredText)
15+
{
16+
LineIndex = lineIndex;
17+
OriginalText = originalText;
18+
_censoredText = censoredText;
19+
}
20+
}

se5/WordCensor/MainWindow.axaml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<Window xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:local="using:SubtitleEdit.Plugins.WordCensor"
6+
x:Class="SubtitleEdit.Plugins.WordCensor.MainWindow"
7+
mc:Ignorable="d"
8+
Title="Word censor"
9+
Width="720" Height="600"
10+
MinWidth="500" MinHeight="380"
11+
WindowStartupLocation="CenterScreen">
12+
<DockPanel Margin="20">
13+
14+
<Grid DockPanel.Dock="Bottom"
15+
ColumnDefinitions="*,Auto,Auto"
16+
Margin="0,14,0,0">
17+
<TextBlock Grid.Column="0"
18+
x:Name="SummaryLabel"
19+
VerticalAlignment="Center"
20+
Opacity="0.75" />
21+
<Button Grid.Column="1"
22+
Content="Cancel"
23+
Click="OnCancel"
24+
MinWidth="100"
25+
Margin="0,0,8,0" />
26+
<Button Grid.Column="2"
27+
x:Name="ApplyButton"
28+
Content="Apply"
29+
Click="OnApply"
30+
MinWidth="100"
31+
Classes="accent"
32+
IsDefault="True" />
33+
</Grid>
34+
35+
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top" Spacing="10" Margin="0,0,0,4">
36+
<Button Content="Select all" Click="OnSelectAll" />
37+
<Button Content="Select none" Click="OnSelectNone" />
38+
<CheckBox x:Name="ColorRedCheck"
39+
Content="Highlight censored words in red"
40+
VerticalAlignment="Center"
41+
Margin="12,0,0,0" />
42+
</StackPanel>
43+
44+
<TextBlock DockPanel.Dock="Top"
45+
FontSize="18"
46+
FontWeight="SemiBold"
47+
Text="Word censor" />
48+
49+
<TextBlock DockPanel.Dock="Top"
50+
x:Name="SubtitleLabel"
51+
Margin="0,4,0,12"
52+
Opacity="0.7"
53+
TextWrapping="Wrap" />
54+
55+
<TextBlock DockPanel.Dock="Top"
56+
x:Name="NoChangesLabel"
57+
FontSize="14"
58+
Margin="0,30,0,0"
59+
HorizontalAlignment="Center"
60+
Opacity="0.65"
61+
Text="No offensive words found in the selected lines."
62+
IsVisible="False" />
63+
64+
<Border BorderBrush="#22808080"
65+
BorderThickness="1"
66+
CornerRadius="4"
67+
Padding="0">
68+
<ListBox x:Name="ChangesList"
69+
Background="Transparent"
70+
SelectionMode="Single">
71+
<ListBox.ItemTemplate>
72+
<DataTemplate x:DataType="local:ChangeProposal">
73+
<Grid ColumnDefinitions="Auto,42,*" Margin="4,6">
74+
<CheckBox Grid.Column="0"
75+
IsChecked="{Binding Include, Mode=TwoWay}"
76+
VerticalAlignment="Top"
77+
Margin="0,2,0,0" />
78+
<TextBlock Grid.Column="1"
79+
Text="{Binding LineNumber}"
80+
Opacity="0.55"
81+
FontSize="12"
82+
Margin="6,2,8,0"
83+
VerticalAlignment="Top" />
84+
<StackPanel Grid.Column="2" Orientation="Vertical" Spacing="2">
85+
<TextBlock Text="{Binding OriginalText}"
86+
TextWrapping="Wrap"
87+
Opacity="0.55"
88+
FontSize="12" />
89+
<TextBlock Text="{Binding CensoredText}"
90+
TextWrapping="Wrap"
91+
FontWeight="SemiBold" />
92+
</StackPanel>
93+
</Grid>
94+
</DataTemplate>
95+
</ListBox.ItemTemplate>
96+
</ListBox>
97+
</Border>
98+
</DockPanel>
99+
</Window>

0 commit comments

Comments
 (0)