Skip to content
Snippets Groups Projects
Commit 037cb5c2 authored by George Nachman's avatar George Nachman
Browse files

Update OSC 8 to require parameters prior to the URL. A difference in...

Update OSC 8 to require parameters prior to the URL. A difference in parameters prevents hover-underlining together.

The new syntax is:

OSC 8 ; params ; url ST

params are (for now) space delimited ASCII and may not contain a ;.
url is a URL. I'm more accepting that I have to be and will take UTF-8 encoded URLs that aren't properly percent-escaped.
parent 955979aa
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -65,6 +65,7 @@
 
// If nonnil then we're currently in a hypertext link.
@property(nonatomic, readonly) NSURL *url;
@property(nonatomic, readonly) NSString *urlParams;
 
- (void)setStateFromDictionary:(NSDictionary *)dict;
 
Loading
Loading
Loading
Loading
@@ -67,6 +67,7 @@ NSString *const kTerminalStateDisableSMCUPAndRMCUPKey = @"Disable Alt Screen";
NSString *const kTerminalStateInCommandKey = @"In Command";
NSString *const kTerminalStateUnicodeVersionStack = @"Unicode Version Stack";
NSString *const kTerminalStateURL = @"URL";
NSString *const kTerminalStateURLParams = @"URL Params";
 
@interface VT100Terminal ()
@property(nonatomic, assign) BOOL reverseVideo;
Loading
Loading
@@ -79,6 +80,7 @@ NSString *const kTerminalStateURL = @"URL";
@property(nonatomic, assign) BOOL columnMode; // YES=132 Column, NO=80 Column
@property(nonatomic, assign) BOOL disableSmcupRmcup;
@property(nonatomic, retain) NSURL *url;
@property(nonatomic, retain) NSString *urlParams;
 
// A write-only property, at the moment. TODO: What should this do?
@property(nonatomic, assign) BOOL strictAnsiMode;
Loading
Loading
@@ -239,6 +241,7 @@ static const int kMaxScreenRows = 4096;
[_answerBackString release];
[_unicodeVersionStack release];
[_url release];
[_urlParams release];
 
[super dealloc];
}
Loading
Loading
@@ -1172,6 +1175,7 @@ static const int kMaxScreenRows = 4096;
graphicRendition_.under = NO;
 
self.url = nil;
self.urlParams = nil;
_currentURLCode = 0;
 
// (Not supported: Reset INVISIBLE)
Loading
Loading
@@ -2107,14 +2111,22 @@ static const int kMaxScreenRows = 4096;
}
 
- (void)executeLink:(VT100Token *)token {
if (token.string.length > 2083) {
NSInteger index = [token.string rangeOfString:@";"].location;
if (index == NSNotFound) {
return;
}
self.url = token.string.length ? [NSURL URLWithUserSuppliedString:token.string] : nil;
NSString *params = [token.string substringToIndex:index];
NSString *urlString = [token.string substringFromIndex:index + 1];
if (urlString.length > 2083) {
return;
}
self.url = urlString.length ? [NSURL URLWithUserSuppliedString:urlString] : nil;
if (self.url == nil) {
_currentURLCode = 0;
self.urlParams = nil;
} else {
_currentURLCode = [[iTermURLStore sharedInstance] codeForURL:self.url];
self.urlParams = params;
_currentURLCode = [[iTermURLStore sharedInstance] codeForURL:self.url withParams:params];
}
}
 
Loading
Loading
@@ -2599,7 +2611,8 @@ static const int kMaxScreenRows = 4096;
kTerminalStateDisableSMCUPAndRMCUPKey: @(self.disableSmcupRmcup),
kTerminalStateInCommandKey: @(inCommand_),
kTerminalStateUnicodeVersionStack: _unicodeVersionStack,
kTerminalStateURL: self.url ?: [NSNull null] };
kTerminalStateURL: self.url ?: [NSNull null],
kTerminalStateURLParams: self.urlParams ?: [NSNull null] };
return [dict dictionaryByRemovingNullValues];
}
 
Loading
Loading
@@ -2633,6 +2646,7 @@ static const int kMaxScreenRows = 4096;
self.keypadMode = [dict[kTerminalStateKeypadModeKey] boolValue];
self.allowKeypadMode = [dict[kTerminalStateAllowKeypadModeKey] boolValue];
self.url = [dict[kTerminalStateURL] nilIfNull];
self.urlParams = [dict[kTerminalStateURLParams] nilIfNull];
 
self.bracketedPasteMode = [dict[kTerminalStateBracketedPasteModeKey] boolValue];
ansiMode_ = [dict[kTerminalStateAnsiModeKey] boolValue];
Loading
Loading
Loading
Loading
@@ -180,11 +180,11 @@ typedef NS_ENUM(NSUInteger, iTermTextExtractorTrimTrailingWhitespace) {
// all punctuation except -.
- (NSString *)fastWordAt:(VT100GridCoord)location;
 
- (NSURL *)urlOfHypertextLinkAt:(VT100GridCoord)coord;
- (NSURL *)urlOfHypertextLinkAt:(VT100GridCoord)coord urlId:(out NSString **)urlId;
 
// Searches before and after `coord` until a coordinate is found that does not pass the test.
// Returns the resulting range.
- (VT100GridWindowedRange)rangeOfCoordinatesAround:(VT100GridCoord)coord
maximumDistance:(int)maximumDistance
passingTest:(BOOL(^)(screen_char_t *c))block;
passingTest:(BOOL(^)(screen_char_t *c, VT100GridCoord coord))block;
@end
Loading
Loading
@@ -192,20 +192,21 @@ const NSInteger kUnlimitedMaximumWordLength = NSIntegerMax;
}
}
 
- (NSURL *)urlOfHypertextLinkAt:(VT100GridCoord)coord {
- (NSURL *)urlOfHypertextLinkAt:(VT100GridCoord)coord urlId:(out NSString **)urlId {
screen_char_t c = [self characterAt:coord];
*urlId = [[iTermURLStore sharedInstance] paramWithKey:@"id" forCode:c.urlCode];
return [[iTermURLStore sharedInstance] urlForCode:c.urlCode];
}
 
- (VT100GridWindowedRange)rangeOfCoordinatesAround:(VT100GridCoord)origin
maximumDistance:(int)maximumDistance
passingTest:(BOOL(^)(screen_char_t *c))block {
passingTest:(BOOL(^)(screen_char_t *c, VT100GridCoord coord))block {
VT100GridCoord coord = origin;
VT100GridCoord previousCoord = origin;
coord = [self predecessorOfCoord:coord];
screen_char_t c = [self characterAt:coord];
int distanceLeft = maximumDistance;
while (distanceLeft > 0 && !VT100GridCoordEquals(coord, previousCoord) && block(&c)) {
while (distanceLeft > 0 && !VT100GridCoordEquals(coord, previousCoord) && block(&c, coord)) {
previousCoord = coord;
coord = [self predecessorOfCoord:coord];
c = [self characterAt:coord];
Loading
Loading
@@ -221,7 +222,7 @@ const NSInteger kUnlimitedMaximumWordLength = NSIntegerMax;
coord = [self successorOfCoord:coord];
c = [self characterAt:coord];
distanceLeft = maximumDistance;
while (distanceLeft > 0 && !VT100GridCoordEquals(coord, previousCoord) && block(&c)) {
while (distanceLeft > 0 && !VT100GridCoordEquals(coord, previousCoord) && block(&c, coord)) {
previousCoord = coord;
coord = [self successorOfCoord:coord];
c = [self characterAt:coord];
Loading
Loading
Loading
Loading
@@ -12,6 +12,7 @@
#import "DebugLogging.h"
#import "iTermAdvancedSettingsModel.h"
#import "iTermTextExtractor.h"
#import "iTermURLStore.h"
#import "iTermSemanticHistoryController.h"
#import "NSCharacterSet+iTerm.h"
#import "NSStringITerm.h"
Loading
Loading
@@ -115,13 +116,18 @@
+ (URLAction *)urlActionForHypertextLinkAt:(VT100GridCoord)coord
extractor:(iTermTextExtractor *)extractor {
screen_char_t oc = [extractor characterAt:coord];
NSURL *url = [extractor urlOfHypertextLinkAt:coord];
NSString *urlId = nil;
NSURL *url = [extractor urlOfHypertextLinkAt:coord urlId:&urlId];
if (url != nil) {
URLAction *action = [URLAction urlActionToOpenURL:url.absoluteString];
action.hover = YES;
action.range = [extractor rangeOfCoordinatesAround:coord
maximumDistance:1000
passingTest:^BOOL(screen_char_t *c) {
passingTest:^BOOL(screen_char_t *c, VT100GridCoord coord) {
// For now a difference in URL code implies separate hovering.
// This could be because there's a different parameter--even an
// undefined one. Discussion here:
// https://bugzilla.gnome.org/show_bug.cgi?id=779734
return (c->urlCode == oc.urlCode);
}];
return action;
Loading
Loading
Loading
Loading
@@ -11,8 +11,9 @@
@interface iTermURLStore : NSObject
 
+ (instancetype)sharedInstance;
- (unsigned short)codeForURL:(NSURL *)url;
- (unsigned short)codeForURL:(NSURL *)url withParams:(NSString *)params;
- (NSURL *)urlForCode:(unsigned short)code;
- (NSString *)paramWithKey:(NSString *)key forCode:(unsigned short)code;
 
- (NSDictionary *)dictionaryValue;
- (void)loadFromDictionary:(NSDictionary *)dictionary;
Loading
Loading
Loading
Loading
@@ -11,11 +11,11 @@
#import "DebugLogging.h"
 
@implementation iTermURLStore {
// NSURL.absoluteString -> @(NSInteger)
NSMutableDictionary<NSString *, NSNumber *> *_store;
// { "url": NSURL.absoluteString, "params": NSString } -> @(NSInteger)
NSMutableDictionary<NSDictionary *, NSNumber *> *_store;
 
// @(unsigned short) -> NSURL
NSMutableDictionary<NSNumber *, NSURL *> *_reverseStore;
// @(unsigned short) -> { "url": NSURL, "params": NSString }
NSMutableDictionary<NSNumber *, NSDictionary *> *_reverseStore;
 
// Internally, the code is stored as a 64-bit integer so we don't have to think about overflow.
// The value that's exported is truncated to 16 bits and will never equal zero.
Loading
Loading
@@ -44,16 +44,23 @@
return self;
}
 
- (unsigned short)codeForURL:(NSURL *)url {
NSString *key = url.absoluteString;
- (unsigned short)codeForURL:(NSURL *)url withParams:(NSString *)params {
NSDictionary *key = @{ @"url": url.absoluteString, @"params": params };
NSNumber *number = _store[key];
unsigned short truncatedCode;
if (number == nil) {
if (_reverseStore.count == USHRT_MAX - 1) {
DLog(@"Ran out of URL storage. Refusing to allocate a code.");
return 0;
}
while (_reverseStore[@(_nextCode)]) {
_nextCode++;
}
number = @(_nextCode);
_nextCode++;
_store[key] = number;
truncatedCode = [iTermURLStore truncatedCodeForCode:number.integerValue];
_reverseStore[@(truncatedCode)] = url;
_reverseStore[@(truncatedCode)] = @{ @"url": url, @"params": params };
return truncatedCode;
} else {
return [iTermURLStore truncatedCodeForCode:number.integerValue];
Loading
Loading
@@ -65,7 +72,34 @@
// Safety valve in case something goes awry. There should never be an entry at 0.
return nil;
}
return _reverseStore[@(code)];
return _reverseStore[@(code)][@"url"];
}
- (NSString *)paramsForCode:(unsigned short)code {
if (code == 0) {
// Safety valve in case something goes awry. There should never be an entry at 0.
return nil;
}
return _reverseStore[@(code)][@"params"];
}
- (NSString *)paramWithKey:(NSString *)key forCode:(unsigned short)code {
NSString *params = [self paramsForCode:code];
if (!params) {
return nil;
}
NSArray<NSString *> *parts = [params componentsSeparatedByString:@" "];
for (NSString *part in parts) {
NSInteger i = [part rangeOfString:@"="].location;
if (i != NSNotFound) {
NSString *partKey = [part substringToIndex:i];
if ([partKey isEqualToString:key]) {
return [part substringFromIndex:i + 1];
}
}
}
return nil;
}
 
- (NSDictionary *)dictionaryValue {
Loading
Loading
@@ -73,13 +107,13 @@
}
 
- (void)loadFromDictionary:(NSDictionary *)dictionary {
[dictionary enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) {
if (![key isKindOfClass:[NSString class]] ||
[dictionary enumerateKeysAndObjectsUsingBlock:^(NSDictionary * _Nonnull key, NSNumber * _Nonnull obj, BOOL * _Nonnull stop) {
if (![key isKindOfClass:[NSDictionary class]] ||
![obj isKindOfClass:[NSNumber class]]) {
ELog(@"Unexpected types when loading dictionary: %@ -> %@", key.class, obj.class);
return;
}
NSURL *url = [NSURL URLWithString:key];
NSURL *url = [NSURL URLWithString:key[@"url"]];
if (url == nil) {
XLog(@"Bogus key not a URL: %@", url);
return;
Loading
Loading
@@ -87,7 +121,7 @@
_store[key] = obj;
 
unsigned short truncated = [iTermURLStore truncatedCodeForCode:obj.integerValue];
_reverseStore[@(truncated)] = url;
_reverseStore[@(truncated)] = @{ @"url": url, @"params": key[@"params"] ?: @"" };
_nextCode = MAX(_nextCode, obj.integerValue + 1);
}];
}
Loading
Loading
This test originally by Egmont Koblinger. Copied with permission, per https://gitlab.com/gnachman/iterm2/issues/5158#note_25843049
 
Tests for ]8;https://bugzilla.gnome.org/show_bug.cgi?id=779734gnome-terminal #779734]8; and ]8;https://gitlab.com/gnachman/iterm2/issues/5158iTerm2 #5158]8;
Tests for ]8;;https://bugzilla.gnome.org/show_bug.cgi?id=779734gnome-terminal #779734]8;; and ]8;;https://gitlab.com/gnachman/iterm2/issues/5158iTerm2 #5158]8;;
═════════════════════════════════════════════════
 
commit ]8;https://git.gnome.org/browse/vte/commit/?id=a9b0b4c75a6dc7282f7cfcaef71413d69f7f0731a9b0b4c75a6dc7282f7cfcaef71413d69f7f0731]8;
Author: Egmont Koblinger <]8;mailto:egmont@gmail.comegmont@gmail.com]8;>
commit ]8;;https://git.gnome.org/browse/vte/commit/?id=a9b0b4c75a6dc7282f7cfcaef71413d69f7f0731a9b0b4c75a6dc7282f7cfcaef71413d69f7f0731]8;;
Author: Egmont Koblinger <]8;;mailto:egmont@gmail.comegmont@gmail.com]8;;>
Date: Sat Oct 24 00:12:22 2015 +0200
 
widget: Implement smooth scrolling
]8;https://bugzilla.gnome.org/show_bug.cgi?id=746690Bug #746690]8;
]8;;https://bugzilla.gnome.org/show_bug.cgi?id=746690Bug #746690]8;;
 
commit ]8;https://git.gnome.org/browse/vte/commit/?id=6a74baeaabb0a1ce54444611b324338f94721a5c6a74baeaabb0a1ce54444611b324338f94721a5c]8;
Merge: ]8;https://git.gnome.org/browse/vte/commit/?id=3fac4463fac446]8; ]8;https://git.gnome.org/browse/vte/commit/?id=56ea58156ea581]8;
Author: Christian Persch <]8;mailto:chpe@gnome.orgchpe@gnome.org]8;>
commit ]8;;https://git.gnome.org/browse/vte/commit/?id=6a74baeaabb0a1ce54444611b324338f94721a5c6a74baeaabb0a1ce54444611b324338f94721a5c]8;;
Merge: ]8;;https://git.gnome.org/browse/vte/commit/?id=3fac4463fac446]8;; ]8;;https://git.gnome.org/browse/vte/commit/?id=56ea58156ea581]8;;
Author: Christian Persch <]8;;mailto:chpe@gnome.orgchpe@gnome.org]8;;>
Date: Mon Apr 27 13:48:52 2015 +0200
 
Merge branch 'work-html' into merge-html
 
]8;file:///var/lib/gconf/defaults/%25gconf-tree.xmlA file with a % sign in its name (escaped as %25)]8;
]8;;file:///var/lib/gconf/defaults/%25gconf-tree.xmlA file with a % sign in its name (escaped as %25)]8;;
 
]8;https://en.wikipedia.org/wiki/ÁWiki page of Á (unescaped raw UTF-8)]8;
]8;https://en.wikipedia.org/wiki/%C3%81Wiki page of Á (escaped as %C3%81)]8;
]8;https://en.wikipedia.org/wiki/%25Wiki page of % (escaped as %25)]8;
]8;;https://en.wikipedia.org/wiki/ÁWiki page of Á (unescaped raw UTF-8)]8;;
]8;;https://en.wikipedia.org/wiki/%C3%81Wiki page of Á (escaped as %C3%81)]8;;
]8;;https://en.wikipedia.org/wiki/%25Wiki page of % (escaped as %25)]8;;
 
Two adjacent links pointing to the same URL: ]8;http://example.com/foofoo]8;]8;http://example.com/foofoo]8;
Two adjacent links pointing to different URLs: ]8;http://example.com/foofoo]8;]8;http://example.com/barbar]8;
Two adjacent links pointing to the same URL: ]8;;http://example.com/foofoo]8;;]8;;http://example.com/foofoo]8;;
Two adjacent links pointing to different URLs: ]8;;http://example.com/foofoo]8;;]8;;http://example.com/barbar]8;;
 
The same two without closing the first link: ]8;http://example.com/foofoo]8;http://example.com/foofoo]8; ]8;http://example.com/foofoo]8;http://example.com/barbar]8;
The same two without closing the first link: ]8;;http://example.com/foofoo]8;;http://example.com/foofoo]8;; ]8;;http://example.com/foofoo]8;;http://example.com/barbar]8;;
 
A URL wrapping to the next line, and a trailing whitespace: ]8;http://example.com/foobarfoo
bar ]8;
A URL wrapping to the next line, and a trailing whitespace: ]8;;http://example.com/foobarfoo
bar ]8;;
 
]8;http://example.com/colorsMulti-colour link also tests that "\e[m" or "\e[0m" does not terminate the link]8;
]8;;http://example.com/colorsMulti-colour link also tests that "\e[m" or "\e[0m" does not terminate the link]8;;
 
Soft reset "\e[!p" resets attributes and terminates link: ]8;http://example.com/softresetfoo[!pbar
Soft reset "\e[!p" resets attributes and terminates link: ]8;;http://example.com/softresetfoo[!pbar
 
(Introducing the "under_score" character for even more fun)
 
Explicit and implicit link: ]8;http://example.com/under_scorehttp://example.com/under_score]8;
Explicit and implicit link with different targets: ]8;http://example.com/explicit_under_scorehttp://example.com/implicit_under_score]8;
Explicit and implicit link, broken into two lines: ]8;http://example.com/under_scorehttp://examp
le.com/under_score]8;
Explicit and implicit link: ]8;;http://example.com/under_scorehttp://example.com/under_score]8;;
Explicit and implicit link with different targets: ]8;;http://example.com/explicit_under_scorehttp://example.com/implicit_under_score]8;;
Explicit and implicit link, broken into two lines: ]8;;http://example.com/under_scorehttp://examp
le.com/under_score]8;;
 
Explicitly underlined links ("\e[4m"):
Explicit link only: ]8;http://example.com/under_scoreI'm an explicit link with under_score]8;
Explicit link only: ]8;;http://example.com/under_scoreI'm an explicit link with under_score]8;;
Implicit link only: http://example.com/under_score
Both: ]8;http://example.com/under_scorehttp://example.com/under_score]8;
Both: ]8;;http://example.com/under_scorehttp://example.com/under_score]8;;
 
Conflicting explicit and implicit links: http://example.com/foobar-]8;http://example.com/explicitexplicit]8;-rest
Conflicting explicit and implicit links: http://example.com/foobar-]8;;http://example.com/explicitexplicit]8;;-rest
 
Invisible explicit and implicit link: ]8;http://example.com/invisibleCan you see me?]8; http://example.com/and_how_about_me
Invisible explicit and implicit link: ]8;;http://example.com/invisibleCan you see me?]8;; http://example.com/and_how_about_me
 
]8;asdfghjklExplicit link with stupid target]8;
]8;;asdfghjklExplicit link with stupid target]8;;
 
]8;http://example.com/.........30........40........50........60........70........80........90.......100.......110.......120.......130.......140.......150.......160.......170.......180.......190.......200.......210.......220.......230.......240.......250.....URL of 255 chars]8;
]8;http://example.com/.........30........40........50........60........70........80........90.......100.......110.......120.......130.......140.......150.......160.......170.......180.......190.......200.......210.......220.......230.......240.......250......URL of 256 chars]8;
]8;http://example.com/.........30........40........50........60........70........80........90.......100.......110.......120.......130.......140.......150.......160.......170.......180.......190.......200.......210.......220.......230.......240.......250.......260.......270.......280.......290.......300.......310.......320.......330.......340.......350.......360.......370.......380.......390.......400.......410.......420.......430.......440.......450.......460.......470.......480.......490.......500.......510.......520.......530.......540.......550.......560.......570.......580.......590.......600.......610.......620.......630.......640.......650.......660.......670.......680.......690.......700.......710.......720.......730.......740.......750.......760.......770.......780.......790.......800.......810.......820.......830.......840.......850.......860.......870.......880.......890.......900.......910.......920.......930.......940.......950.......960.......970.......980.......990......1000......1010......1020......1030......1040......1050......1060......1070......1080......1090......1100......1110......1120......1130......1140......1150......1160......1170......1180......1190......1200......1210......1220......1230......1240......1250......1260......1270......1280......1290......1300......1310......1320......1330......1340......1350......1360......1370......1380......1390......1400......1410......1420......1430......1440......1450......1460......1470......1480......1490......1500......1510......1520......1530......1540......1550......1560......1570......1580......1590......1600......1610......1620......1630......1640......1650......1660......1670......1680......1690......1700......1710......1720......1730......1740......1750......1760......1770......1780......1790......1800......1810......1820......1830......1840......1850......1860......1870......1880......1890......1900......1910......1920......1930......1940......1950......1960......1970......1980......1990......2000......2010......2020......2030......2040......2050......2060......2070......2080...URL of 2083 chars]8;
]8;http://example.com/.........30........40........50........60........70........80........90.......100.......110.......120.......130.......140.......150.......160.......170.......180.......190.......200.......210.......220.......230.......240.......250.......260.......270.......280.......290.......300.......310.......320.......330.......340.......350.......360.......370.......380.......390.......400.......410.......420.......430.......440.......450.......460.......470.......480.......490.......500.......510.......520.......530.......540.......550.......560.......570.......580.......590.......600.......610.......620.......630.......640.......650.......660.......670.......680.......690.......700.......710.......720.......730.......740.......750.......760.......770.......780.......790.......800.......810.......820.......830.......840.......850.......860.......870.......880.......890.......900.......910.......920.......930.......940.......950.......960.......970.......980.......990......1000......1010......1020......1030......1040......1050......1060......1070......1080......1090......1100......1110......1120......1130......1140......1150......1160......1170......1180......1190......1200......1210......1220......1230......1240......1250......1260......1270......1280......1290......1300......1310......1320......1330......1340......1350......1360......1370......1380......1390......1400......1410......1420......1430......1440......1450......1460......1470......1480......1490......1500......1510......1520......1530......1540......1550......1560......1570......1580......1590......1600......1610......1620......1630......1640......1650......1660......1670......1680......1690......1700......1710......1720......1730......1740......1750......1760......1770......1780......1790......1800......1810......1820......1830......1840......1850......1860......1870......1880......1890......1900......1910......1920......1930......1940......1950......1960......1970......1980......1990......2000......2010......2020......2030......2040......2050......2060......2070......2080....URL of 2084 chars]8;
]8;;http://example.com/.........30........40........50........60........70........80........90.......100.......110.......120.......130.......140.......150.......160.......170.......180.......190.......200.......210.......220.......230.......240.......250.....URL of 255 chars]8;;
]8;;http://example.com/.........30........40........50........60........70........80........90.......100.......110.......120.......130.......140.......150.......160.......170.......180.......190.......200.......210.......220.......230.......240.......250......URL of 256 chars]8;;
]8;;http://example.com/.........30........40........50........60........70........80........90.......100.......110.......120.......130.......140.......150.......160.......170.......180.......190.......200.......210.......220.......230.......240.......250.......260.......270.......280.......290.......300.......310.......320.......330.......340.......350.......360.......370.......380.......390.......400.......410.......420.......430.......440.......450.......460.......470.......480.......490.......500.......510.......520.......530.......540.......550.......560.......570.......580.......590.......600.......610.......620.......630.......640.......650.......660.......670.......680.......690.......700.......710.......720.......730.......740.......750.......760.......770.......780.......790.......800.......810.......820.......830.......840.......850.......860.......870.......880.......890.......900.......910.......920.......930.......940.......950.......960.......970.......980.......990......1000......1010......1020......1030......1040......1050......1060......1070......1080......1090......1100......1110......1120......1130......1140......1150......1160......1170......1180......1190......1200......1210......1220......1230......1240......1250......1260......1270......1280......1290......1300......1310......1320......1330......1340......1350......1360......1370......1380......1390......1400......1410......1420......1430......1440......1450......1460......1470......1480......1490......1500......1510......1520......1530......1540......1550......1560......1570......1580......1590......1600......1610......1620......1630......1640......1650......1660......1670......1680......1690......1700......1710......1720......1730......1740......1750......1760......1770......1780......1790......1800......1810......1820......1830......1840......1850......1860......1870......1880......1890......1900......1910......1920......1930......1940......1950......1960......1970......1980......1990......2000......2010......2020......2030......2040......2050......2060......2070......2080...URL of 2083 chars]8;;
]8;;http://example.com/.........30........40........50........60........70........80........90.......100.......110.......120.......130.......140.......150.......160.......170.......180.......190.......200.......210.......220.......230.......240.......250.......260.......270.......280.......290.......300.......310.......320.......330.......340.......350.......360.......370.......380.......390.......400.......410.......420.......430.......440.......450.......460.......470.......480.......490.......500.......510.......520.......530.......540.......550.......560.......570.......580.......590.......600.......610.......620.......630.......640.......650.......660.......670.......680.......690.......700.......710.......720.......730.......740.......750.......760.......770.......780.......790.......800.......810.......820.......830.......840.......850.......860.......870.......880.......890.......900.......910.......920.......930.......940.......950.......960.......970.......980.......990......1000......1010......1020......1030......1040......1050......1060......1070......1080......1090......1100......1110......1120......1130......1140......1150......1160......1170......1180......1190......1200......1210......1220......1230......1240......1250......1260......1270......1280......1290......1300......1310......1320......1330......1340......1350......1360......1370......1380......1390......1400......1410......1420......1430......1440......1450......1460......1470......1480......1490......1500......1510......1520......1530......1540......1550......1560......1570......1580......1590......1600......1610......1620......1630......1640......1650......1660......1670......1680......1690......1700......1710......1720......1730......1740......1750......1760......1770......1780......1790......1800......1810......1820......1830......1840......1850......1860......1870......1880......1890......1900......1910......1920......1930......1940......1950......1960......1970......1980......1990......2000......2010......2020......2030......2040......2050......2060......2070......2080....URL of 2084 chars]8;;
The following three links have the same target. The first two should highlight together.
]8;id=id1;http://example.com/<Some text with id=id1>]8;;]8;id=id1;http://example.com/]8;id=id1;http://example.com/<More text with id=id1>]8;;]8;id=id2;http://example.com/<Some text with id=id2>]8;;
The following links have the same target, same ID, but different spam parameters. spam is not defined.
]8;spam=id1;http://example.com/<Some text with spam=id1>]8;;]8;spam=id1;http://example.com/]8;spam=id1;http://example.com/<More text with spam=id1>]8;;]8;spam=id2;http://example.com/<Some text with spam=id2>]8;;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment