QR doesn't need its own settings section
This commit is contained in:
commit
81d65cc3ca
13
CHANGELOG.md
13
CHANGELOG.md
@ -1,3 +1,16 @@
|
|||||||
|
seaweedchan:
|
||||||
|
- Fix Gist links if no username is specificed
|
||||||
|
|
||||||
|
MayhemYDG:
|
||||||
|
- **New feature**: `Quick Reply Personas`
|
||||||
|
- Add custom auto-completion for the name, e-mail and subject inputs.
|
||||||
|
- Always use a specific persona.
|
||||||
|
- Per-board configuration.
|
||||||
|
- Access it in the `QR` tab of the Settings window.
|
||||||
|
|
||||||
|
zixaphir:
|
||||||
|
- Add Gist link titles
|
||||||
|
|
||||||
### 1.1.5 - 2013-04-30
|
### 1.1.5 - 2013-04-30
|
||||||
seaweedchan:
|
seaweedchan:
|
||||||
- Fix various embedding issues
|
- Fix various embedding issues
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* 4chan X - Version 1.1.5 - 2013-04-30
|
* 4chan X - Version 1.1.5 - 2013-05-01
|
||||||
*
|
*
|
||||||
* Licensed under the MIT license.
|
* Licensed under the MIT license.
|
||||||
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
|
* https://github.com/seaweedchan/4chan-x/blob/master/LICENSE
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
1. Precise steps to reproduce the problem, with the expected and actual results.
|
1. Precise steps to reproduce the problem, with the expected and actual results.
|
||||||
2. Console errors, if any.
|
2. Console errors, if any.
|
||||||
3. Browser version.
|
3. Browser version.
|
||||||
4. Your exported settings.
|
4. Your exported settings. If your settings contains sensitive information (e.g. personas), edit the text file manually.
|
||||||
|
|
||||||
Open your console with:
|
Open your console with:
|
||||||
- `Ctrl + Shift + J` on Chrome.
|
- `Ctrl + Shift + J` on Chrome.
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -19,12 +19,7 @@ ThreadHiding =
|
|||||||
hiddenThreads = ThreadHiding.db.get
|
hiddenThreads = ThreadHiding.db.get
|
||||||
boardID: g.BOARD.ID
|
boardID: g.BOARD.ID
|
||||||
defaultValue: {}
|
defaultValue: {}
|
||||||
# XXX tmp fix
|
hiddenThreadsOnCatalog = JSON.parse(localStorage.getItem "4chan-hide-t-#{g.BOARD}") or {}
|
||||||
try
|
|
||||||
hiddenThreadsOnCatalog = JSON.parse(localStorage.getItem "4chan-hide-t-#{g.BOARD}") or {}
|
|
||||||
catch e
|
|
||||||
localStorage.setItem "4chan-hide-t-#{g.BOARD}", JSON.stringify {}
|
|
||||||
return ThreadHiding.syncCatalog()
|
|
||||||
|
|
||||||
# Add threads that were hidden in the catalog.
|
# Add threads that were hidden in the catalog.
|
||||||
for threadID of hiddenThreadsOnCatalog
|
for threadID of hiddenThreadsOnCatalog
|
||||||
@ -130,10 +125,10 @@ ThreadHiding =
|
|||||||
return if thread.isHidden
|
return if thread.isHidden
|
||||||
{OP} = thread
|
{OP} = thread
|
||||||
threadRoot = OP.nodes.root.parentNode
|
threadRoot = OP.nodes.root.parentNode
|
||||||
threadRoot.hidden = thread.isHidden = true
|
thread.isHidden = true
|
||||||
|
|
||||||
unless makeStub
|
unless makeStub
|
||||||
threadRoot.nextElementSibling.hidden = true # <hr>
|
threadRoot.hidden = threadRoot.nextElementSibling.hidden = true # <hr>
|
||||||
return
|
return
|
||||||
|
|
||||||
numReplies = 0
|
numReplies = 0
|
||||||
@ -154,7 +149,7 @@ ThreadHiding =
|
|||||||
$.add thread.stub, a
|
$.add thread.stub, a
|
||||||
if Conf['Menu']
|
if Conf['Menu']
|
||||||
$.add thread.stub, [$.tn(' '), Menu.makeButton OP]
|
$.add thread.stub, [$.tn(' '), Menu.makeButton OP]
|
||||||
$.before threadRoot, thread.stub
|
$.prepend threadRoot, thread.stub
|
||||||
|
|
||||||
show: (thread) ->
|
show: (thread) ->
|
||||||
if thread.stub
|
if thread.stub
|
||||||
@ -162,4 +157,4 @@ ThreadHiding =
|
|||||||
delete thread.stub
|
delete thread.stub
|
||||||
threadRoot = thread.OP.nodes.root.parentNode
|
threadRoot = thread.OP.nodes.root.parentNode
|
||||||
threadRoot.nextElementSibling.hidden =
|
threadRoot.nextElementSibling.hidden =
|
||||||
threadRoot.hidden = thread.isHidden = false
|
threadRoot.hidden = thread.isHidden = false
|
||||||
|
|||||||
@ -425,6 +425,11 @@ http://iqdb.org/?url=%TURL
|
|||||||
|
|
||||||
boardnav: '[ toggle-all ] [current-title]'
|
boardnav: '[ toggle-all ] [current-title]'
|
||||||
|
|
||||||
|
QR:
|
||||||
|
'QR.personas': [
|
||||||
|
'#email:"sage";boards:jp;always'
|
||||||
|
].join '\n'
|
||||||
|
|
||||||
time: '%m/%d/%y(%a)%H:%M:%S'
|
time: '%m/%d/%y(%a)%H:%M:%S'
|
||||||
|
|
||||||
backlink: '>>%id'
|
backlink: '>>%id'
|
||||||
|
|||||||
@ -8,6 +8,8 @@ Get =
|
|||||||
if excerpt.length > 70
|
if excerpt.length > 70
|
||||||
excerpt = "#{excerpt[...67]}..."
|
excerpt = "#{excerpt[...67]}..."
|
||||||
"/#{thread.board}/ - #{excerpt}"
|
"/#{thread.board}/ - #{excerpt}"
|
||||||
|
threadFromRoot: (root) ->
|
||||||
|
g.threads["#{g.BOARD}.#{root.id[1..]}"]
|
||||||
postFromRoot: (root) ->
|
postFromRoot: (root) ->
|
||||||
link = $ 'a[title="Highlight this post"]', root
|
link = $ 'a[title="Highlight this post"]', root
|
||||||
boardID = link.pathname.split('/')[1]
|
boardID = link.pathname.split('/')[1]
|
||||||
@ -226,4 +228,4 @@ Get =
|
|||||||
post = new Post Build.post(o, true), thread, board,
|
post = new Post Build.post(o, true), thread, board,
|
||||||
isArchived: true
|
isArchived: true
|
||||||
Main.callbackNodes Post, [post]
|
Main.callbackNodes Post, [post]
|
||||||
Get.insert post, root, context
|
Get.insert post, root, context
|
||||||
|
|||||||
@ -310,10 +310,10 @@ Settings =
|
|||||||
section.innerHTML = """
|
section.innerHTML = """
|
||||||
<%= grunt.file.read('src/General/html/Settings/Sauce.html').replace(/>\s+</g, '><').trim() %>
|
<%= grunt.file.read('src/General/html/Settings/Sauce.html').replace(/>\s+</g, '><').trim() %>
|
||||||
"""
|
"""
|
||||||
sauce = $ 'textarea', section
|
ta = $ 'textarea', section
|
||||||
$.get 'sauces', Conf['sauces'], (item) ->
|
$.get 'sauces', Conf['sauces'], (item) ->
|
||||||
sauce.value = item['sauces']
|
ta.value = item['sauces']
|
||||||
$.on sauce, 'change', $.cb.value
|
$.on ta, 'change', $.cb.value
|
||||||
|
|
||||||
advanced: (section) ->
|
advanced: (section) ->
|
||||||
section.innerHTML = """
|
section.innerHTML = """
|
||||||
@ -331,6 +331,12 @@ Settings =
|
|||||||
'input'
|
'input'
|
||||||
$.on input, event, $.cb.value
|
$.on input, event, $.cb.value
|
||||||
|
|
||||||
|
# Quick Reply Personas
|
||||||
|
ta = $ '.personafield', section
|
||||||
|
$.get 'QR.personas', Conf['QR.personas'], (item) ->
|
||||||
|
ta.value = item['QR.personas']
|
||||||
|
$.on ta, 'change', $.cb.value
|
||||||
|
|
||||||
# Archiver
|
# Archiver
|
||||||
archiver = $ 'select[name=archiver]', section
|
archiver = $ 'select[name=archiver]', section
|
||||||
toSelect = Redirect.select g.BOARD.ID
|
toSelect = Redirect.select g.BOARD.ID
|
||||||
|
|||||||
@ -321,8 +321,13 @@ a[href="javascript:;"] {
|
|||||||
.section-advanced ul {
|
.section-advanced ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
}
|
||||||
|
.section-sauce ul {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
.section-advanced ul {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
.section-sauce li,
|
.section-sauce li,
|
||||||
.section-advanced li {
|
.section-advanced li {
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
@ -570,9 +575,7 @@ a.hide-announcement {
|
|||||||
float: left;
|
float: left;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
.stub ~ .sideArrows,
|
.stub ~ * {
|
||||||
.stub ~ .hide-reply-button,
|
|
||||||
.stub ~ .post {
|
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
.stub input {
|
.stub input {
|
||||||
@ -927,4 +930,4 @@ a:only-of-type > .remove {
|
|||||||
.linkify.gist {
|
.linkify.gist {
|
||||||
background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/gist.png", {encoding: "base64"}) %>') center left no-repeat!important;
|
background: transparent url('data:image/png;base64,<%= grunt.file.read("src/General/img/links/gist.png", {encoding: "base64"}) %>') center left no-repeat!important;
|
||||||
padding-left: 18px;
|
padding-left: 18px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,12 +11,12 @@
|
|||||||
<form>
|
<form>
|
||||||
<div class=persona>
|
<div class=persona>
|
||||||
<input id=dump-button type=button title='Dump list' value=+ tabindex=0>
|
<input id=dump-button type=button title='Dump list' value=+ tabindex=0>
|
||||||
<input name=name data-name=name title=Name placeholder=Name class=field size=1 tabindex=10>
|
<input name=name data-name=name list="list-name" placeholder=Name class=field size=1 tabindex=10>
|
||||||
<input name=email data-name=email title=E-mail placeholder=E-mail class=field size=1 tabindex=20>
|
<input name=email data-name=email list="list-email" placeholder=E-mail class=field size=1 tabindex=20>
|
||||||
<input name=sub data-name=sub title=Subject placeholder=Subject class=field size=1 tabindex=30>
|
<input name=sub data-name=sub list="list-sub" placeholder=Subject class=field size=1 tabindex=30>
|
||||||
</div>
|
</div>
|
||||||
<div class=textarea>
|
<div class=textarea>
|
||||||
<textarea data-name=com title=Comment placeholder=Comment class=field tabindex=40></textarea>
|
<textarea data-name=com placeholder=Comment class=field tabindex=40></textarea>
|
||||||
<span id=char-count></span>
|
<span id=char-count></span>
|
||||||
</div>
|
</div>
|
||||||
<div id=dump-list-container>
|
<div id=dump-list-container>
|
||||||
@ -35,4 +35,7 @@
|
|||||||
<label id=qr-spoiler-label>
|
<label id=qr-spoiler-label>
|
||||||
<input type=checkbox id=qr-file-spoiler title='Spoiler image' tabindex=90>Spoiler?
|
<input type=checkbox id=qr-file-spoiler title='Spoiler image' tabindex=90>Spoiler?
|
||||||
</label>
|
</label>
|
||||||
</form>
|
</form>
|
||||||
|
<datalist id="list-name"></datalist>
|
||||||
|
<datalist id="list-email"></datalist>
|
||||||
|
<datalist id="list-sub"></datalist>
|
||||||
@ -52,6 +52,23 @@
|
|||||||
<div>Resolution: <code>%r</code> (Displays 'PDF' for PDF files)</div>
|
<div>Resolution: <code>%r</code> (Displays 'PDF' for PDF files)</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Quick Reply Personas <span class="warning" #{if Conf['Quick Reply'] then 'hidden' else ''}>is disabled.</span></legend>
|
||||||
|
<textarea class=personafield name="QR.personas" class="field" spellcheck="false"></textarea>
|
||||||
|
<p>
|
||||||
|
One item per line.<br>
|
||||||
|
Items will be added in the relevant input's auto-completion list.<br>
|
||||||
|
Password items will always be used, since there is no password input.<br>
|
||||||
|
Lines starting with a <code>#</code> will be ignored.
|
||||||
|
</p>
|
||||||
|
<ul>You can use these settings with each item, separate them with semicolons:
|
||||||
|
<li>Possible items are: <code>name</code>, <code>email</code>, <code>subject</code> and <code>password</code>.</li>
|
||||||
|
<li>Wrap values of items with quotes, like this: <code>email:"sage"</code>.</li>
|
||||||
|
<li>Force values as defaults with the <code>always</code> keyword, for example: <code>email:"sage";always</code>.</li>
|
||||||
|
<li>Select specific boards for an item, separated with commas, for example: <code>email:"sage";boards:jp;always</code>.</li>
|
||||||
|
</ul>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Unread Favicon <span class=warning #{if Conf['Unread Favicon'] then 'hidden' else ''}>is disabled.</span></legend>
|
<legend>Unread Favicon <span class=warning #{if Conf['Unread Favicon'] then 'hidden' else ''}>is disabled.</span></legend>
|
||||||
<select name=favicon>
|
<select name=favicon>
|
||||||
|
|||||||
@ -46,18 +46,12 @@ DeleteLink =
|
|||||||
$.off @, 'click', DeleteLink.delete
|
$.off @, 'click', DeleteLink.delete
|
||||||
@textContent = "Deleting #{@textContent}..."
|
@textContent = "Deleting #{@textContent}..."
|
||||||
|
|
||||||
pwd =
|
|
||||||
if m = d.cookie.match /4chan_pass=([^;]+)/
|
|
||||||
decodeURIComponent m[1]
|
|
||||||
else
|
|
||||||
$.id('delPassword').value
|
|
||||||
|
|
||||||
fileOnly = $.hasClass @, 'delete-file'
|
fileOnly = $.hasClass @, 'delete-file'
|
||||||
|
|
||||||
form =
|
form =
|
||||||
mode: 'usrdel'
|
mode: 'usrdel'
|
||||||
onlyimgdel: fileOnly
|
onlyimgdel: fileOnly
|
||||||
pwd: pwd
|
pwd: QR.persona.getPassword()
|
||||||
form[post.ID] = 'delete'
|
form[post.ID] = 'delete'
|
||||||
|
|
||||||
link = @
|
link = @
|
||||||
@ -106,4 +100,4 @@ DeleteLink =
|
|||||||
delete DeleteLink.cooldown.counting
|
delete DeleteLink.cooldown.counting
|
||||||
return
|
return
|
||||||
setTimeout DeleteLink.cooldown.count, 1000, post, seconds - 1, length, node
|
setTimeout DeleteLink.cooldown.count, 1000, post, seconds - 1, length, node
|
||||||
node.textContent = "Delete (#{seconds})"
|
node.textContent = "Delete (#{seconds})"
|
||||||
|
|||||||
@ -44,7 +44,9 @@ Nav =
|
|||||||
else
|
else
|
||||||
headRect = Header.bar.getBoundingClientRect()
|
headRect = Header.bar.getBoundingClientRect()
|
||||||
topMargin = headRect.top + headRect.height
|
topMargin = headRect.top + headRect.height
|
||||||
threads = $$ '.thread:not([hidden])'
|
threads = $$('.thread').filter (thread) ->
|
||||||
|
thread = Get.threadFromRoot thread
|
||||||
|
!(thread.isHidden and !thread.stub)
|
||||||
for thread, i in threads
|
for thread, i in threads
|
||||||
rect = thread.getBoundingClientRect()
|
rect = thread.getBoundingClientRect()
|
||||||
if rect.bottom > topMargin # not scrolled past
|
if rect.bottom > topMargin # not scrolled past
|
||||||
@ -62,4 +64,4 @@ Nav =
|
|||||||
i += delta
|
i += delta
|
||||||
|
|
||||||
top = threads[i]?.getBoundingClientRect().top - topMargin
|
top = threads[i]?.getBoundingClientRect().top - topMargin
|
||||||
window.scrollBy 0, top
|
window.scrollBy 0, top
|
||||||
|
|||||||
@ -157,6 +157,72 @@ QR =
|
|||||||
value
|
value
|
||||||
status.disabled = disabled or false
|
status.disabled = disabled or false
|
||||||
|
|
||||||
|
persona:
|
||||||
|
name: []
|
||||||
|
email: []
|
||||||
|
sub: []
|
||||||
|
pwd: ''
|
||||||
|
always: {}
|
||||||
|
init: ->
|
||||||
|
QR.persona.getPassword()
|
||||||
|
$.get 'QR.personas', Conf['QR.personas'], ({'QR.personas': personas}) ->
|
||||||
|
for item in personas.split '\n'
|
||||||
|
QR.persona.parseItem item.trim()
|
||||||
|
for type in ['name', 'email', 'sub']
|
||||||
|
QR.persona.loadPersonas type
|
||||||
|
return
|
||||||
|
parseItem: (item) ->
|
||||||
|
return if item[0] is '#'
|
||||||
|
return unless match = item.match /(name|email|subject|password):"(.*)"/i
|
||||||
|
[match, type, val] = match
|
||||||
|
|
||||||
|
# Don't mix up item settings with val.
|
||||||
|
item = item.replace match, ''
|
||||||
|
|
||||||
|
boards = item.match(/boards:([^;]+)/i)?[1].toLowerCase() or 'global'
|
||||||
|
if boards isnt 'global' and not (g.BOARD.ID in boards.split ',')
|
||||||
|
return
|
||||||
|
|
||||||
|
if type is 'password'
|
||||||
|
QR.persona.pwd = val
|
||||||
|
return
|
||||||
|
|
||||||
|
type = 'sub' if type is 'subject'
|
||||||
|
|
||||||
|
if /always/i.test item
|
||||||
|
QR.persona.always[type] = val
|
||||||
|
|
||||||
|
unless val in QR.persona[type]
|
||||||
|
QR.persona[type].push val
|
||||||
|
loadPersonas: (type) ->
|
||||||
|
list = $ "#list-#{type}", QR.nodes.el
|
||||||
|
for val in QR.persona[type]
|
||||||
|
$.add list, $.el 'option',
|
||||||
|
textContent: val
|
||||||
|
return
|
||||||
|
getPassword: ->
|
||||||
|
unless QR.persona.pwd
|
||||||
|
QR.persona.pwd = if m = d.cookie.match /4chan_pass=([^;]+)/
|
||||||
|
decodeURIComponent m[1]
|
||||||
|
else if input = $.id 'postPassword'
|
||||||
|
input.value
|
||||||
|
else
|
||||||
|
# If we're in a closed thread, #postPassword isn't available.
|
||||||
|
# And since #delPassword.value is only filled on window.onload
|
||||||
|
# we'd rather use #postPassword when we can.
|
||||||
|
$.id('delPassword').value
|
||||||
|
return QR.persona.pwd
|
||||||
|
get: (cb) ->
|
||||||
|
$.get 'QR.persona', {}, ({'QR.persona': persona}) ->
|
||||||
|
cb persona
|
||||||
|
set: (post) ->
|
||||||
|
$.get 'QR.persona', {}, ({'QR.persona': persona}) ->
|
||||||
|
persona =
|
||||||
|
name: post.name
|
||||||
|
email: if /^sage$/.test post.email then persona.email else post.email
|
||||||
|
sub: if Conf['Remember Subject'] then post.sub else undefined
|
||||||
|
$.set 'QR.persona', persona
|
||||||
|
|
||||||
cooldown:
|
cooldown:
|
||||||
init: ->
|
init: ->
|
||||||
return unless Conf['Cooldown']
|
return unless Conf['Cooldown']
|
||||||
@ -430,18 +496,27 @@ QR =
|
|||||||
prev.spoiler
|
prev.spoiler
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
$.get 'QR.persona', {}, (item) =>
|
QR.persona.get (persona) =>
|
||||||
persona = item['QR.persona']
|
@name = if 'name' of QR.persona.always
|
||||||
@name = if prev
|
QR.persona.always.name
|
||||||
|
else if prev
|
||||||
prev.name
|
prev.name
|
||||||
else
|
else
|
||||||
persona.name
|
persona.name
|
||||||
@email = if prev and !/^sage$/.test prev.email
|
|
||||||
|
@email = if 'email' of QR.persona.always
|
||||||
|
QR.persona.always.email
|
||||||
|
else if prev and !/^sage$/.test prev.email
|
||||||
prev.email
|
prev.email
|
||||||
else
|
else
|
||||||
persona.email
|
persona.email
|
||||||
if Conf['Remember Subject']
|
|
||||||
@sub = if prev then prev.sub else persona.sub
|
@sub = if 'sub' of QR.persona.always
|
||||||
|
QR.persona.always.sub
|
||||||
|
else if Conf['Remember Subject']
|
||||||
|
if prev then prev.sub else persona.sub
|
||||||
|
else
|
||||||
|
''
|
||||||
@load() if QR.selected is @ # load persona
|
@load() if QR.selected is @ # load persona
|
||||||
@select() if select
|
@select() if select
|
||||||
@unlock()
|
@unlock()
|
||||||
@ -847,8 +922,8 @@ QR =
|
|||||||
$.set 'QR Size', @style.cssText
|
$.set 'QR Size', @style.cssText
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
|
QR.persona.init()
|
||||||
new QR.post true
|
new QR.post true
|
||||||
|
|
||||||
QR.status()
|
QR.status()
|
||||||
QR.cooldown.init()
|
QR.cooldown.init()
|
||||||
QR.captcha.init()
|
QR.captcha.init()
|
||||||
@ -928,7 +1003,7 @@ QR =
|
|||||||
spoiler: post.spoiler
|
spoiler: post.spoiler
|
||||||
textonly: textOnly
|
textonly: textOnly
|
||||||
mode: 'regist'
|
mode: 'regist'
|
||||||
pwd: if m = d.cookie.match(/4chan_pass=([^;]+)/) then decodeURIComponent m[1] else $.id('postPassword').value
|
pwd: QR.persona.pwd
|
||||||
recaptcha_challenge_field: challenge
|
recaptcha_challenge_field: challenge
|
||||||
recaptcha_response_field: response
|
recaptcha_response_field: response
|
||||||
|
|
||||||
@ -1031,13 +1106,7 @@ QR =
|
|||||||
QR.cleanNotifications()
|
QR.cleanNotifications()
|
||||||
QR.notifications.push new Notification 'success', h1.textContent, 5
|
QR.notifications.push new Notification 'success', h1.textContent, 5
|
||||||
|
|
||||||
$.get 'QR.persona', {}, (item) ->
|
QR.persona.set post
|
||||||
persona = item['QR.persona']
|
|
||||||
persona =
|
|
||||||
name: post.name
|
|
||||||
email: if /^sage$/.test post.email then persona.email else post.email
|
|
||||||
sub: if Conf['Remember Subject'] then post.sub else null
|
|
||||||
$.set 'QR.persona', persona
|
|
||||||
|
|
||||||
[_, threadID, postID] = h1.nextSibling.textContent.match /thread:(\d+),no:(\d+)/
|
[_, threadID, postID] = h1.nextSibling.textContent.match /thread:(\d+),no:(\d+)/
|
||||||
postID = +postID
|
postID = +postID
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user