DEV: Update linting config and run gjs-codemod

This commit is contained in:
Jarek Radosz 2025-06-05 12:34:48 +02:00 committed by GitHub
parent 123dc9e6d8
commit a98a223a35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
52 changed files with 957 additions and 813 deletions

View File

@ -1,3 +1,4 @@
< 3.5.0.beta5-dev: bd9af0b9a577bfd2c01cc8b81a782a4e8b81b9c5
< 3.5.0.beta1-dev: 6ceba62e985223c269782c4bc9a1bdc4a5adba28 < 3.5.0.beta1-dev: 6ceba62e985223c269782c4bc9a1bdc4a5adba28
< 3.4.0.beta2-dev: 7685ebf396c93e8accc5a76a81fcec4384a73fa3 < 3.4.0.beta2-dev: 7685ebf396c93e8accc5a76a81fcec4384a73fa3
< 3.4.0.beta1-dev: da38a4c053b68d7076db4441cfe86b473979945d < 3.4.0.beta1-dev: da38a4c053b68d7076db4441cfe86b473979945d

View File

@ -14,30 +14,31 @@ GEM
securerandom (>= 0.3) securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5) tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1) uri (>= 0.13.1)
ast (2.4.2) ast (2.4.3)
base64 (0.2.0) base64 (0.3.0)
benchmark (0.4.0) benchmark (0.4.1)
bigdecimal (3.1.9) bigdecimal (3.2.0)
concurrent-ruby (1.3.5) concurrent-ruby (1.3.5)
connection_pool (2.5.0) connection_pool (2.5.3)
drb (2.2.1) drb (2.2.3)
i18n (1.14.7) i18n (1.14.7)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
json (2.10.2) json (2.12.2)
language_server-protocol (3.17.0.4) language_server-protocol (3.17.0.5)
lint_roller (1.1.0) lint_roller (1.1.0)
logger (1.6.6) logger (1.7.0)
minitest (5.25.5) minitest (5.25.5)
parallel (1.26.3) parallel (1.27.0)
parser (3.3.7.1) parser (3.3.8.0)
ast (~> 2.4.1) ast (~> 2.4.1)
racc racc
prettier_print (1.2.1) prettier_print (1.2.1)
prism (1.4.0)
racc (1.8.1) racc (1.8.1)
rack (3.1.12) rack (3.1.15)
rainbow (3.1.1) rainbow (3.1.1)
regexp_parser (2.10.0) regexp_parser (2.10.0)
rubocop (1.74.0) rubocop (1.75.8)
json (~> 2.3) json (~> 2.3)
language_server-protocol (~> 3.17.0.2) language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0) lint_roller (~> 1.1.0)
@ -45,11 +46,12 @@ GEM
parser (>= 3.3.0.2) parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0) regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.38.0, < 2.0) rubocop-ast (>= 1.44.0, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0) unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.38.1) rubocop-ast (1.44.1)
parser (>= 3.3.1.0) parser (>= 3.3.7.2)
prism (~> 1.4)
rubocop-capybara (2.22.1) rubocop-capybara (2.22.1)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1) rubocop (~> 1.72, >= 1.72.1)
@ -65,13 +67,13 @@ GEM
rubocop-factory_bot (2.27.1) rubocop-factory_bot (2.27.1)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1) rubocop (~> 1.72, >= 1.72.1)
rubocop-rails (2.30.3) rubocop-rails (2.32.0)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.72.1, < 2.0) rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0) rubocop-ast (>= 1.44.0, < 2.0)
rubocop-rspec (3.5.0) rubocop-rspec (3.6.0)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1) rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec_rails (2.31.0) rubocop-rspec_rails (2.31.0)
@ -97,4 +99,4 @@ DEPENDENCIES
syntax_tree syntax_tree
BUNDLED WITH BUNDLED WITH
2.6.6 2.6.9

View File

@ -0,0 +1,34 @@
import { action } from "@ember/object";
import { mapBy } from "@ember/object/computed";
import { classNames } from "@ember-decorators/component";
import DButton from "discourse/components/d-button";
import { makeArray } from "discourse/lib/helpers";
import HouseAdsChooser from "./house-ads-chooser";
import HouseAdsSetting from "./house-ads-setting";
@classNames("house-ads-setting house-ads-list-setting")
export default class HouseAdsListSetting extends HouseAdsSetting {
@mapBy("allAds", "name") adNames;
@action
changeAdValue(value) {
const settingValue = makeArray(value).join("|");
this.set("adValue", settingValue);
}
<template>
<label for={{this.name}}>{{this.title}}</label>
<HouseAdsChooser
@settingValue={{this.adValue}}
@choices={{this.adNames}}
@onChange={{this.changeAdValue}}
/>
<div class="setting-controls">
{{#if this.changed}}
<DButton class="ok" @action={{action "save"}} @icon="check" />
<DButton class="cancel" @action={{action "cancel"}} @icon="xmark" />
{{/if}}
</div>
<p class="help">{{this.help}}</p>
</template>
}

View File

@ -1,6 +1,8 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { classNames } from "@ember-decorators/component"; import { classNames } from "@ember-decorators/component";
import DButton from "discourse/components/d-button";
import TextField from "discourse/components/text-field";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import { i18n as computedI18n, propertyNotEqual } from "discourse/lib/computed"; import { i18n as computedI18n, propertyNotEqual } from "discourse/lib/computed";
@ -55,4 +57,16 @@ export default class HouseAdsSetting extends Component {
cancel() { cancel() {
this.set("adValue", this.get("value")); this.set("adValue", this.get("value"));
} }
<template>
<label for={{this.name}}>{{this.title}}</label>
<TextField @value={{this.adValue}} @classNames="house-ads-text-input" />
<div class="setting-controls">
{{#if this.changed}}
<DButton class="ok" @action={{action "save"}} @icon="check" />
<DButton class="cancel" @action={{action "cancel"}} @icon="xmark" />
{{/if}}
</div>
<p class="help">{{this.help}}</p>
</template>
} }

View File

@ -0,0 +1,62 @@
import { LinkTo } from "@ember/routing";
import RouteTemplate from "ember-route-template";
import DButton from "discourse/components/d-button";
import routeAction from "discourse/helpers/route-action";
import { i18n } from "discourse-i18n";
import HouseAdsListSetting from "../components/house-ads-list-setting";
export default RouteTemplate(
<template>
<section class="house-ads-settings content-body">
<div>{{i18n "admin.adplugin.house_ads.description"}}</div>
{{#if @controller.houseAds.length}}
<form class="form-horizontal">
<HouseAdsListSetting
@name="topic_list_top"
@value={{@controller.adSettings.topic_list_top}}
@allAds={{@controller.houseAds}}
@adSettings={{@controller.adSettings}}
/>
<HouseAdsListSetting
@name="topic_above_post_stream"
@value={{@controller.adSettings.topic_above_post_stream}}
@allAds={{@controller.houseAds}}
@adSettings={{@controller.adSettings}}
/>
<HouseAdsListSetting
@name="topic_above_suggested"
@value={{@controller.adSettings.topic_above_suggested}}
@allAds={{@controller.houseAds}}
@adSettings={{@controller.adSettings}}
/>
<HouseAdsListSetting
@name="post_bottom"
@value={{@controller.adSettings.post_bottom}}
@allAds={{@controller.houseAds}}
@adSettings={{@controller.adSettings}}
/>
<HouseAdsListSetting
@name="topic_list_between"
@value={{@controller.adSettings.topic_list_between}}
@allAds={{@controller.houseAds}}
@adSettings={{@controller.adSettings}}
/>
<DButton
@label="admin.adplugin.house_ads.more_settings"
@icon="gear"
@action={{routeAction "moreSettings"}}
class="btn-default"
/>
</form>
{{else}}
<p>
{{#LinkTo route="adminPlugins.houseAds.show" model="new"}}
{{i18n "admin.adplugin.house_ads.get_started"}}
{{/LinkTo}}
</p>
{{/if}}
</section>
</template>
);

View File

@ -0,0 +1,97 @@
import { Input } from "@ember/component";
import { fn, hash } from "@ember/helper";
import RouteTemplate from "ember-route-template";
import AceEditor from "discourse/components/ace-editor";
import DButton from "discourse/components/d-button";
import TextField from "discourse/components/text-field";
import { i18n } from "discourse-i18n";
import GroupChooser from "select-kit/components/group-chooser";
import HouseAdsCategorySelector from "../components/house-ads-category-selector";
export default RouteTemplate(
<template>
<section class="edit-house-ad content-body">
<h1><TextField
@value={{@controller.buffered.name}}
class="house-ad-name"
/></h1>
<div class="controls">
<AceEditor
@content={{@controller.buffered.html}}
@onChange={{fn (mut @controller.buffered.html)}}
@mode="html"
/>
</div>
<div class="controls">
<div class="visibility-settings">
<div>
<Input
@type="checkbox"
@checked={{@controller.buffered.visible_to_logged_in_users}}
class="visible-to-logged-in-checkbox"
/>
<span>{{i18n
"admin.adplugin.house_ads.show_to_logged_in_users"
}}</span>
</div>
<div>
<Input
class="visible-to-anonymous-checkbox"
@type="checkbox"
@checked={{@controller.buffered.visible_to_anons}}
/>
<span>{{i18n "admin.adplugin.house_ads.show_to_anons"}}</span>
</div>
<HouseAdsCategorySelector
@categories={{@controller.site.categories}}
@selectedCategories={{@controller.selectedCategories}}
@onChange={{@controller.setCategoryIds}}
@options={{hash allowAny=true}}
class="house-ads-categories"
/>
<div class="description">
{{i18n "admin.adplugin.house_ads.category_chooser_description"}}
</div>
<GroupChooser
@content={{@controller.site.groups}}
@onChange={{@controller.setGroupIds}}
@value={{@controller.selectedGroups}}
class="banner-groups"
/>
<div class="description">
{{i18n "admin.adplugin.house_ads.group_chooser_description"}}
</div>
</div>
<DButton
@action={{@controller.save}}
@disabled={{@controller.disabledSave}}
@label="admin.adplugin.house_ads.save"
class="btn-primary save-button"
/>
{{#if @controller.saving}}
{{@controller.savingStatus}}
{{else}}
{{#unless @controller.disabledSave}}
<DButton @action={{@controller.cancel}} @label="cancel" />
{{/unless}}
{{/if}}
<DButton
@action={{@controller.openPreview}}
@label="admin.adplugin.house_ads.preview"
/>
<DButton
@action={{@controller.destroy}}
@label="admin.adplugin.house_ads.delete"
class="btn-danger delete-button"
/>
</div>
</section>
</template>
);

View File

@ -0,0 +1,43 @@
import { LinkTo } from "@ember/routing";
import RouteTemplate from "ember-route-template";
import icon from "discourse/helpers/d-icon";
import { i18n } from "discourse-i18n";
export default RouteTemplate(
<template>
<div class="adplugin-mgmt">
<h1>{{i18n "admin.adplugin.house_ads.title"}}</h1>
{{#if @controller.model.length}}
<div class="content-list">
<div class="house-ads-actions">
<LinkTo
@route="adminPlugins.houseAds.show"
@model="new"
class="btn btn-primary"
>
{{icon "plus"}}
<span>{{i18n "admin.adplugin.house_ads.new"}}</span>
</LinkTo>
<LinkTo
@route="adminPlugins.houseAds.index"
class="btn btn-default"
>
{{icon "gear"}}
<span>{{i18n "admin.adplugin.house_ads.settings"}}</span>
</LinkTo>
</div>
<ul class="house-ads-list">
{{#each @controller.model as |ad|}}
<li class="house-ads-list-item">
{{#LinkTo route="adminPlugins.houseAds.show" model=ad.id}}
{{ad.name}}
{{/LinkTo}}
</li>
{{/each}}
</ul>
</div>
{{/if}}
{{outlet}}
</div>
</template>
);

View File

@ -1,13 +0,0 @@
<label for={{this.name}}>{{this.title}}</label>
{{house-ads-chooser
settingValue=this.adValue
choices=this.adNames
onChange=this.changeAdValue
}}
<div class="setting-controls">
{{#if this.changed}}
<DButton class="ok" @action={{action "save"}} @icon="check" />
<DButton class="cancel" @action={{action "cancel"}} @icon="xmark" />
{{/if}}
</div>
<p class="help">{{this.help}}</p>

View File

@ -1,16 +0,0 @@
import { action } from "@ember/object";
import { mapBy } from "@ember/object/computed";
import { classNames } from "@ember-decorators/component";
import { makeArray } from "discourse/lib/helpers";
import HouseAdsSetting from "discourse/plugins/discourse-adplugin/discourse/components/house-ads-setting";
@classNames("house-ads-setting house-ads-list-setting")
export default class HouseAdsListSetting extends HouseAdsSetting {
@mapBy("allAds", "name") adNames;
@action
changeAdValue(value) {
const settingValue = makeArray(value).join("|");
this.set("adValue", settingValue);
}
}

View File

@ -1,9 +0,0 @@
<label for={{this.name}}>{{this.title}}</label>
<TextField @value={{this.adValue}} @classNames="house-ads-text-input" />
<div class="setting-controls">
{{#if this.changed}}
<DButton class="ok" @action={{action "save"}} @icon="check" />
<DButton class="cancel" @action={{action "cancel"}} @icon="xmark" />
{{/if}}
</div>
<p class="help">{{this.help}}</p>

View File

@ -1,51 +0,0 @@
<section class="house-ads-settings content-body">
<div>{{i18n "admin.adplugin.house_ads.description"}}</div>
{{#if this.houseAds.length}}
<form class="form-horizontal">
{{house-ads-list-setting
name="topic_list_top"
value=this.adSettings.topic_list_top
allAds=this.houseAds
adSettings=this.adSettings
}}
{{house-ads-list-setting
name="topic_above_post_stream"
value=this.adSettings.topic_above_post_stream
allAds=this.houseAds
adSettings=this.adSettings
}}
{{house-ads-list-setting
name="topic_above_suggested"
value=this.adSettings.topic_above_suggested
allAds=this.houseAds
adSettings=this.adSettings
}}
{{house-ads-list-setting
name="post_bottom"
value=this.adSettings.post_bottom
allAds=this.houseAds
adSettings=this.adSettings
}}
{{house-ads-list-setting
name="topic_list_between"
value=this.adSettings.topic_list_between
allAds=this.houseAds
adSettings=this.adSettings
}}
<DButton
@label="admin.adplugin.house_ads.more_settings"
@icon="gear"
@action={{route-action "moreSettings"}}
class="btn-default"
/>
</form>
{{else}}
<p>
{{#link-to route="adminPlugins.houseAds.show" model="new"}}
{{i18n "admin.adplugin.house_ads.get_started"}}
{{/link-to}}
</p>
{{/if}}
</section>

View File

@ -1,78 +0,0 @@
<section class="edit-house-ad content-body">
<h1><TextField @value={{this.buffered.name}} class="house-ad-name" /></h1>
<div class="controls">
<AceEditor
@content={{this.buffered.html}}
@onChange={{fn (mut this.buffered.html)}}
@mode="html"
/>
</div>
<div class="controls">
<div class="visibility-settings">
<div>
<Input
@type="checkbox"
@checked={{this.buffered.visible_to_logged_in_users}}
class="visible-to-logged-in-checkbox"
/>
<span>{{i18n "admin.adplugin.house_ads.show_to_logged_in_users"}}</span>
</div>
<div>
<Input
class="visible-to-anonymous-checkbox"
@type="checkbox"
@checked={{this.buffered.visible_to_anons}}
/>
<span>{{i18n "admin.adplugin.house_ads.show_to_anons"}}</span>
</div>
<HouseAdsCategorySelector
@categories={{this.site.categories}}
@selectedCategories={{this.selectedCategories}}
@onChange={{this.setCategoryIds}}
@options={{hash allowAny=true}}
class="house-ads-categories"
/>
<div class="description">
{{i18n "admin.adplugin.house_ads.category_chooser_description"}}
</div>
<GroupChooser
@content={{this.site.groups}}
@onChange={{this.setGroupIds}}
@value={{this.selectedGroups}}
class="banner-groups"
/>
<div class="description">
{{i18n "admin.adplugin.house_ads.group_chooser_description"}}
</div>
</div>
<DButton
@action={{this.save}}
@disabled={{this.disabledSave}}
@label="admin.adplugin.house_ads.save"
class="btn-primary save-button"
/>
{{#if this.saving}}
{{this.savingStatus}}
{{else}}
{{#unless this.disabledSave}}
<DButton @action={{this.cancel}} @label="cancel" />
{{/unless}}
{{/if}}
<DButton
@action={{this.openPreview}}
@label="admin.adplugin.house_ads.preview"
/>
<DButton
@action={{this.destroy}}
@label="admin.adplugin.house_ads.delete"
class="btn-danger delete-button"
/>
</div>
</section>

View File

@ -1,31 +0,0 @@
<div class="adplugin-mgmt">
<h1>{{i18n "admin.adplugin.house_ads.title"}}</h1>
{{#if this.model.length}}
<div class="content-list">
<div class="house-ads-actions">
<LinkTo
@route="adminPlugins.houseAds.show"
@model="new"
class="btn btn-primary"
>
{{d-icon "plus"}}
<span>{{i18n "admin.adplugin.house_ads.new"}}</span>
</LinkTo>
<LinkTo @route="adminPlugins.houseAds.index" class="btn btn-default">
{{d-icon "gear"}}
<span>{{i18n "admin.adplugin.house_ads.settings"}}</span>
</LinkTo>
</div>
<ul class="house-ads-list">
{{#each this.model as |ad|}}
<li class="house-ads-list-item">
{{#link-to route="adminPlugins.houseAds.show" model=ad.id}}
{{ad.name}}
{{/link-to}}
</li>
{{/each}}
</ul>
</div>
{{/if}}
{{outlet}}
</div>

View File

@ -1,13 +1,26 @@
import { array } from "@ember/helper";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { service } from "@ember/service"; import { service } from "@ember/service";
import { isBlank } from "@ember/utils"; import { isBlank } from "@ember/utils";
import { tagName } from "@ember-decorators/component"; import { tagName } from "@ember-decorators/component";
import discourseComputed from "discourse/lib/decorators"; import discourseComputed from "discourse/lib/decorators";
import AdComponent from "discourse/plugins/discourse-adplugin/discourse/components/ad-component"; import { isNthPost, isNthTopicListItem } from "../helpers/slot-position";
import { import AdComponent from "./ad-component";
isNthPost, import AdbutlerAd from "./adbutler-ad";
isNthTopicListItem, import AmazonProductLinks from "./amazon-product-links";
} from "discourse/plugins/discourse-adplugin/discourse/helpers/slot-position"; import CarbonadsAd from "./carbonads-ad";
import GoogleAdsense from "./google-adsense";
import GoogleDfpAd from "./google-dfp-ad";
import HouseAd from "./house-ad";
const AD_COMPONENTS = {
"house-ad": HouseAd,
"google-adsense": GoogleAdsense,
"google-dfp-ad": GoogleDfpAd,
"amazon-product-links": AmazonProductLinks,
"carbonads-ad": CarbonadsAd,
"adbutler-ad": AdbutlerAd,
};
const adConfig = EmberObject.create({ const adConfig = EmberObject.create({
"google-adsense": { "google-adsense": {
@ -201,7 +214,7 @@ export default class AdSlot extends AdComponent {
* Depends on `router.currentRoute` so that we refresh ads when navigating around. * Depends on `router.currentRoute` so that we refresh ads when navigating around.
*/ */
@discourseComputed("placement", "availableAdTypes", "router.currentRoute") @discourseComputed("placement", "availableAdTypes", "router.currentRoute")
adComponents(placement, availableAdTypes) { adComponentNames(placement, availableAdTypes) {
if ( if (
!availableAdTypes.includes("house-ad") || !availableAdTypes.includes("house-ad") ||
availableAdTypes.length === 1 availableAdTypes.length === 1
@ -240,4 +253,23 @@ export default class AdSlot extends AdComponent {
return networkNames; return networkNames;
} }
get adComponents() {
return this.adComponentNames.map((name) => AD_COMPONENTS[name]);
}
<template>
{{#each this.adComponents as |Ad|}}
{{! Trick to force full destroy/re-render of component when route changes }}
{{#each (array this.router.currentRoute)}}
<Ad
@placement={{this.placement}}
@category={{this.category}}
@postNumber={{this.postNumber}}
@indexNumber={{this.indexNumber}}
@tagName={{this.childTagName}}
/>
{{/each}}
{{/each}}
</template>
} }

View File

@ -1,13 +0,0 @@
{{#each this.adComponents as |adComponent|}}
{{! Trick to force full destroy/re-render of component when route changes }}
{{#each (array this.router.currentRoute)}}
{{component
adComponent
placement=this.placement
category=this.category
postNumber=this.postNumber
indexNumber=this.indexNumber
tagName=this.childTagName
}}
{{/each}}
{{/each}}

View File

@ -3,7 +3,7 @@ import RSVP from "rsvp";
import discourseComputed from "discourse/lib/decorators"; import discourseComputed from "discourse/lib/decorators";
import { isTesting } from "discourse/lib/environment"; import { isTesting } from "discourse/lib/environment";
import loadScript from "discourse/lib/load-script"; import loadScript from "discourse/lib/load-script";
import AdComponent from "discourse/plugins/discourse-adplugin/discourse/components/ad-component"; import AdComponent from "./ad-component";
let _loaded = false, let _loaded = false,
_promise = null, _promise = null,
@ -150,4 +150,10 @@ export default class AdbutlerAd extends AdComponent {
} }
return this.isNthPost(parseInt(this.siteSettings.adbutler_nth_post, 10)); return this.isNthPost(parseInt(this.siteSettings.adbutler_nth_post, 10));
} }
<template>
{{#if this.showAd}}
<div id={{this.divId}} class={{this.className}}></div>
{{/if}}
</template>
} }

View File

@ -1,3 +0,0 @@
{{#if this.showAd}}
<div id={{this.divId}} class={{this.className}}></div>
{{/if}}

View File

@ -2,7 +2,8 @@ import { and } from "@ember/object/computed";
import { htmlSafe } from "@ember/template"; import { htmlSafe } from "@ember/template";
import { classNames } from "@ember-decorators/component"; import { classNames } from "@ember-decorators/component";
import discourseComputed from "discourse/lib/decorators"; import discourseComputed from "discourse/lib/decorators";
import AdComponent from "discourse/plugins/discourse-adplugin/discourse/components/ad-component"; import { i18n } from "discourse-i18n";
import AdComponent from "./ad-component";
@classNames("amazon-product-links") @classNames("amazon-product-links")
export default class AmazonProductLinks extends AdComponent { export default class AmazonProductLinks extends AdComponent {
@ -186,4 +187,41 @@ export default class AmazonProductLinks extends AdComponent {
return this.isNthPost(parseInt(this.siteSettings.amazon_nth_post_code, 10)); return this.isNthPost(parseInt(this.siteSettings.amazon_nth_post_code, 10));
} }
<template>
{{#if this.showAd}}
{{#if this.site.mobileView}}
<div
class="amazon-product-links-label"
style={{this.adTitleStyleMobile}}
><h2>{{i18n "adplugin.advertisement_label"}}</h2></div>
<iframe
style={{this.adWrapperStyleMobile}}
marginwidth="0"
marginheight="0"
scrolling="no"
frameborder="0"
src={{this.userInputMobile}}
title={{i18n "adplugin.advertisement_label"}}
>
</iframe>
{{else}}
<div class="amazon-product-links-label"><h2>{{i18n
"adplugin.advertisement_label"
}}</h2></div>
<div class="container" align="center">
<iframe
style={{this.adWrapperStyle}}
marginwidth="0"
marginheight="0"
scrolling="no"
frameborder="0"
src={{this.userInput}}
title={{i18n "adplugin.advertisement_label"}}
>
</iframe>
</div>
{{/if}}
{{/if}}
</template>
} }

View File

@ -1,34 +0,0 @@
{{#if this.showAd}}
{{#if this.site.mobileView}}
<div
class="amazon-product-links-label"
style={{this.adTitleStyleMobile}}
><h2>{{i18n "adplugin.advertisement_label"}}</h2></div>
<iframe
style={{this.adWrapperStyleMobile}}
marginwidth="0"
marginheight="0"
scrolling="no"
frameborder="0"
src={{this.userInputMobile}}
title={{i18n "adplugin.advertisement_label"}}
>
</iframe>
{{else}}
<div class="amazon-product-links-label"><h2>{{i18n
"adplugin.advertisement_label"
}}</h2></div>
<div class="container" align="center">
<iframe
style={{this.adWrapperStyle}}
marginwidth="0"
marginheight="0"
scrolling="no"
frameborder="0"
src={{this.userInput}}
title={{i18n "adplugin.advertisement_label"}}
>
</iframe>
</div>
{{/if}}
{{/if}}

View File

@ -1,6 +1,6 @@
import { htmlSafe } from "@ember/template"; import { htmlSafe } from "@ember/template";
import discourseComputed from "discourse/lib/decorators"; import discourseComputed from "discourse/lib/decorators";
import AdComponent from "discourse/plugins/discourse-adplugin/discourse/components/ad-component"; import AdComponent from "./ad-component";
export default class CarbonadsAd extends AdComponent { export default class CarbonadsAd extends AdComponent {
serve_id = null; serve_id = null;
@ -40,4 +40,12 @@ export default class CarbonadsAd extends AdComponent {
placement && serveId && showCarbonAds && showToGroups && showOnCurrentPage placement && serveId && showCarbonAds && showToGroups && showOnCurrentPage
); );
} }
<template>
{{#if this.showAd}}
{{! template-lint-disable no-forbidden-elements }}
<script src={{this.url}} id="_carbonads_js" async type="text/javascript">
</script>
{{/if}}
</template>
} }

View File

@ -1,5 +0,0 @@
{{#if this.showAd}}
{{! template-lint-disable no-forbidden-elements }}
<script src={{this.url}} id="_carbonads_js" async type="text/javascript">
</script>
{{/if}}

View File

@ -5,7 +5,8 @@ import RSVP from "rsvp";
import discourseComputed from "discourse/lib/decorators"; import discourseComputed from "discourse/lib/decorators";
import { isTesting } from "discourse/lib/environment"; import { isTesting } from "discourse/lib/environment";
import loadScript from "discourse/lib/load-script"; import loadScript from "discourse/lib/load-script";
import AdComponent from "discourse/plugins/discourse-adplugin/discourse/components/ad-component"; import { i18n } from "discourse-i18n";
import AdComponent from "./ad-component";
let _loaded = false, let _loaded = false,
_promise = null, _promise = null,
@ -247,4 +248,26 @@ export default class GoogleAdsense extends AdComponent {
parseInt(this.siteSettings.adsense_nth_post_code, 10) parseInt(this.siteSettings.adsense_nth_post_code, 10)
); );
} }
<template>
{{#if this.showAd}}
<div class="google-adsense-label"><h2>{{i18n
"adplugin.advertisement_label"
}}</h2></div>
<div
class="google-adsense-content"
id={{if this.isResponsive "google-adsense__responsive"}}
style={{this.adWrapperStyle}}
>
<ins
class="adsbygoogle"
style={{this.adInsStyle}}
data-ad-client="ca-pub-{{this.publisher_id}}"
data-ad-slot={{this.ad_code}}
data-ad-format={{this.autoAdFormat}}
>
</ins>
</div>
{{/if}}
</template>
} }

View File

@ -1,19 +0,0 @@
{{#if this.showAd}}
<div class="google-adsense-label"><h2>{{i18n
"adplugin.advertisement_label"
}}</h2></div>
<div
class="google-adsense-content"
id={{if this.isResponsive "google-adsense__responsive"}}
style={{this.adWrapperStyle}}
>
<ins
class="adsbygoogle"
style={{this.adInsStyle}}
data-ad-client="ca-pub-{{this.publisher_id}}"
data-ad-slot={{this.ad_code}}
data-ad-format={{this.autoAdFormat}}
>
</ins>
</div>
{{/if}}

View File

@ -5,7 +5,8 @@ import RSVP from "rsvp";
import discourseComputed, { on } from "discourse/lib/decorators"; import discourseComputed, { on } from "discourse/lib/decorators";
import { isTesting } from "discourse/lib/environment"; import { isTesting } from "discourse/lib/environment";
import loadScript from "discourse/lib/load-script"; import loadScript from "discourse/lib/load-script";
import AdComponent from "discourse/plugins/discourse-adplugin/discourse/components/ad-component"; import { i18n } from "discourse-i18n";
import AdComponent from "./ad-component";
let _loaded = false, let _loaded = false,
_promise = null, _promise = null,
@ -427,4 +428,29 @@ export default class GoogleDfpAd extends AdComponent {
cleanup() { cleanup() {
destroySlot(this.get("divId")); destroySlot(this.get("divId"));
} }
<template>
{{#if this.showAd}}
{{#if this.site.mobileView}}
<div class="google-dfp-ad-label" style={{this.adTitleStyleMobile}}><h2
>{{i18n "adplugin.advertisement_label"}}</h2></div>
<div
id={{this.divId}}
style={{this.adWrapperStyle}}
class="dfp-ad-unit"
align="center"
></div>
{{else}}
<div class="google-dfp-ad-label"><h2>{{i18n
"adplugin.advertisement_label"
}}</h2></div>
<div
id={{this.divId}}
style={{this.adWrapperStyle}}
class="dfp-ad-unit"
align="center"
></div>
{{/if}}
{{/if}}
</template>
} }

View File

@ -1,22 +0,0 @@
{{#if this.showAd}}
{{#if this.site.mobileView}}
<div class="google-dfp-ad-label" style={{this.adTitleStyleMobile}}><h2
>{{i18n "adplugin.advertisement_label"}}</h2></div>
<div
id={{this.divId}}
style={{this.adWrapperStyle}}
class="dfp-ad-unit"
align="center"
></div>
{{else}}
<div class="google-dfp-ad-label"><h2>{{i18n
"adplugin.advertisement_label"
}}</h2></div>
<div
id={{this.divId}}
style={{this.adWrapperStyle}}
class="dfp-ad-unit"
align="center"
></div>
{{/if}}
{{/if}}

View File

@ -4,8 +4,9 @@ import {
classNameBindings, classNameBindings,
classNames, classNames,
} from "@ember-decorators/component"; } from "@ember-decorators/component";
import htmlSafe from "discourse/helpers/html-safe";
import discourseComputed from "discourse/lib/decorators"; import discourseComputed from "discourse/lib/decorators";
import AdComponent from "discourse/plugins/discourse-adplugin/discourse/components/ad-component"; import AdComponent from "./ad-component";
const adIndex = { const adIndex = {
topic_list_top: null, topic_list_top: null,
@ -146,4 +147,10 @@ export default class HouseAd extends AdComponent {
this.refreshAd(); this.refreshAd();
} }
<template>
{{#if this.showAd}}
{{htmlSafe this.adHtml}}
{{/if}}
</template>
} }

View File

@ -1,3 +0,0 @@
{{#if this.showAd}}
{{html-safe this.adHtml}}
{{/if}}

View File

@ -0,0 +1,11 @@
import AdSlot from "./ad-slot";
const PostBottomAd = <template>
<AdSlot
@placement="post-bottom"
@category={{@model.topic.category.slug}}
@postNumber={{@model.post_number}}
/>
</template>;
export default PostBottomAd;

View File

@ -1,5 +0,0 @@
{{ad-slot
placement="post-bottom"
category=@model.topic.category.slug
postNumber=@model.post_number
}}

View File

@ -0,0 +1,29 @@
import Component from "@ember/component";
import { classNames, tagName } from "@ember-decorators/component";
import { slotContenders } from "discourse/plugins/discourse-adplugin/discourse/components/ad-slot";
import AdSlot from "../../components/ad-slot";
@tagName("tr")
@classNames("after-topic-list-item-outlet", "discourse-adplugin")
export default class DiscourseAdplugin extends Component {
static shouldRender(args, context) {
return (
args.index &&
slotContenders(
context.site,
context.siteSettings,
"topic-list-between",
args.index
).length > 0
);
}
<template>
<AdSlot
@placement="topic-list-between"
@category={{this.category.slug}}
@indexNumber={{this.index}}
@childTagName="td"
/>
</template>
}

View File

@ -1,6 +0,0 @@
{{ad-slot
placement="topic-list-between"
category=this.category.slug
indexNumber=this.index
childTagName="td"
}}

View File

@ -1,15 +0,0 @@
import { slotContenders } from "discourse/plugins/discourse-adplugin/discourse/components/ad-slot";
export default {
shouldRender(args, component) {
return (
args.index &&
slotContenders(
component.site,
component.siteSettings,
"topic-list-between",
args.index
).length > 0
);
},
};

View File

@ -0,0 +1,11 @@
import Component from "@ember/component";
import { classNames, tagName } from "@ember-decorators/component";
import AdSlot from "../../components/ad-slot";
@tagName("span")
@classNames("discovery-list-container-top-outlet", "discourse-adplugin")
export default class DiscourseAdplugin extends Component {
<template>
<AdSlot @placement="topic-list-top" @category={{this.category.slug}} />
</template>
}

View File

@ -1 +0,0 @@
{{ad-slot placement="topic-list-top" category=this.category.slug}}

View File

@ -0,0 +1,14 @@
import Component from "@ember/component";
import { classNames, tagName } from "@ember-decorators/component";
import AdSlot from "../../components/ad-slot";
@tagName("div")
@classNames("topic-above-post-stream-outlet", "discourse-adplugin")
export default class DiscourseAdplugin extends Component {
<template>
<AdSlot
@placement="topic-above-post-stream"
@category={{this.model.category.slug}}
/>
</template>
}

View File

@ -1,4 +0,0 @@
{{ad-slot
placement="topic-above-post-stream"
category=this.model.category.slug
}}

View File

@ -0,0 +1,14 @@
import Component from "@ember/component";
import { classNames, tagName } from "@ember-decorators/component";
import AdSlot from "../../components/ad-slot";
@tagName("div")
@classNames("topic-above-suggested-outlet", "discourse-adplugin")
export default class DiscourseAdplugin extends Component {
<template>
<AdSlot
@placement="topic-above-suggested"
@category={{this.model.category.slug}}
/>
</template>
}

View File

@ -1 +0,0 @@
{{ad-slot placement="topic-above-suggested" category=this.model.category.slug}}

View File

@ -1,3 +1,5 @@
@use "lib/viewport";
.google-dfp-ad { .google-dfp-ad {
padding: 3px 0; padding: 3px 0;
margin-bottom: 10px; margin-bottom: 10px;
@ -57,7 +59,7 @@
padding: 0 11px; padding: 0 11px;
} }
@media all and (max-width: 775px) { @media all and (width <= 775px) {
.google-adsense.adsense-post-bottom { .google-adsense.adsense-post-bottom {
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
@ -100,7 +102,7 @@
} }
} }
@include breakpoint(mobile-extra-large) { @include viewport.until(sm) {
.google-dfp-ad .google-dfp-ad-label { .google-dfp-ad .google-dfp-ad-label {
width: 100%; width: 100%;
text-align: center; text-align: center;
@ -132,7 +134,7 @@
clear: both; clear: both;
} }
@include breakpoint(mobile-extra-large) { @include viewport.until(sm) {
.house-creative.house-post-bottom { .house-creative.house-post-bottom {
margin: 0 0 10px 0; margin: 0 0 10px 0;
} }
@ -208,7 +210,7 @@
margin: 10px 0 10px 56px; margin: 10px 0 10px 56px;
} }
@include breakpoint(mobile-extra-large) { @include viewport.until(sm) {
.adbutler-post-bottom { .adbutler-post-bottom {
margin: 10px 0; margin: 10px 0;
} }

View File

@ -1,11 +1,11 @@
{ {
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"@discourse/lint-configs": "2.11.1", "@discourse/lint-configs": "2.23.0",
"ember-template-lint": "7.0.1", "ember-template-lint": "7.7.0",
"eslint": "9.22.0", "eslint": "9.28.0",
"prettier": "3.5.3", "prettier": "3.5.3",
"stylelint": "16.16.0" "stylelint": "16.20.0"
}, },
"engines": { "engines": {
"node": ">= 22", "node": ">= 22",

881
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
describe "Admin House Ad", type: :system, js: true do describe "Admin House Ad", type: :system do
fab!(:admin) fab!(:admin)
let(:house_ad) do let(:house_ad) do
AdPlugin::HouseAd.create( AdPlugin::HouseAd.create(
@ -14,7 +14,7 @@ describe "Admin House Ad", type: :system, js: true do
before { sign_in(admin) } before { sign_in(admin) }
describe "when visiting the page for creating new ads" do describe "when visiting the page for creating new ads" do
it "should have the visibility checkboxes on by default" do it "has the visibility checkboxes on by default" do
visit("/admin/plugins/pluginad/house_creatives/new") visit("/admin/plugins/pluginad/house_creatives/new")
expect(find("input.visible-to-anonymous-checkbox").checked?).to eq(true) expect(find("input.visible-to-anonymous-checkbox").checked?).to eq(true)