TZWBBNQJ5URAQZOQGMVOCOKOGF6IYZWX6AHWLNSG53SRL7GJCX7AC /*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#pragma once#include <QDialog>class QLineEdit;class QDialogButtonBox;class SlugRewriteRuleDialog : public QDialog{Q_OBJECTpublic:explicit SlugRewriteRuleDialog(QWidget *parent = nullptr);~SlugRewriteRuleDialog() override;void setMatchPrefix(const QString &prefix);void setReplacePrefix(const QString &prefix);[[nodiscard]] QString matchPrefix() const;[[nodiscard]] QString replacePrefix() const;private:void updateOkButton();QLineEdit *mMatchPrefixEdit = nullptr;QLineEdit *mReplacePrefixEdit = nullptr;QDialogButtonBox *mButtonBox = nullptr;};
/*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#include "slugrewriteruledialog.h"#include <KLocalizedString>#include <QDialogButtonBox>#include <QFormLayout>#include <QLineEdit>#include <QPushButton>#include <QVBoxLayout>SlugRewriteRuleDialog::SlugRewriteRuleDialog(QWidget *parent): QDialog(parent){setWindowTitle(i18nc("@title:window", "Slug Rewrite Rule"));auto *mainLayout = new QVBoxLayout(this);auto *formLayout = new QFormLayout;mMatchPrefixEdit = new QLineEdit(this);mMatchPrefixEdit->setPlaceholderText(i18nc("@info:placeholder", "https://reddit.com"));formLayout->addRow(i18nc("@label:textbox", "Match Prefix:"), mMatchPrefixEdit);mReplacePrefixEdit = new QLineEdit(this);mReplacePrefixEdit->setPlaceholderText(i18nc("@info:placeholder", "https://old.reddit.com"));formLayout->addRow(i18nc("@label:textbox", "Replace With:"), mReplacePrefixEdit);mainLayout->addLayout(formLayout);mButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);mainLayout->addWidget(mButtonBox);connect(mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);connect(mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);connect(mMatchPrefixEdit, &QLineEdit::textChanged, this, &SlugRewriteRuleDialog::updateOkButton);connect(mReplacePrefixEdit, &QLineEdit::textChanged, this, &SlugRewriteRuleDialog::updateOkButton);updateOkButton();}SlugRewriteRuleDialog::~SlugRewriteRuleDialog() = default;void SlugRewriteRuleDialog::setMatchPrefix(const QString &prefix){mMatchPrefixEdit->setText(prefix);}void SlugRewriteRuleDialog::setReplacePrefix(const QString &prefix){mReplacePrefixEdit->setText(prefix);}QString SlugRewriteRuleDialog::matchPrefix() const{return mMatchPrefixEdit->text().trimmed();}QString SlugRewriteRuleDialog::replacePrefix() const{return mReplacePrefixEdit->text().trimmed();}void SlugRewriteRuleDialog::updateOkButton(){mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(!matchPrefix().isEmpty() && !replacePrefix().isEmpty());}#include "moc_slugrewriteruledialog.cpp"
/*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#pragma once#include <QVariant>#include <WebEngineViewer/NetworkPluginUrlInterceptor>namespace WebEngineViewer{class NetworkPluginUrlInterceptorInterface;}class SlugRewritePluginUrlInterceptor : public WebEngineViewer::NetworkPluginUrlInterceptor{Q_OBJECTpublic:explicit SlugRewritePluginUrlInterceptor(QObject *parent = nullptr, const QList<QVariant> & = QList<QVariant>());~SlugRewritePluginUrlInterceptor() override;[[nodiscard]] WebEngineViewer::NetworkPluginUrlInterceptorInterface *createInterface(QWebEngineView *webEngine, QObject *parent) override;void showConfigureDialog(QWidget *parent) override;[[nodiscard]] bool hasConfigureDialog() const override;};
/*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#include "slugrewritepluginurlinterceptor.h"#include "slugrewriteconfiguredialog.h"#include "slugrewriteinterceptorinterface.h"#include <KPluginFactory>#include <WebEngineViewer/NetworkPluginUrlInterceptorInterface>K_PLUGIN_CLASS_WITH_JSON(SlugRewritePluginUrlInterceptor, "messageviewer_slugrewriteurlinterceptor.json")SlugRewritePluginUrlInterceptor::SlugRewritePluginUrlInterceptor(QObject *parent, const QList<QVariant> &): WebEngineViewer::NetworkPluginUrlInterceptor(parent){}SlugRewritePluginUrlInterceptor::~SlugRewritePluginUrlInterceptor() = default;WebEngineViewer::NetworkPluginUrlInterceptorInterface *SlugRewritePluginUrlInterceptor::createInterface(QWebEngineView *webEngine, QObject *parent){Q_UNUSED(webEngine)return new SlugRewriteInterceptorInterface(parent);}bool SlugRewritePluginUrlInterceptor::hasConfigureDialog() const{return true;}void SlugRewritePluginUrlInterceptor::showConfigureDialog(QWidget *parent){SlugRewriteConfigureDialog dlg(parent);dlg.exec();}#include "slugrewritepluginurlinterceptor.moc"#include "moc_slugrewritepluginurlinterceptor.cpp"
/*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#pragma once#include <WebEngineViewer/NetworkPluginUrlInterceptorInterface>class SlugRewriteInterceptorInterface : public WebEngineViewer::NetworkPluginUrlInterceptorInterface{Q_OBJECTpublic:explicit SlugRewriteInterceptorInterface(QObject *parent = nullptr);~SlugRewriteInterceptorInterface() override;bool interceptRequest(QWebEngineUrlRequestInfo &info) override;};
/*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#include "slugrewriteinterceptorinterface.h"#include "slugrewriteengine.h"#include "slugrewriteinterceptor_debug.h"#include "slugrewritesettings.h"SlugRewriteInterceptorInterface::SlugRewriteInterceptorInterface(QObject *parent): WebEngineViewer::NetworkPluginUrlInterceptorInterface(parent){}SlugRewriteInterceptorInterface::~SlugRewriteInterceptorInterface() = default;bool SlugRewriteInterceptorInterface::interceptRequest(QWebEngineUrlRequestInfo &info){if (!SlugRewriteSettings::self()->slugRewriteEnabled()) {return false;}return SlugRewriteEngine::self()->interceptRequest(info);}#include "moc_slugrewriteinterceptorinterface.cpp"
/*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#pragma once#include <QObject>#include <QWebEngineUrlRequestInfo>#include <optional>#include <slugrewrite.rs.h>class SlugRewriteEngine : public QObject{Q_OBJECTpublic:static SlugRewriteEngine *self();[[nodiscard]] bool interceptRequest(QWebEngineUrlRequestInfo &info);void reloadRules();private:explicit SlugRewriteEngine(QObject *parent = nullptr);~SlugRewriteEngine() override;std::optional<rust::Box<SlugRewriter>> mRewriter;};
/*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#include "slugrewriteengine.h"#include "slugrewriteinterceptor_debug.h"#include "slugrewritesettings.h"SlugRewriteEngine::SlugRewriteEngine(QObject *parent): QObject(parent){reloadRules();}SlugRewriteEngine::~SlugRewriteEngine() = default;SlugRewriteEngine *SlugRewriteEngine::self(){static SlugRewriteEngine s_self;return &s_self;}void SlugRewriteEngine::reloadRules(){const QStringList matchPrefixes = SlugRewriteSettings::self()->matchPrefixes();const QStringList replacePrefixes = SlugRewriteSettings::self()->replacePrefixes();if (matchPrefixes.size() != replacePrefixes.size()) {qCWarning(SLUGREWRITEINTERCEPTOR_LOG) << "Match and replace prefix lists have different sizes, ignoring rules";mRewriter.reset();return;}std::vector<rust::String> rustMatchPrefixes;std::vector<rust::String> rustReplacePrefixes;for (const auto &prefix : matchPrefixes) {rustMatchPrefixes.emplace_back(prefix.toStdString());}for (const auto &prefix : replacePrefixes) {rustReplacePrefixes.emplace_back(prefix.toStdString());}mRewriter = createRewriter(rust::Slice<const rust::String>(rustMatchPrefixes.data(), rustMatchPrefixes.size()),rust::Slice<const rust::String>(rustReplacePrefixes.data(), rustReplacePrefixes.size()));}bool SlugRewriteEngine::interceptRequest(QWebEngineUrlRequestInfo &info){if (!mRewriter) {return false;}const std::string url = info.requestUrl().toString().toStdString();const RewriteResult result = (*mRewriter)->rewriteUrl(url);if (result.matched) {const QUrl rewrittenUrl = QUrl(QString::fromStdString(std::string(result.rewrittenUrl)));qCDebug(SLUGREWRITEINTERCEPTOR_LOG) << "Rewriting" << info.requestUrl() << "to" << rewrittenUrl;info.redirect(rewrittenUrl);return true;}return false;}#include "moc_slugrewriteengine.cpp"
/*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#pragma once#include <WebEngineViewer/NetworkPluginUrlInterceptorConfigureWidget>class QCheckBox;class QTreeWidget;class QPushButton;class SlugRewriteConfigureWidget : public WebEngineViewer::NetworkPluginUrlInterceptorConfigureWidget{Q_OBJECTpublic:explicit SlugRewriteConfigureWidget(QWidget *parent = nullptr);~SlugRewriteConfigureWidget() override;void loadSettings() override;void saveSettings() override;void resetSettings() override;private:void slotAdd();void slotEdit();void slotRemove();void updateButtons();QCheckBox *mEnabledCheckBox = nullptr;QTreeWidget *mRulesTree = nullptr;QPushButton *mAddButton = nullptr;QPushButton *mEditButton = nullptr;QPushButton *mRemoveButton = nullptr;};
/*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#include "slugrewriteconfigurewidget.h"#include "slugrewriteengine.h"#include "slugrewriteruledialog.h"#include "slugrewritesettings.h"#include <KLocalizedString>#include <QCheckBox>#include <QHBoxLayout>#include <QHeaderView>#include <QPushButton>#include <QTreeWidget>#include <QVBoxLayout>SlugRewriteConfigureWidget::SlugRewriteConfigureWidget(QWidget *parent): WebEngineViewer::NetworkPluginUrlInterceptorConfigureWidget(parent){auto *mainLayout = new QVBoxLayout(this);mainLayout->setContentsMargins({});mEnabledCheckBox = new QCheckBox(i18nc("@option:check", "Enable URL slug rewriting"), this);mainLayout->addWidget(mEnabledCheckBox);auto *rulesLayout = new QHBoxLayout;mRulesTree = new QTreeWidget(this);mRulesTree->setHeaderLabels({i18nc("@title:column", "Match Prefix"), i18nc("@title:column", "Replace With")});mRulesTree->setRootIsDecorated(false);mRulesTree->header()->setStretchLastSection(true);rulesLayout->addWidget(mRulesTree);auto *buttonsLayout = new QVBoxLayout;mAddButton = new QPushButton(i18nc("@action:button", "Add..."), this);mEditButton = new QPushButton(i18nc("@action:button", "Edit..."), this);mRemoveButton = new QPushButton(i18nc("@action:button", "Remove"), this);buttonsLayout->addWidget(mAddButton);buttonsLayout->addWidget(mEditButton);buttonsLayout->addWidget(mRemoveButton);buttonsLayout->addStretch();rulesLayout->addLayout(buttonsLayout);mainLayout->addLayout(rulesLayout);connect(mAddButton, &QPushButton::clicked, this, &SlugRewriteConfigureWidget::slotAdd);connect(mEditButton, &QPushButton::clicked, this, &SlugRewriteConfigureWidget::slotEdit);connect(mRemoveButton, &QPushButton::clicked, this, &SlugRewriteConfigureWidget::slotRemove);connect(mRulesTree, &QTreeWidget::itemSelectionChanged, this, &SlugRewriteConfigureWidget::updateButtons);connect(mEnabledCheckBox, &QCheckBox::toggled, this, [this]() {Q_EMIT configureChanged();});updateButtons();}SlugRewriteConfigureWidget::~SlugRewriteConfigureWidget() = default;void SlugRewriteConfigureWidget::loadSettings(){mEnabledCheckBox->setChecked(SlugRewriteSettings::self()->slugRewriteEnabled());mRulesTree->clear();const QStringList matchPrefixes = SlugRewriteSettings::self()->matchPrefixes();const QStringList replacePrefixes = SlugRewriteSettings::self()->replacePrefixes();const int count = qMin(matchPrefixes.size(), replacePrefixes.size());for (int i = 0; i < count; ++i) {auto *item = new QTreeWidgetItem(mRulesTree);item->setText(0, matchPrefixes.at(i));item->setText(1, replacePrefixes.at(i));}}void SlugRewriteConfigureWidget::saveSettings(){SlugRewriteSettings::self()->setSlugRewriteEnabled(mEnabledCheckBox->isChecked());QStringList matchPrefixes;QStringList replacePrefixes;for (int i = 0; i < mRulesTree->topLevelItemCount(); ++i) {const auto *item = mRulesTree->topLevelItem(i);matchPrefixes << item->text(0);replacePrefixes << item->text(1);}SlugRewriteSettings::self()->setMatchPrefixes(matchPrefixes);SlugRewriteSettings::self()->setReplacePrefixes(replacePrefixes);SlugRewriteSettings::self()->save();SlugRewriteEngine::self()->reloadRules();}void SlugRewriteConfigureWidget::resetSettings(){const bool bUseDefaults = SlugRewriteSettings::self()->useDefaults(true);loadSettings();SlugRewriteSettings::self()->useDefaults(bUseDefaults);}void SlugRewriteConfigureWidget::slotAdd(){SlugRewriteRuleDialog dlg(this);if (dlg.exec() == QDialog::Accepted) {auto *item = new QTreeWidgetItem(mRulesTree);item->setText(0, dlg.matchPrefix());item->setText(1, dlg.replacePrefix());Q_EMIT configureChanged();}}void SlugRewriteConfigureWidget::slotEdit(){auto *item = mRulesTree->currentItem();if (!item) {return;}SlugRewriteRuleDialog dlg(this);dlg.setMatchPrefix(item->text(0));dlg.setReplacePrefix(item->text(1));if (dlg.exec() == QDialog::Accepted) {item->setText(0, dlg.matchPrefix());item->setText(1, dlg.replacePrefix());Q_EMIT configureChanged();}}void SlugRewriteConfigureWidget::slotRemove(){auto *item = mRulesTree->currentItem();if (item) {delete item;Q_EMIT configureChanged();}}void SlugRewriteConfigureWidget::updateButtons(){const bool hasSelection = mRulesTree->currentItem() != nullptr;mEditButton->setEnabled(hasSelection);mRemoveButton->setEnabled(hasSelection);}#include "moc_slugrewriteconfigurewidget.cpp"
/*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#pragma once#include <PimCommon/ConfigurePluginDialog>class SlugRewriteConfigureWidget;class SlugRewriteConfigureDialog : public PimCommon::ConfigurePluginDialog{Q_OBJECTpublic:explicit SlugRewriteConfigureDialog(QWidget *parent = nullptr);~SlugRewriteConfigureDialog() override;protected:[[nodiscard]] QWidget *createLayout() override;void save() override;void load() override;void reset() override;void help() override;private:void readConfig();void writeConfig();SlugRewriteConfigureWidget *mConfigureWidget = nullptr;};
/*SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later*/#include "slugrewriteconfiguredialog.h"#include "slugrewriteconfigurewidget.h"#include <KConfigGroup>#include <KLocalizedString>#include <KSharedConfig>#include <KWindowConfig>#include <QWindow>namespace{static const char myConfigGroupName[] = "SlugRewriteConfigureDialog";}SlugRewriteConfigureDialog::SlugRewriteConfigureDialog(QWidget *parent): PimCommon::ConfigurePluginDialog(parent){setWindowTitle(i18nc("@title:window", "Configure Slug Rewrite Plugin"));initLayout();readConfig();}SlugRewriteConfigureDialog::~SlugRewriteConfigureDialog(){writeConfig();}QWidget *SlugRewriteConfigureDialog::createLayout(){mConfigureWidget = new SlugRewriteConfigureWidget(this);return mConfigureWidget;}void SlugRewriteConfigureDialog::save(){mConfigureWidget->saveSettings();}void SlugRewriteConfigureDialog::load(){mConfigureWidget->loadSettings();}void SlugRewriteConfigureDialog::reset(){mConfigureWidget->resetSettings();}void SlugRewriteConfigureDialog::help(){}void SlugRewriteConfigureDialog::readConfig(){create();windowHandle()->resize(QSize(600, 400));KConfigGroup group(KSharedConfig::openStateConfig(), QLatin1StringView(myConfigGroupName));KWindowConfig::restoreWindowSize(windowHandle(), group);resize(windowHandle()->size());}void SlugRewriteConfigureDialog::writeConfig(){KConfigGroup group(KSharedConfig::openStateConfig(), QLatin1StringView(myConfigGroupName));KWindowConfig::saveWindowSize(windowHandle(), group);group.sync();}#include "moc_slugrewriteconfiguredialog.cpp"
File=slugrewritesettings.kcfgClassName=SlugRewriteSettingsMutators=trueSingleton=trueItemAccessors=trueSetUserTexts=trueTranslationSystem=kde
<?xml version="1.0" encoding="utf-8"?><!--SPDX-FileCopyrightText: 2026 ahoutsSPDX-License-Identifier: GPL-2.0-or-later--><kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 http://www.kde.org/standards/kcfg/1.0/kcfg.xsd"><kcfgfile name="slugrewritesettingsrc" /><group name="General"><entry name="SlugRewriteEnabled" type="Bool"><label>Enable slug rewrite</label><default>false</default></entry></group><group name="Rules"><entry key="matchPrefixes" type="StringList"><default></default></entry><entry key="replacePrefixes" type="StringList"><default></default></entry></group></kcfg>
// SPDX-FileCopyrightText: 2026 ahouts//// SPDX-License-Identifier: GPL-2.0-or-laterstruct SlugRewriter {rules: Vec<(String, String)>,}fn create_rewriter(match_prefixes: &[String], replace_prefixes: &[String]) -> Box<SlugRewriter> {let rules: Vec<(String, String)> = match_prefixes.iter().zip(replace_prefixes.iter()).map(|(m, r)| (m.clone(), r.clone())).collect();Box::new(SlugRewriter { rules })}impl SlugRewriter {fn rewrite_url(&self, url: &str) -> ffi::RewriteResult {for (match_prefix, replace_prefix) in &self.rules {if url.starts_with(match_prefix.as_str()) {let rewritten = format!("{}{}", replace_prefix, &url[match_prefix.len()..]);return ffi::RewriteResult {matched: true,rewritten_url: rewritten,};}}ffi::RewriteResult {matched: false,rewritten_url: String::new(),}}}#[cxx::bridge]mod ffi {#[derive(Default)]struct RewriteResult {matched: bool,#[cxx_name = "rewrittenUrl"]rewritten_url: String,}extern "Rust" {type SlugRewriter;#[cxx_name = "createRewriter"]fn create_rewriter(match_prefixes: &[String],replace_prefixes: &[String],) -> Box<SlugRewriter>;#[cxx_name = "rewriteUrl"]fn rewrite_url(self: &SlugRewriter, url: &str) -> RewriteResult;}}
// SPDX-FileCopyrightText: 2026 ahouts//// SPDX-License-Identifier: GPL-2.0-or-latermod slugrewrite;
// SPDX-FileCopyrightText: 2026 ahouts//// SPDX-License-Identifier: GPL-2.0-or-laterfn main() {cxx_build::bridge("src/slugrewrite.rs").compile("slugrewrite-engine")}
# SPDX-FileCopyrightText: 2026 ahouts# SPDX-License-Identifier: GPL-2.0-or-later[package]name = "webengineviewer-slugrewrite"version = "0.1.0"edition = "2021"[lib]crate-type = ["staticlib"][build-dependencies]cxx-build = "1.0"[dependencies]cxx = "1.0"
{"KPlugin": {"Description": "This plugin rewrites URL prefixes in web views.","EnabledByDefault": false,"Name": "Slug Rewrite","Version": "1.0"}}
- remove enable toggle, the plugin itself is already toggabable- investigate functionality, in practice neither the rendered content nor clicked links are rewritten
# Maintainer: ahoutspkgname=akregator-url-rewrite-pluginpkgver=1.0.0pkgrel=1pkgdesc='KDE PIM WebEngine URL interceptor plugin for rewriting URL prefixes in Akregator RSS feed views'arch=(x86_64)license=(GPL-2.0-or-later)options=(!lto)depends=(messagelibpimcommon)makedepends=(cmakecorrosionextra-cmake-modulesrust)build() {cmake -B build -S "$startdir" \-DCMAKE_BUILD_TYPE=Release \-DCMAKE_INSTALL_PREFIX=/usrcmake --build build}package() {DESTDIR="$pkgdir" cmake --install build}
# SPDX-FileCopyrightText: 2026 ahouts# SPDX-License-Identifier: GPL-2.0-or-later[workspace]members = ["rs/slugrewrite/"]resolver = "2"[profile.release]lto = truepanic = 'abort'
# This file is automatically @generated by Cargo.# It is not intended for manual editing.version = 4[[package]]name = "anstyle"version = "1.0.14"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"[[package]]name = "cc"version = "1.2.58"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1"dependencies = ["find-msvc-tools","shlex",][[package]]name = "clap"version = "4.6.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"dependencies = ["clap_builder",][[package]]name = "clap_builder"version = "4.6.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"dependencies = ["anstyle","clap_lex","strsim",][[package]]name = "clap_lex"version = "1.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"[[package]]name = "codespan-reporting"version = "0.13.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681"dependencies = ["serde","termcolor","unicode-width",][[package]]name = "cxx"version = "1.0.194"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "747d8437319e3a2f43d93b341c137927ca70c0f5dabeea7a005a73665e247c7e"dependencies = ["cc","cxx-build","cxxbridge-cmd","cxxbridge-flags","cxxbridge-macro","foldhash","link-cplusplus",][[package]]name = "cxx-build"version = "1.0.194"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b0f4697d190a142477b16aef7da8a99bfdc41e7e8b1687583c0d23a79c7afc1e"dependencies = ["cc","codespan-reporting","indexmap","proc-macro2","quote","scratch","syn",][[package]]name = "cxxbridge-cmd"version = "1.0.194"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d0956799fa8678d4c50eed028f2de1c0552ae183c76e976cf7ca8c4e36a7c328"dependencies = ["clap","codespan-reporting","indexmap","proc-macro2","quote","syn",][[package]]name = "cxxbridge-flags"version = "1.0.194"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "23384a836ab4f0ad98ace7e3955ad2de39de42378ab487dc28d3990392cb283a"[[package]]name = "cxxbridge-macro"version = "1.0.194"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e6acc6b5822b9526adfb4fc377b67128fdd60aac757cc4a741a6278603f763cf"dependencies = ["indexmap","proc-macro2","quote","syn",][[package]]name = "equivalent"version = "1.0.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"[[package]]name = "find-msvc-tools"version = "0.1.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"[[package]]name = "foldhash"version = "0.2.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"[[package]]name = "hashbrown"version = "0.16.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"[[package]]name = "indexmap"version = "2.13.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"dependencies = ["equivalent","hashbrown",][[package]]name = "link-cplusplus"version = "1.0.12"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7f78c730aaa7d0b9336a299029ea49f9ee53b0ed06e9202e8cb7db9bae7b8c82"dependencies = ["cc",][[package]]name = "proc-macro2"version = "1.0.106"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"dependencies = ["unicode-ident",][[package]]name = "quote"version = "1.0.45"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"dependencies = ["proc-macro2",][[package]]name = "scratch"version = "1.0.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2"[[package]]name = "serde"version = "1.0.228"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"dependencies = ["serde_core","serde_derive",][[package]]name = "serde_core"version = "1.0.228"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"dependencies = ["serde_derive",][[package]]name = "serde_derive"version = "1.0.228"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"dependencies = ["proc-macro2","quote","syn",][[package]]name = "shlex"version = "1.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"[[package]]name = "strsim"version = "0.11.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"[[package]]name = "syn"version = "2.0.117"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"dependencies = ["proc-macro2","quote","unicode-ident",][[package]]name = "termcolor"version = "1.4.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"dependencies = ["winapi-util",][[package]]name = "unicode-ident"version = "1.0.24"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"[[package]]name = "unicode-width"version = "0.2.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"[[package]]name = "webengineviewer-slugrewrite"version = "0.1.0"dependencies = ["cxx","cxx-build",][[package]]name = "winapi-util"version = "0.1.11"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"dependencies = ["windows-sys",][[package]]name = "windows-link"version = "0.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"[[package]]name = "windows-sys"version = "0.61.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"dependencies = ["windows-link",]
# SPDX-FileCopyrightText: 2026 ahouts# SPDX-License-Identifier: GPL-2.0-or-latercmake_minimum_required(VERSION 3.29)project(slugrewrite-plugin VERSION 1.0.0)set(KF_MIN_VERSION "6.22.0")set(QT_REQUIRED_VERSION "6.9.0")find_package(ECM ${KF_MIN_VERSION} CONFIG REQUIRED)set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})include(KDEInstallDirs)include(KDECMakeSettings)include(KDECompilerSettings NO_POLICY_SCOPE)include(ECMQtDeclareLoggingCategory)find_package(Qt6 ${QT_REQUIRED_VERSION} REQUIRED COMPONENTS WebEngineWidgets Widgets)find_package(KF6 ${KF_MIN_VERSION} REQUIRED COMPONENTS I18n ConfigWidgets CoreAddons)find_package(KPim6WebEngineViewer CONFIG REQUIRED)find_package(KPim6MessageViewer CONFIG REQUIRED)find_package(KPim6PimCommon CONFIG REQUIRED)find_package(Corrosion CONFIG REQUIRED)# Rust crateadd_custom_target(slugrewrite_rsSOURCESrs/slugrewrite/Cargo.tomlrs/slugrewrite/build.rsrs/slugrewrite/src/lib.rsrs/slugrewrite/src/slugrewrite.rs)corrosion_import_crate(MANIFEST_PATH ${CMAKE_CURRENT_SOURCE_DIR}/rs/slugrewrite/Cargo.toml)# CXX bridge include path (version-dependent, same pattern as kdepim-addons adblock)if(Corrosion_VERSION VERSION_LESS 0.6.0)set(corrosion_build_dir "build")else()string(SHA1 cargo_path_hash ${CMAKE_CURRENT_SOURCE_DIR}/rs/slugrewrite/Cargo.toml)string(SUBSTRING "${cargo_path_hash}" 0 5 cargo_path_hash)set(corrosion_build_dir "slugrewrite_${cargo_path_hash}")endif()# Plugin targetkcoreaddons_add_plugin(webengineviewer_slugrewritepluginINSTALL_NAMESPACE pim6/webengineviewer/urlinterceptor)target_sources(webengineviewer_slugrewritepluginPRIVATEslugrewritepluginurlinterceptor.hslugrewritepluginurlinterceptor.cppslugrewriteinterceptorinterface.hslugrewriteinterceptorinterface.cppslugrewriteengine.hslugrewriteengine.cppslugrewriteconfiguredialog.hslugrewriteconfiguredialog.cppslugrewriteconfigurewidget.hslugrewriteconfigurewidget.cppslugrewriteruledialog.hslugrewriteruledialog.cpp)kconfig_add_kcfg_files(webengineviewer_slugrewritepluginsettings/slugrewritesettings.kcfgc)ecm_qt_declare_logging_category(webengineviewer_slugrewritepluginHEADER slugrewriteinterceptor_debug.hIDENTIFIER SLUGREWRITEINTERCEPTOR_LOGCATEGORY_NAME org.kde.pim.slugrewriteinterceptorDESCRIPTION "slugrewrite url interceptor plugin")target_include_directories(webengineviewer_slugrewritepluginPRIVATE${CMAKE_BINARY_DIR}/cargo/${corrosion_build_dir}/${Rust_CARGO_TARGET}/cxxbridge/webengineviewer-slugrewrite/src/)target_link_libraries(webengineviewer_slugrewritepluginKPim6::MessageViewerKPim6::WebEngineViewerKPim6::PimCommonKF6::I18nKF6::ConfigWidgetsKF6::CoreAddonsQt::WebEngineWidgets)# Link Rust static lib (target name depends on Corrosion version)if(Corrosion_VERSION VERSION_LESS 0.5.0)target_link_libraries(webengineviewer_slugrewriteplugin webengineviewer-slugrewrite)else()target_link_libraries(webengineviewer_slugrewriteplugin webengineviewer_slugrewrite)endif()
.git.DS_Store/akregator-url-rewrite-plugin-*.pkg.*build/pkg/target.claude