New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

wiki-plugin-activity

Package Overview
Dependencies
Maintainers
0
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

wiki-plugin-activity - npm Package Compare versions

Comparing version 0.6.1 to 0.7.0-rc.0

.github/workflows/test.yml

49

package.json
{
"name": "wiki-plugin-activity",
"version": "0.6.1",
"version": "0.7.0-rc.0",
"description": "Federated Wiki - Activity Plug-in",

@@ -16,33 +16,25 @@ "keywords": [

"contributors": [
{
"name": "Nick Niemeir",
"email": "nick.niemeir@gmail.com",
"url": "http://nrn.io"
},
{
"name": "Paul Rodwell",
"email": "paul.rodwell@btinternet.com",
"url": "http://wiki-paul90.rhcloud.com"
}
"Ward Cunningham <ward@c2.com>",
"Nick Niemeir <nick.niemeir@gmail.com>",
"Marcin Cieslak <saper@saper.info>",
"Paul Rodwell <paul.rodwell@btinternet.com>",
"Robert Best <chessscholar@gmail.com>"
],
"scripts": {
"test": "grunt mochaTest"
"build": "npm run clean; mocha; node --no-warnings scripts/build-client.js",
"clean": "rm client/activity.js client/activity.js.map",
"prettier:format": "prettier --write './**/*.js'",
"prettier:check": "prettier --check ./**/*.js",
"test": "mocha",
"update-authors": "node scripts/update-authors.cjs"
},
"dependencies": {
"lodash": "^4.17.19",
"virtual-dom": "~2"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/preset-env": "^7.23.2",
"coffeeify": "^3.0.1",
"coffeescript": "^2.4.1",
"@eslint/js": "^9.14.0",
"esbuild": "^0.24.0",
"eslint": "^9.14.0",
"expect.js": "*",
"grunt": "^1.2.1",
"grunt-browserify": "^6.0.0",
"grunt-contrib-clean": "^2.0.0",
"grunt-contrib-watch": "^1.1.0",
"grunt-git-authors": "~3",
"grunt-mocha-test": "^0.13.3",
"mocha": "^10.1.0"
"globals": "^15.12.0",
"mocha": "^10.1.0",
"prettier": "3.3.3",
"virtual-dom": "~2"
},

@@ -57,5 +49,6 @@ "license": "MIT",

},
"type": "module",
"engines": {
"node": ">=6.0"
"node": ">=18.x"
}
}

@@ -5,1 +5,6 @@ # Federated Wiki - Activity Plugin

Page names used on multiple sites are grouped together, with the most current site on the right.
The client source code is in `src/activity.js`, tests in `test/test.js`
Running `npm run build` will use `scripts/build-client.js` to build the client `client/activity.js`
together with a map file.

@@ -8,200 +8,419 @@ /*

import { h } from 'virtual-dom';
import diff from 'virtual-dom/diff.js';
import patch from 'virtual-dom/patch.js';
import createElement from 'virtual-dom/create-element.js';
import _ from 'lodash';
import { h } from 'virtual-dom'
import diff from 'virtual-dom/diff.js'
import patch from 'virtual-dom/patch.js'
import createElement from 'virtual-dom/create-element.js'
const escape = (line) => {
return line
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
};
const escape = line => {
return line.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
}
const setDefaults = (query) => {
query.since = 0;
query.listing = [];
query.errors = 0;
query.includeNeighbors = true;
query.twins = 0;
query.sortOrder = "date";
query.searchTerm = '';
query.searchResults = '';
query.rosterResults = {};
query.mine = "yes";
query.conversation = false;
query.narrative = false;
};
const setDefaults = query => {
query.since = 0
query.listing = []
query.errors = 0
query.includeNeighbors = true
query.twins = 0
query.sortOrder = 'date'
query.searchTerm = ''
query.searchResults = ''
query.rosterResults = {}
query.mine = 'yes'
query.conversation = false
query.narrative = false
}
const open_conversation = (this_page, uri) => {
const tuples = uri.split('/');
tuples.shift();
const tuples = uri.split('/')
tuples.shift()
while (tuples.length) {
const site = tuples.shift();
const slug = tuples.shift();
wiki.doInternalLink(slug, this_page, site);
this_page = null;
const site = tuples.shift()
const slug = tuples.shift()
wiki.doInternalLink(slug, this_page, site)
this_page = null
}
};
}
const parse = (query, text, $item, item) => {
query.listing = [];
query.errors = 0;
const lines = text.split(/\r?\n/);
const parse = (query, text, $item) => {
query.listing = []
query.errors = 0
const lines = text.split(/\r?\n/)
for (const line of lines) {
const words = line.match(/\S+/g);
if (!words) continue;
const words = line.match(/\S+/g)
if (!words) continue
let html = escape(line);
const today = new Date();
const todayStart = today.setHours(0, 0, 0, 0);
let html = escape(line)
const today = new Date()
const todayStart = today.setHours(0, 0, 0, 0)
try {
const [, op, arg] = line.match(/^\s*(\w*)\s*(.*)$/);
let [match, op, arg] = line.match(/^\s*(\w*)\s*(.*)$/)
switch (op) {
case '':
break;
break
case 'SINCE':
let match;
if ((match = arg.match(/^(\d+) hours?$/i))) {
query.since = Date.now() - (+match[1] * 1000 * 60 * 60);
query.since = Date.now() - +match[1] * 1000 * 60 * 60
} else if ((match = arg.match(/^(\d+) days?$/i))) {
query.since = Date.now() - (+match[1] * 1000 * 60 * 60 * 24);
query.since = Date.now() - +match[1] * 1000 * 60 * 60 * 24
} else if ((match = arg.match(/^(\d+) weeks?$/i))) {
query.since = Date.now() - (+match[1] * 1000 * 60 * 60 * 24 * 7);
query.since = Date.now() - +match[1] * 1000 * 60 * 60 * 24 * 7
} else if ((match = arg.match(/^(sun|mon|tue|wed|thu|fri|sat)[a-z]*$/i))) {
const days = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
query.since = todayStart - ((((new Date()).getDay() + 7 - (days.indexOf(match[1].toLowerCase()))) % 7) * 1000 * 60 * 60 * 24);
const days = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']
query.since =
todayStart - ((new Date().getDay() + 7 - days.indexOf(match[1].toLowerCase())) % 7) * 1000 * 60 * 60 * 24
} else if (!isNaN(Date.parse(arg))) {
query.since = Date.parse(arg);
query.since = Date.parse(arg)
} else {
throw new Error(`don't know SINCE '${arg}' argument`);
throw new Error(`don't know SINCE '${arg}' argument`)
}
break;
break
case 'NEIGHBORHOOD':
if (arg.match(/^yes/i)) {
query.includeNeighbors = true;
query.includeNeighbors = true
} else if (arg.match(/^no/i)) {
query.includeNeighbors = false;
query.includeNeighbors = false
} else {
throw new Error(`don't know NEIGHBORHOOD '${arg}' argument`);
throw new Error(`don't know NEIGHBORHOOD '${arg}' argument`)
}
break;
break
case 'TWINS':
if ((match = arg.match(/^(\d+)/))) {
query.twins = +match[1];
query.twins = +match[1]
} else {
throw new Error(`don't know TWINS '${arg}' argument`);
throw new Error(`don't know TWINS '${arg}' argument`)
}
break;
break
case 'SORT':
if (arg.match(/^titles?$/i)) {
query.sortOrder = "title";
query.sortOrder = 'title'
} else if (arg.match(/^date/i)) {
query.sortOrder = "date";
query.sortOrder = 'date'
} else {
throw new Error(`don't know SORT '${arg}' argument`);
throw new Error(`don't know SORT '${arg}' argument`)
}
break;
break
case 'SEARCH':
query.searchTerm = arg;
query.searchResults = wiki.neighborhoodObject.search(query.searchTerm);
break;
query.searchTerm = arg
query.searchResults = wiki.neighborhoodObject.search(query.searchTerm)
break
case 'ROSTER':
query.includeNeighbors = false;
const items = $(".item:lt(" + $('.item').index($item) + ")");
const sources = items.filter(".roster-source");
sources.each((i, source) => {
const roster = source.getRoster();
for (const [key, value] of Object.entries(roster)) {
if (key.toLowerCase().indexOf(arg.toLowerCase()) >= 0) {
for (const site of value) {
query.rosterResults[site] = true;
query.includeNeighbors = false
$('.item:lt(' + $('.item').index($item) + ')')
.filter('.roster-source')
.each((i, source) => {
const roster = source.getRoster()
for (const [key, value] of Object.entries(roster)) {
if (key.toLowerCase().indexOf(arg.toLowerCase()) >= 0) {
for (const site of value) {
query.rosterResults[site] = true
}
}
}
}
});
})
if (!query.rosterResults[location.host]) {
query.mine = "no";
query.mine = 'no'
}
for (const site in query.rosterResults) {
wiki.neighborhoodObject.registerNeighbor(site);
wiki.neighborhoodObject.registerNeighbor(site)
}
break;
break
case 'MINE':
if (arg.match(/^yes/i)) {
query.mine = "yes";
query.mine = 'yes'
} else if (arg.match(/^no/i)) {
query.mine = "no";
query.mine = 'no'
} else if (arg.match(/^only/i)) {
query.mine = "only";
query.mine = 'only'
} else if (arg.match(/^exclude/i)) {
query.mine = "exclude";
query.mine = 'exclude'
} else {
throw new Error(`don't know MINE '${arg}' argument`);
throw new Error(`don't know MINE '${arg}' argument`)
}
break;
break
case 'CONVERSATION':
query.conversation = true;
break;
query.conversation = true
break
case 'NARRATIVE':
query.narrative = true;
break;
query.narrative = true
break
default:
throw new Error(`don't know '${op}' command`);
throw new Error(`don't know '${op}' command`)
}
} catch (err) {
query.errors++;
html = `<span style="background-color:#fdd;width:100%;" title="${err.message}">${html}</span>`;
query.errors++
html = `<span style="background-color:#fdd;width:100%;" title="${err.message}">${html}</span>`
}
query.listing.push(html);
query.listing.push(html)
}
};
}
const emit = ($item, item) => {};
const emit = ($item, item) => {}
const bind = ($item, item) => {
let tree = h('div');
let rootNode = createElement(tree);
$item.append(rootNode);
let omitted = 0
const unfilteredPages = new Map();
let pages = {};
let tree = h('div')
let rootNode = createElement(tree)
$item.append(rootNode)
const unfilteredPages = new Map()
let pages = {}
const display = (query, pages) => {
// ... (rest of the display function)
};
// Catch query errors
if (query.errors) {
const newTree = h('div', h('p', query.listing.join('<br>')))
const patches = diff(tree, newTree)
rootNode = patch(rootNode, patches)
return
}
// create content for the plugin's title
const header = []
const subHeadStyle = { style: { marginTop: '0px', marginBottom: '0px' } }
if (query.searchTerm) header.push(h('p', subHeadStyle, `searching for "${query.searchTerm}"`))
if (query.since) header.push(h('p', subHeadStyle, `since ${new Date(query.since).toDateString()}`))
if (query.twins > 0) header.push(h('p', subHeadStyle, `more than ${query.twins} twins`))
if (query.sortOrder === 'title') header.push(h('p', subHeadStyle, 'sorted by page title'))
if (query.includeNeighbors === false) header.push(h('p', subHeadStyle, 'excluding neighborhood'))
if (query.mine === 'no') header.push(h('p', subHeadStyle, 'excluding my pages'))
if (query.mine === 'only') header.push(h('p', subHeadStyle, 'including only pages I have a twin of'))
if (query.mine === 'exclude') header.push(h('p', subHeadStyle, "including only pages I don't have a twin of"))
const activityTitle = h(
'div',
{ style: { textAlign: 'center', fontSize: 'small', color: 'gray', marginTop: '14px' } },
header,
)
const now = Date.now()
const sections = [
{ date: now - 1000 * 60 * 60 * 24 * 365, period: 'Years' },
{ date: now - 1000 * 60 * 60 * 24 * 91, period: 'a Year' },
{ date: now - 1000 * 60 * 60 * 24 * 31, period: 'a Season' },
{ date: now - 1000 * 60 * 60 * 24 * 7, period: 'a Month' },
{ date: now - 1000 * 60 * 60 * 24, period: 'a Week' },
{ date: now - 1000 * 60 * 60, period: 'a Day' },
{ date: now - 1000 * 60, period: 'an Hour' },
{ date: now - 1000, period: 'a Minute' },
{ date: now, period: 'Seconds' },
]
let bigger = query.sortOrder === 'title' ? '' : now
const activityBody = []
omitted = 0
for (const sites of pages) {
if (
(sites.length >= query.twins || query.twins === 0) &&
(query.mine !== 'only' || sites.some(twin => twin.site === location.host)) &&
(query.mine !== 'exclude' || !sites.some(twin => twin.site === location.host))
) {
let smaller
if (query.sortOrder === 'title') {
smaller = sites[0].page.title.substr(0, 1).toUpperCase()
if (smaller !== bigger) {
activityBody.push(h('h3', { style: { width: '100%', textAlign: 'right' } }, smaller))
}
} else {
smaller = sites[0].page.date
for (const section of sections) {
if (section.date > smaller && section.date < bigger) {
activityBody.push(h('h3', `Within ${section.period}`))
break
}
}
}
bigger = smaller
const context = sites[0].site === location.host ? 'view' : `view => ${sites[0].site}`
const pageURL =
(sites.length === 1 && sites[0].site !== location.host) || !sites.some(i => i.site === location.host)
? wiki.site(sites[0].site).getURL(`/${sites[0].page.slug}.html`)
: `/${sites[0].page.slug}.html`
const pageLink = h(
'a.internal',
{
href: pageURL,
title: context,
key: sites[0].page.slug,
attributes: { 'data-page-name': sites[0].page.slug },
},
sites[0].page.title || sites[0].page.slug,
)
const links = []
if (query.narrative) {
let narrativeLink = sites[0].page.slug
for (const each of sites) {
narrativeLink += `@${each.site}`
}
links.push(
h(
'a',
{
href: `http://paul90.github.io/wiki-narrative-chart/#${narrativeLink}`,
title: 'Narrative Chart',
target: 'narrative',
},
'※',
),
)
}
if (query.conversation) {
let conversationLink = ''
for (const each of sites.slice().reverse()) {
conversationLink += `/${each.site}/${each.page.slug}`
}
links.push(
h(
'a.conversation',
{
href: conversationLink,
title: 'Conversation',
target: 'conversation',
},
'»',
),
)
}
const flags = []
sites.forEach((each, i) => {
if (i < 10) {
const joint = i > 0 && sites[i - 1].page.date === each.page.date ? '' : ' '
flags.unshift(joint)
flags.unshift(
h('img.remote', {
title: `${each.site}\n${wiki.util.formatElapsedTime(each.page.date)}`,
src: wiki.site(each.site).flag(),
attributes: { 'data-site': each.site, 'data-slug': each.page.slug },
}),
)
} else if (i === 10) {
flags.unshift(' ⋯ ')
}
})
activityBody.push(
h('div', { style: { clear: 'both' }, id: sites[0].page.slug }, [
h('div', { style: { float: 'left' } }, pageLink),
h('div', { style: { textAlign: 'right' } }, [
flags,
h('div', { style: { float: 'right', marginRight: '-1.1em' } }, links),
]),
]),
)
} else {
omitted++
}
}
if (omitted > 0) {
activityBody.push(h('p', h('i', `${omitted} more titles`)))
}
const newTree = h('div', [activityTitle, activityBody])
const patches = diff(tree, newTree)
rootNode = patch(rootNode, patches)
tree = newTree
$item.find('.conversation').on('click', e => {
e.stopPropagation()
e.preventDefault()
const this_page = e.shiftKey ? null : $item.parents('.page')
open_conversation(this_page, $(e.currentTarget).attr('href'))
})
}
const merge = (query, neighborhoodSites) => {
// ... (rest of the merge function)
};
for (const site of neighborhoodSites) {
const map = wiki.neighborhood[site]
if (map.sitemapRequestInflight || !map.sitemap) continue
if (
query.includeNeighbors ||
(!query.includeNeighbors && site === location.host) ||
site === location.host ||
query.rosterResults[site]
) {
if (!(query.mine === 'no' && site === location.host)) {
for (const each of map.sitemap) {
if (!unfilteredPages.has(each.slug)) {
unfilteredPages.set(each.slug, [])
}
const sites = unfilteredPages.get(each.slug)
const index = sites.findIndex(el => el.site == site)
if (index === -1) {
sites.push({ site: site, page: { slug: each.slug, title: each.title, date: each.date } })
} else {
sites[index] = { site: site, page: { slug: each.slug, title: each.title, date: each.date } }
}
}
}
}
}
pages = Object.fromEntries(unfilteredPages)
for (const [slug, sites] of Object.entries(pages)) {
sites.sort((a, b) => (b.page.date || 0) - (a.page.date || 0))
}
pages = Object.values(pages)
pages.sort((a, b) => {
if (query.sortOrder === 'title') {
return a[0].page.title.localeCompare(b[0].page.title, { sensitivity: 'accent' })
} else {
return (b[0].page.date || 0) - (a[0].page.date || 0)
}
})
const query = {};
setDefaults(query);
parse(query, item.text || '', $item, item);
omitted = 0
return pages.filter(e => {
let willInclude = true
if (query.since) {
if (e[0].page.date <= query.since || e[0].page.date === undefined) {
willInclude = false
omitted++
}
}
if (query.searchTerm && willInclude) {
if (!query.searchResults.finds.some(finds => finds.page === e[0].page)) {
willInclude = false
omitted++
}
}
return willInclude
})
}
let omitted = 0;
display(query, merge(query, Object.keys(wiki.neighborhood)));
const query = {}
setDefaults(query)
parse(query, item.text || '', $item)
omitted = 0
display(query, merge(query, Object.keys(wiki.neighborhood)))
$('body').on('new-neighbor-done', (e, site) => {
if (query.searchTerm) {
const searchResults = wiki.neighborhoodObject.search(query.searchTerm);
query.searchResults = wiki.neighborhoodObject.search(query.searchTerm)
}
omitted = 0;
display(query, merge(query, [site]));
});
omitted = 0
display(query, merge(query, [site]))
})
$item.on('dblclick', () => {
$('body').off('new-neighbor-done');
wiki.textEditor($item, item);
});
};
$('body').off('new-neighbor-done')
wiki.textEditor($item, item)
})
}
if (typeof window !== 'undefined') {
window.plugins.activity = { emit, bind };
window.plugins.activity = { emit, bind }
}
if (typeof module !== 'undefined') {
module.exports = { escape, parse };
}
export const activity = typeof window == 'undefined' ? { escape, parse } : undefined

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc