userscripts
userscripts copied to clipboard
Support for @connect ?
Sorry for not filling out the form, I just wanted to know if there were any plans to support @connect in metadata?
edit to add: the specific script I want to run is this one
@bheliot there are no plans to implement that key/val, but the lack of that metadata key shouldn't stop the usage of scripts. If my understanding is correct, that is a Tampermonkey specific key/val which allows domains for GM_xmlhttpRequest. This manager doesn't require that, so not having it shouldn't affect functionality.
Ah okay, thanks for letting me know! I did notice that the script works in TamperMonkey but not Usercripts, even when I add @inject-into content
@bheliot There are other reasons the script fails to run
1) It is using unsafeWindow which doesn't exist in this extension - see #252
To solve for this change line 34 to:
let wkItemInfo = typeof unsafeWindow !== "undefined" ? unsafeWindow.wkItemInfo : window.wkItemInfo;
2) There no error checking when a script that it requires calls querySelector, specifically line 80 of the script I just linked here:
_currentState.id = parseInt(document.querySelector(meta[name=subject_id]).content); <-- that is causing errors for me
I have no idea why that would work with Tampermonkey but not Userscripts, because document.querySelector(meta[name=subject_id]) doesn't even work in the browser console for me (see image below) - it returns null

Huh that’s so weird. :o But thanks so much for the info and the help!
Just had a chance to actually play around with the script some more, sorry for double-posting.
The most recent version of the required other script can be found here, and it doesn't seem to have that problematic line. However, even after updating the Stroke Order script with your suggested change for line 34 and updating the version of the required other script, it doesn't work.
Of course, this all may depend on being logged into WaniKani, so I understand if there's nothing further you can do to troubleshoot. Thanks for all your help so far!
@bheliot
it doesn't seem to have that problematic line.
Looking and testing the updated require script you linked - it still has the problematic line 84. I am trying to run the script on this page and getting the same error as I did with the old version (shown below).
This could be a different error than what you are seeing if you're on a different page, but this error is present on the page I linked. What errors do you see in the browser console?
I’m on my phone right now so I’ll have to take a more in-depth look later, but the script is meant to display the stroke order of a specific kanji on its individual page, e.g. one like this, does that make any difference?
... on its individual page, e.g. one like this ...
When I visit that page, the userscript, with my edits, appears to work

This is what I'm getting with your edited version of the script:

This is what I'm getting with your edited version of the script:
On what page url are you getting that error?
It seems to suggest that wkItemInfo is undefined when calling the on method. Are you sure you are using the edited version of the script?
That's on the same page as we've linked before. I've since removed a line of blank space so the error looks like this now:

I'm using a version of the script that changes line 34 to let wkItemInfo = typeof unsafeWindow !== "undefined" ? unsafeWindow.wkItemInfo : window.wkItemInfo; and updated the version of the required script to 1024045. Was there another change I needed to make?
Was there another change I needed to make?
Not for the error that you are showing in the screenshot. I am not sure why wkItemInfo is coming up as undefined. The userscript seems to function exactly as expected on my machine, here: https://www.wanikani.com/kanji/玉
I am going to paste the script I am using, just in case there is some other difference:
// ==UserScript==
// @name WaniKani Stroke Order
// @namespace japanese
// @version 1.1.12
// @description Shows a kanji's stroke order on its page and during lessons and reviews.
// @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
// @include http*://*wanikani.com/kanji/*
// @include http*://*wanikani.com/review/session
// @include http*://*wanikani.com/lesson/session
// @author Looki, maintained by Kumirei
// @grant GM_xmlhttpRequest
// @connect jisho.org
// @connect cloudfront.net
// @require https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js
// @require https://greasyfork.org/scripts/430565-wanikani-item-info-injector/code/WaniKani%20Item%20Info%20Injector.user.js?version=1024045
// @inject-into page
// ==/UserScript==
/*
* Thanks a lot to ...
* Wanikani Phonetic-Semantic Composition - Userscript
* by ruipgpinheiro (LordGravewish)
* ... for code showing me how to insert sections during kanji reviews.
* The code heavily borrows from that script!
* Also thanks to Halo for a loading bug fix!
*/
;(function () {
/* global Snap */
/*
* Helper Functions/Variables
*/
let wkItemInfo = typeof unsafeWindow !== "undefined" ? unsafeWindow.wkItemInfo : window.wkItemInfo;
/*
* Global Variables/Objects/Classes
*/
const JISHO = 'https://jisho.org'
const strokeOrderCss =
'.stroke_order_diagram--bounding_box {fill: none; stroke: #ddd; stroke-width: 2; stroke-linecap: square; stroke-linejoin: square;}' +
'.stroke_order_diagram--bounding_box {fill: none; stroke: #ddd; stroke-width: 2; stroke-linecap: square; stroke-linejoin: square;}' +
'.stroke_order_diagram--existing_path {fill: none; stroke: #aaa; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round;}' +
'.stroke_order_diagram--current_path {fill: none; stroke: #000; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round;}' +
'.stroke_order_diagram--path_start {fill: rgba(255,0,0,0.7); stroke: none;}' +
'.stroke_order_diagram--guide_line {fill: none; stroke: #ddd; stroke-width: 2; stroke-linecap: square; stroke-linejoin: square; stroke-dasharray: 5, 5;}'
init()
/*
* Main
*/
function init() {
wkItemInfo.on('lesson').forType('kanji').under('composition').append('Stroke Order', loadDiagram)
wkItemInfo
.on('lessonQuiz, review,itemPage')
.forType('kanji')
.under('composition')
.appendAtTop('Stroke Order', loadDiagram)
let style = document.createElement('style')
style.textContent = strokeOrderCss
document.head.appendChild(style)
}
function xmlHttpRequest(urlText) {
return new Promise((resolve, reject) =>
GM_xmlhttpRequest({
method: 'GET',
url: new URL(urlText),
onload: (xhr) => {
xhr.status === 200 ? resolve(xhr) : reject(xhr.responseText)
},
onerror: (xhr) => {
reject(xhr.responseText)
},
}),
)
}
/*
* Adds the diagram section element to the appropriate location
*/
async function loadDiagram(injectorState) {
let xhr = await xmlHttpRequest(JISHO + '/search/' + injectorState.characters + '%20%23kanji')
let strokeOrderSvg = xhr.responseText.match(/var url = '\/\/(.+)';/)
if (!strokeOrderSvg) return null
xhr = await xmlHttpRequest('https://' + strokeOrderSvg[1])
let namespace = 'http://www.w3.org/2000/svg'
let div = document.createElement('div')
let svg = document.createElementNS(namespace, 'svg')
svg.id = 'stroke_order'
div.style = 'width: 100%; overflow: auto hidden;'
new strokeOrderDiagram(
svg,
xhr.responseXML || new DOMParser().parseFromString(xhr.responseText, 'application/xml'),
)
div.append(svg)
return div
}
/*
* Lifted from jisho.org
*/
var strokeOrderDiagram = function (element, svgDocument) {
var s = Snap(element)
var diagramSize = 200
var coordRe = '(?:\\d+(?:\\.\\d+)?)'
var strokeRe = new RegExp('^[LMT]\\s*(' + coordRe + ')[,\\s](' + coordRe + ')', 'i')
var f = Snap(svgDocument.getElementsByTagName('svg')[0])
var allPaths = f.selectAll('path')
var drawnPaths = []
var canvasWidth = (allPaths.length * diagramSize) / 2
var canvasHeight = diagramSize / 2
var frameSize = diagramSize / 2
var frameOffsetMatrix = new Snap.Matrix()
frameOffsetMatrix.translate(-frameSize / 16 + 2, -frameSize / 16 + 2)
// Set drawing area
s.node.style.width = canvasWidth + 'px'
s.node.style.height = canvasHeight + 'px'
s.node.setAttribute('viewBox', '0 0 ' + canvasWidth + ' ' + canvasHeight)
// Draw global guides
var boundingBoxTop = s.line(1, 1, canvasWidth - 1, 1)
var boundingBoxLeft = s.line(1, 1, 1, canvasHeight - 1)
var boundingBoxBottom = s.line(1, canvasHeight - 1, canvasWidth - 1, canvasHeight - 1)
var horizontalGuide = s.line(0, canvasHeight / 2, canvasWidth, canvasHeight / 2)
boundingBoxTop.attr({ class: 'stroke_order_diagram--bounding_box' })
boundingBoxLeft.attr({ class: 'stroke_order_diagram--bounding_box' })
boundingBoxBottom.attr({ class: 'stroke_order_diagram--bounding_box' })
horizontalGuide.attr({ class: 'stroke_order_diagram--guide_line' })
// Draw strokes
var pathNumber = 1
allPaths.forEach(function (currentPath) {
var moveFrameMatrix = new Snap.Matrix()
moveFrameMatrix.translate(frameSize * (pathNumber - 1) - 4, -4)
// Draw frame guides
var verticalGuide = s.line(
frameSize * pathNumber - frameSize / 2,
1,
frameSize * pathNumber - frameSize / 2,
canvasHeight - 1,
)
var frameBoxRight = s.line(frameSize * pathNumber - 1, 1, frameSize * pathNumber - 1, canvasHeight - 1)
verticalGuide.attr({ class: 'stroke_order_diagram--guide_line' })
frameBoxRight.attr({ class: 'stroke_order_diagram--bounding_box' })
// Draw previous strokes
drawnPaths.forEach(function (existingPath) {
var localPath = existingPath.clone()
localPath.transform(moveFrameMatrix)
localPath.attr({ class: 'stroke_order_diagram--existing_path' })
s.append(localPath)
})
// Draw current stroke
currentPath.transform(frameOffsetMatrix)
currentPath.transform(moveFrameMatrix)
currentPath.attr({ class: 'stroke_order_diagram--current_path' })
s.append(currentPath)
// Draw stroke start point
var match = strokeRe.exec(currentPath.node.getAttribute('d'))
var pathStartX = match[1]
var pathStartY = match[2]
var strokeStart = s.circle(pathStartX, pathStartY, 4)
strokeStart.attr({ class: 'stroke_order_diagram--path_start' })
strokeStart.transform(moveFrameMatrix)
pathNumber++
drawnPaths.push(currentPath.clone())
})
}
})()
Still not working on either iOS or Mac, even with that exact code. Sorry I can't be more helpful in figuring this out.
It's funny though, running it on TamperMonkey gives the same errors in the console but the stroke diagram still shows up:

This is quite strange, since I get no errors.
running it on TamperMonkey gives the same errors in the console
Just to make 100% sure, are you testing the script changes with this extension with Tampermonkey disabled? And when testing Tampermonkey, disabling Userscripts (this extension)?
The reason I ask is because I see the stroke order on the page, and you mentioned Tampermonkey, so it seems like both extensions are running at the same time - which wouldn't be ideal for testing.
If you are already testing with Tampermonkey disabled, then I am running out of ideas
I can confirm I’m not running both extensions at the same time.
Considering everything we have gone through here, I am quite confused why this is happening on your machine and not mine...
Sorry for all the trouble 😅
I am glad to help I just wish I could more help to you.