Основная структура

This commit is contained in:
2023-03-27 15:04:48 +04:00
parent d2ed8eaf58
commit f90f0c542b
13 changed files with 12384 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
node_modules
+35
View File
@@ -0,0 +1,35 @@
module.exports = function (grunt) {
grunt.initConfig({
browserify: {
dev: {
src: 'src/**/*.ts',
dest: 'bin/april-fools.js',
options: {
browserifyOptions: {
debug: true
},
configure: function (bundler) {
bundler.plugin(require('tsify'));
bundler.transform(require('babelify'), {
presets: ['@babel/env'],
extensions: ['.ts']
});
}
}
},
},
uglify: {
dev: {
files: {
'bin/april-fools.min.js': ['bin/april-fools.js'],
}
}
}
});
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-jsdoc-to-markdown');
grunt.registerTask('default', ['browserify', 'uglify']);
};
+270
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
!function n(r,i,s){function a(e,t){if(!i[e]){if(!r[e]){var o="function"==typeof require&&require;if(!t&&o)return o(e,!0);if(c)return c(e,!0);throw(t=new Error("Cannot find module '"+e+"'")).code="MODULE_NOT_FOUND",t}o=i[e]={exports:{}},r[e][0].call(o.exports,function(t){return a(r[e][1][t]||t)},o,o.exports,n,r,i,s)}return i[e].exports}for(var c="function"==typeof require&&require,t=0;t<s.length;t++)a(s[t]);return a}({1:[function(t,e,o){"use strict";var i=function(){return(i=Object.assign||function(t){for(var e,o=1,n=arguments.length;o<n;o++)for(var r in e=arguments[o])Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t}).apply(this,arguments)};define(["require","exports"],function(t,e){function o(){this.jokes={}}Object.defineProperty(e,"__esModule",{value:!0}),e.AprilFoolsJokeClass=void 0,o.prototype.add=function(t){this.jokes[t.id]=t},o.prototype.setSettings=function(t){for(var e=0,o=Object.entries(t);e<o.length;e++){var n=o[e],r=n[0],n=n[1];this.jokes[r].settings=i(i({},this.jokes[r].settings),n)}},o.prototype.check=function(t){return Math.random()<.01*t},o.prototype.start=function(t,e){void 0===e&&(e=!1),t in this.jokes&&(t=this.jokes[t],e||this.check(t.settings.chance))&&t.start()},o.prototype.startAll=function(){for(var t=0,e=Object.keys(this.jokes);t<e.length;t++){var o=e[t];this.start(o)}},e.AprilFoolsJokeClass=o})},{}],2:[function(t,e,o){"use strict";n=function(t,e){return(n=Object.setPrototypeOf||({__proto__:[]}instanceof Array?function(t,e){t.__proto__=e}:function(t,e){for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o])}))(t,e)};var n,s=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function o(){this.constructor=t}n(t,e),t.prototype=null===e?Object.create(e):(o.prototype=e.prototype,new o)};define(["require","exports"],function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.StopableJoke=e.Joke=void 0;function o(){}e.Joke=o,s(i,n=o);var n,r=i;function i(){return null!==n&&n.apply(this,arguments)||this}e.StopableJoke=r})},{}],3:[function(t,e,o){"use strict";n=function(t,e){return(n=Object.setPrototypeOf||({__proto__:[]}instanceof Array?function(t,e){t.__proto__=e}:function(t,e){for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o])}))(t,e)};var n,i=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function o(){this.constructor=t}n(t,e),t.prototype=null===e?Object.create(e):(o.prototype=e.prototype,new o)};define(["require","exports","../joke"],function(t,e,o){Object.defineProperty(e,"__esModule",{value:!0}),e.ShakeJokeSettings=e.ShakeJoke=void 0;n=o.StopableJoke,i(r,n),r.prototype.rand=function(t){return t+this.settings.force*(2*Math.random()-1)},r.prototype.start=function(){var s=this;this.items=$(this.settings.selector),this.items.each(function(t,e){var o={};s.settings.directions.forEach(function(t){o[t]=parseInt($(e).css("margin-"+t))}),$(e).data(s.data_name,o)}),this.interval_id=setInterval(function(){s.items.each(function(t,e){for(var o=$(e).data(s.data_name),n=0,r=Object.entries(o);n<r.length;n++){var i=r[n];$(e).css("margin-"+i[0],s.rand(i[1]))}})},this.settings.interval)},r.prototype.stop=function(){var n=this;clearInterval(this.interval_id),this.items.each(function(t,e){var o={};n.settings.directions.forEach(function(t){$(e).css("margin-"+t,o[t])}),$(e).data(n.data_name,o)})};var n,o=r;function r(){var t=null!==n&&n.apply(this,arguments)||this;return t.data_name="april-fools-shake",t}e.ShakeJoke=o,e.ShakeJokeSettings=function(){this.chance=1,this.directions=["top","left","bottom","left"],this.selector="[id^=pun]",this.interval=100,this.force=.5}})},{}],4:[function(t,e,o){"use strict";define(["require","exports","./handler","./jokes/shake"],function(t,e,o,n){var r;Object.defineProperty(e,"__esModule",{value:!0}),window.AprilJokes=(e=[n.ShakeJoke],r=new o.AprilFoolsJokeClass,e.forEach(function(t){r.add(new t)}),r)})},{}]},{},[1,2,3,4]);
+174
View File
@@ -0,0 +1,174 @@
## Classes
<dl>
<dt><a href="#AprilFoolsJokeClass">AprilFoolsJokeClass</a></dt>
<dd><p>Блок обработки перво-апрельских шуток</p></dd>
<dt><a href="#Joke">Joke</a></dt>
<dd><p>Объект, описывающий шутку</p></dd>
<dt><a href="#ShakeJoke">ShakeJoke</a></dt>
<dd><p>Форумо-трясение</p>
<p>Страница форума начинает трястись</p></dd>
</dl>
## Members
<dl>
<dt><a href="#AprilFoolsJokeClass">AprilFoolsJokeClass</a></dt>
<dd><p>Объект хранения шуток</p></dd>
<dt><a href="#Joke">Joke</a></dt>
<dd><p>Объект, описывающий шутку, которая может быть остановлена</p></dd>
</dl>
<a name="AprilFoolsJokeClass"></a>
## AprilFoolsJokeClass
<p>Блок обработки перво-апрельских шуток</p>
**Kind**: global class
**Author**: Kozhilya
* [AprilFoolsJokeClass](#AprilFoolsJokeClass)
* [.add(joke)](#AprilFoolsJokeClass+add)
* [.setSettings(settings)](#AprilFoolsJokeClass+setSettings)
* [.check(chance)](#AprilFoolsJokeClass+check) ⇒ <code>boolean</code>
* [.start(id, forced)](#AprilFoolsJokeClass+start)
* [.startAll()](#AprilFoolsJokeClass+startAll)
<a name="AprilFoolsJokeClass+add"></a>
### aprilFoolsJokeClass.add(joke)
<p>Добавление шутки</p>
**Kind**: instance method of [<code>AprilFoolsJokeClass</code>](#AprilFoolsJokeClass)
| Param |
| --- |
| joke |
<a name="AprilFoolsJokeClass+setSettings"></a>
### aprilFoolsJokeClass.setSettings(settings)
<p>Запись новых настроек</p>
**Kind**: instance method of [<code>AprilFoolsJokeClass</code>](#AprilFoolsJokeClass)
| Param |
| --- |
| settings |
<a name="AprilFoolsJokeClass+check"></a>
### aprilFoolsJokeClass.check(chance) ⇒ <code>boolean</code>
<p>Проверка вероятности</p>
**Kind**: instance method of [<code>AprilFoolsJokeClass</code>](#AprilFoolsJokeClass)
**Returns**: <code>boolean</code> - <p>Флаг срабатывания (true - сработало)</p>
| Param | Type | Description |
| --- | --- | --- |
| chance | <code>number</code> | <p>Вероятность срабатывания</p> |
<a name="AprilFoolsJokeClass+start"></a>
### aprilFoolsJokeClass.start(id, forced)
<p>Запуск шутки</p>
**Kind**: instance method of [<code>AprilFoolsJokeClass</code>](#AprilFoolsJokeClass)
| Param | Type | Default |
| --- | --- | --- |
| id | | |
| forced | <code>boolean</code> | <code>false</code> |
<a name="AprilFoolsJokeClass+startAll"></a>
### aprilFoolsJokeClass.startAll()
<p>Запуск всех шуток</p>
**Kind**: instance method of [<code>AprilFoolsJokeClass</code>](#AprilFoolsJokeClass)
<a name="Joke"></a>
## Joke
<p>Объект, описывающий шутку</p>
**Kind**: global class
<a name="ShakeJoke"></a>
## ShakeJoke
<p>Форумо-трясение</p>
<p>Страница форума начинает трястись</p>
**Kind**: global class
**Author**: Kozhilya
<a name="AprilFoolsJokeClass"></a>
## AprilFoolsJokeClass
<p>Объект хранения шуток</p>
**Kind**: global variable
* [AprilFoolsJokeClass](#AprilFoolsJokeClass)
* [.add(joke)](#AprilFoolsJokeClass+add)
* [.setSettings(settings)](#AprilFoolsJokeClass+setSettings)
* [.check(chance)](#AprilFoolsJokeClass+check) ⇒ <code>boolean</code>
* [.start(id, forced)](#AprilFoolsJokeClass+start)
* [.startAll()](#AprilFoolsJokeClass+startAll)
<a name="AprilFoolsJokeClass+add"></a>
### aprilFoolsJokeClass.add(joke)
<p>Добавление шутки</p>
**Kind**: instance method of [<code>AprilFoolsJokeClass</code>](#AprilFoolsJokeClass)
| Param |
| --- |
| joke |
<a name="AprilFoolsJokeClass+setSettings"></a>
### aprilFoolsJokeClass.setSettings(settings)
<p>Запись новых настроек</p>
**Kind**: instance method of [<code>AprilFoolsJokeClass</code>](#AprilFoolsJokeClass)
| Param |
| --- |
| settings |
<a name="AprilFoolsJokeClass+check"></a>
### aprilFoolsJokeClass.check(chance) ⇒ <code>boolean</code>
<p>Проверка вероятности</p>
**Kind**: instance method of [<code>AprilFoolsJokeClass</code>](#AprilFoolsJokeClass)
**Returns**: <code>boolean</code> - <p>Флаг срабатывания (true - сработало)</p>
| Param | Type | Description |
| --- | --- | --- |
| chance | <code>number</code> | <p>Вероятность срабатывания</p> |
<a name="AprilFoolsJokeClass+start"></a>
### aprilFoolsJokeClass.start(id, forced)
<p>Запуск шутки</p>
**Kind**: instance method of [<code>AprilFoolsJokeClass</code>](#AprilFoolsJokeClass)
| Param | Type | Default |
| --- | --- | --- |
| id | | |
| forced | <code>boolean</code> | <code>false</code> |
<a name="AprilFoolsJokeClass+startAll"></a>
### aprilFoolsJokeClass.startAll()
<p>Запуск всех шуток</p>
**Kind**: instance method of [<code>AprilFoolsJokeClass</code>](#AprilFoolsJokeClass)
<a name="Joke"></a>
## Joke
<p>Объект, описывающий шутку, которая может быть остановлена</p>
**Kind**: global variable
+43
View File
@@ -0,0 +1,43 @@
{
"source": {
"includePattern": ".+\\.ts(doc|x)?$",
"excludePattern": ".+\\.(test|spec).ts"
},
"plugins": [
"plugins/markdown",
"node_modules/jsdoc-babel"
],
"babel": {
"extensions": [
"ts",
"tsx"
],
"ignore": [
"**/*.(test|spec).ts"
],
"babelrc": false,
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": true
}
}
],
"@babel/preset-typescript"
],
"plugins": [
"@babel/proposal-class-properties",
"@babel/proposal-object-rest-spread"
]
},
"opts": {
"encoding": "utf8",
"destination": "docs/",
"recurse": true,
"verbose": true,
"pedantic": true,
"readme": "./README.md"
}
}
+11576
View File
File diff suppressed because it is too large Load Diff
+27
View File
@@ -0,0 +1,27 @@
{
"devDependencies": {
"@babel/cli": "^7.21.0",
"@babel/core": "^7.21.3",
"@babel/preset-env": "^7.20.2",
"@babel/preset-typescript": "^7.21.0",
"@types/jquery": "^3.5.16",
"@types/markdown-it": "^12.2.3",
"@types/node": "^18.15.10",
"babelify": "^10.0.0",
"grunt": "^1.6.1",
"grunt-browserify": "^6.0.0",
"grunt-contrib-uglify": "^5.2.2",
"grunt-jsdoc-to-markdown": "^6.0.0",
"jsdoc-babel": "^0.5.0",
"jsdoc-to-markdown": "^8.0.0",
"markdown-it": "^13.0.1",
"markdown-it-container": "^3.0.0",
"tsify": "^5.0.4",
"typescript": "^5.0.2",
"uglify-js": "^3.17.4"
},
"scripts": {
"compile": "grunt & npm run jsdoc",
"jsdoc": "cmd /r \"jsdoc2md --files ./src/**/*.ts --configure ./jsdoc2md.json > ./docs/april-fools.md\""
}
}
+88
View File
@@ -0,0 +1,88 @@
import { Joke, JokeSettings } from "./joke";
/**
* Блок обработки перво-апрельских шуток
*
* @author Kozhilya
*/
export class AprilFoolsJokeClass {
/**
* Добавление шутки
*
* @param joke
*/
add(joke: Joke): void {
this.jokes[joke.id] = joke;
}
/**
* Запись новых настроек
*
* @param settings
*/
setSettings(settings: SettingsMap): void {
for (const entry of Object.entries(settings)) {
const id = entry[0];
const jokeSettings = entry[1];
this.jokes[id].settings = { ...this.jokes[id].settings, ...jokeSettings };
}
}
/**
* Проверка вероятности
*
* @param {number} chance Вероятность срабатывания
* @returns {boolean} Флаг срабатывания (true - сработало)
*/
check(chance: number): boolean {
return Math.random() < 0.01 * chance;
}
/**
* Запуск шутки
*
* @param id
* @param {boolean} forced
*/
start(id: string, forced: boolean = false) {
if (!(id in this.jokes))
return;
const joke = this.jokes[id];
if (!forced && !this.check(joke.settings.chance)) {
return;
}
joke.start();
}
/**
* Запуск всех шуток
*/
startAll() {
for (const key of Object.keys(this.jokes)) {
this.start(key);
}
}
/**
* Перечисление всех шуток
*/
jokes: JokeMap = {}
}
/**
* Объект хранения шуток
*/
interface JokeMap {
[key: string]: Joke;
}
/**
* Объект задания настроек
*/
interface SettingsMap {
[key: string]: JokeSettings;
}
+50
View File
@@ -0,0 +1,50 @@
/**
* Объект настроек шутки
*/
export interface JokeSettings {
/**
* Вероятность срабатывания в процентах (0 для отключения)
*/
chance: number;
}
/**
* Объект, описывающий шутку
*/
export abstract class Joke {
/**
* Идентификатор шутки
*/
id: string;
/**
* Настройки шутки
*/
settings: JokeSettings;
/**
* Флаг, указывающий, должна ли шутка быть запущена
*/
enabled: boolean;
/**
* Флаг, указывающий, может ли шутка быть остановлена
*/
is_stopable: boolean;
/**
* Запуск шутки
*/
abstract start(): void;
}
/**
* Объект, описывающий шутку, которая может быть остановлена
*/
export abstract class StopableJoke extends Joke
{
/**
* Остановка шутки, если возможно
*/
abstract stop(): void;
}
+90
View File
@@ -0,0 +1,90 @@
import { Joke, JokeSettings, StopableJoke } from "../joke";
/**
* Форумо-трясение
*
* Страница форума начинает трястись
*
* @author Kozhilya
*/
export class ShakeJoke extends StopableJoke {
settings: ShakeJokeSettings;
private interval_id: NodeJS.Timer;
private items: JQuery;
private data_name: string = 'april-fools-shake';
rand(a: number): number {
return a + this.settings.force * (Math.random() * 2 - 1);
}
start(): void {
this.items = $(this.settings.selector);
this.items.each((_, elem) => {
let data: ShakeJokeMargin = {};
this.settings.directions.forEach(d => {
data[d] = parseInt($(elem).css('margin-' + d));
});
$(elem).data(this.data_name, data);
});
this.interval_id = setInterval(() => {
this.items.each((_, elem) => {
const data: ShakeJokeMargin = $(elem).data(this.data_name);
for (const entry of Object.entries(data)) {
$(elem).css('margin-' + entry[0], this.rand(entry[1]))
}
});
}, this.settings.interval);
}
stop(): void {
clearInterval(this.interval_id);
this.items.each((_, elem) => {
let data: ShakeJokeMargin = {};
this.settings.directions.forEach(d => {
$(elem).css('margin-' + d, data[d]);
});
$(elem).data(this.data_name, data);
});
}
}
export class ShakeJokeSettings implements JokeSettings {
chance: number = 1;
/**
* Направление тряски
*/
directions: string[] = ['top', 'left', 'bottom', 'left'];
/**
* Селектор всех элементов, которые будут трястись
*/
selector: string = '[id^=pun]';
/**
* Частота тряски
*/
interval: number = 100;
/**
* Сила тряски
*/
force: number = 0.5;
}
interface ShakeJokeMargin {
[key: string]: number;
}
+17
View File
@@ -0,0 +1,17 @@
import { AprilFoolsJokeClass } from "./handler";
import { Joke } from "./joke";
import { ShakeJoke } from "./jokes/shake";
(window as any).AprilJokes = ((jokes: JokeClassList): AprilFoolsJokeClass => {
const cl = new AprilFoolsJokeClass();
jokes.forEach(joke => {
cl.add(new joke());
});
return cl;
})([
ShakeJoke,
]);
interface JokeClassList extends Array<new () => Joke> {}
+12
View File
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"module": "AMD",
"lib": ["es2017", "dom"],
"rootDir": "./src/",
"outFile": "./bin/april-fools.js",
"moduleResolution": "nodenext"
},
"files": [
"src/main.ts"
]
}