Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>HLDiff</title>
- <style type="text/css">
- :root {
- --add-color: rgba(124, 252, 0, 0.5);
- --move-color: rgba(100, 149, 237, 0.5);
- --update-color: rgba(244, 164, 96, 0.5);
- --delete-color: rgba(255, 0, 0, 0.5);
- --line-color: rgb(0, 0, 0);
- }
- .wrapper {
- display: grid;
- grid-template-columns: 40% 20% 40%;
- }
- .code {
- border: 1px solid black;
- }
- figure {
- margin-inline-start: 5pt;
- margin-inline-end: 5pt;
- }
- code {
- display: block;
- white-space: pre-wrap;
- word-break: break-all;
- }
- .added {
- background-color: var(--add-color);
- }
- .removed {
- background-color: red;
- }
- .moved {
- background-color: var(--move-color);
- }
- .updated {
- background-color: var(--update-color);
- }
- .diff {
- position: relative;
- }
- .change {
- position: absolute;
- width: calc(100% - 20pt);
- padding: 10pt;
- display: block;
- }
- .change-addition {
- border: 2px solid var(--add-color);
- background-color: #7CFC0033;
- }
- .change-addition:hover {
- background-color: #7CFC00AA;
- }
- .change-move {
- border: 2px solid var(--move-color);
- background-color: #6495ED33;
- }
- .change-move:hover {
- background-color: #6495EDAA;
- }
- .change-update {
- border: 2px solid var(--update-color);
- background-color: #F4A46033;
- }
- .change-update:hover {
- background-color: #F4A460AA;
- }
- .change-delete {
- border: 2px solid var(--delete-color);
- background-color: #FF000033;
- }
- .change-delete:hover {
- background-color: #FF0000AA;
- }
- .svg {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100000pt;
- }
- .line {
- z-index: 100;
- stroke-width: 3px;
- stroke: var(--line-color);
- }
- svg {
- pointer-events: none;
- }
- svg * {
- pointer-events: all;
- }
- </style>
- </head>
- <body>
- <h1>Diff of 2 files</h1>
- <svg id="svg" class="svg" xmlns="http://www.w3.org/2000/svg">
- <line id="line" class="line"></line>
- </svg>
- <svg id="svg2" class="svg" xmlns="http://www.w3.org/2000/svg">
- <line id="line2" class="line"></line>
- </svg>
- <div class="wrapper">
- <figure class="code">
- <figcaption>Before:</figcaption>
- <code>
- /*
- * Copyright 2002-2019 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.springframework.http.codec.json;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.function.Function;
- import com.fasterxml.jackson.core.JsonFactory;
- import com.fasterxml.jackson.core.JsonParser;
- import com.fasterxml.jackson.core.JsonProcessingException;
- import com.fasterxml.jackson.core.JsonToken;
- import com.fasterxml.jackson.core.async.ByteArrayFeeder;
- import com.fasterxml.jackson.databind.DeserializationContext;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.fasterxml.jackson.databind.deser.DefaultDeserializationContext;
- import com.fasterxml.jackson.databind.util.TokenBuffer;
- import reactor.core.Exceptions;
- import reactor.core.publisher.Flux;
- import org.springframework.core.codec.DecodingException;
- import org.springframework.core.io.buffer.DataBuffer;
- import org.springframework.core.io.buffer.DataBufferLimitException;
- import org.springframework.core.io.buffer.DataBufferUtils;
- /**
- * {@link Function} to transform a JSON stream of arbitrary size, byte array
- * chunks into a {@code Flux<TokenBuffer>} where each token buffer is a
- * well-formed JSON object.
- *
- * @author Arjen Poutsma
- * @author Rossen Stoyanchev
- * @author Juergen Hoeller
- * @since 5.0
- */
- final class Jackson2Tokenizer {
- private final JsonParser parser;
- private final DeserializationContext deserializationContext;
- private final boolean tokenizeArrayElements;
- <span class="changed-code moved code-change-0">private TokenBuffer tokenBuffer;</span>
- private int objectDepth;
- private int arrayDepth;
- <span class="changed-code moved code-change-1">private final int maxInMemorySize;</span>
- private int byteCount;
- // TODO: change to ByteBufferFeeder when supported by Jackson
- // See https://github.com/FasterXML/jackson-core/issues/478
- private final ByteArrayFeeder inputFeeder;
- private Jackson2Tokenizer(JsonParser parser, DeserializationContext deserializationContext,
- boolean tokenizeArrayElements, int maxInMemorySize) {
- this.parser = parser;
- this.deserializationContext = deserializationContext;
- this.tokenizeArrayElements = tokenizeArrayElements;
- <span class="changed-code moved code-change-3"><span class="changed-code updated code-change-19">this.tokenBuffer</span> = <span class="changed-code removed code-change-15">new TokenBuffer(parser, deserializationContext)</span></span>;
- this.inputFeeder = (ByteArrayFeeder) this.parser.getNonBlockingInputFeeder();
- this.maxInMemorySize = maxInMemorySize;
- }
- private List<TokenBuffer> tokenize(DataBuffer dataBuffer) {
- int bufferSize = dataBuffer.readableByteCount();
- byte[] bytes = new byte[bufferSize];
- dataBuffer.read(bytes);
- DataBufferUtils.release(dataBuffer);
- try {
- this.inputFeeder.feedInput(bytes, 0, bytes.length);
- List<TokenBuffer> result = parseTokenBufferFlux();
- assertInMemorySize(bufferSize, result);
- return result;
- }
- catch (JsonProcessingException ex) {
- throw new DecodingException("JSON decoding error: " + ex.getOriginalMessage(), ex);
- }
- catch (IOException ex) {
- throw Exceptions.propagate(ex);
- }
- }
- private Flux<TokenBuffer> endOfInput() {
- return Flux.defer(() -> {
- this.inputFeeder.endOfInput();
- try {
- return Flux.fromIterable(parseTokenBufferFlux());
- }
- catch (JsonProcessingException ex) {
- throw new DecodingException("JSON decoding error: " + ex.getOriginalMessage(), ex);
- }
- catch (IOException ex) {
- throw Exceptions.propagate(ex);
- }
- });
- }
- private List<TokenBuffer> parseTokenBufferFlux() throws IOException {
- List<TokenBuffer> result = new ArrayList<>();
- // SPR-16151: Smile data format uses null to separate documents
- boolean previousNull = false;
- while (!this.parser.isClosed()) {
- JsonToken token = this.parser.nextToken();
- if (token == JsonToken.NOT_AVAILABLE ||
- token == null && previousNull) {
- break;
- }
- else if (token == null ) { // !previousNull
- previousNull = true;
- continue;
- }
- updateDepth(token);
- if (!this.tokenizeArrayElements) {
- processTokenNormal(token, result);
- }
- else {
- processTokenArray(token, result);
- }
- }
- return result;
- }
- private void updateDepth(JsonToken token) {
- switch (token) {
- case START_OBJECT:
- this.objectDepth++;
- break;
- case END_OBJECT:
- this.objectDepth--;
- break;
- case START_ARRAY:
- this.arrayDepth++;
- break;
- case END_ARRAY:
- this.arrayDepth--;
- break;
- }
- }
- private void processTokenNormal(JsonToken token, List<TokenBuffer> result) throws IOException {
- this.tokenBuffer.copyCurrentEvent(this.parser);
- if ((token.isStructEnd() || token.isScalarValue()) && this.objectDepth == 0 && this.arrayDepth == 0) {
- result.add(this.tokenBuffer);
- <span class="changed-code removed code-change-17">this.tokenBuffer = new TokenBuffer(this.parser, this.deserializationContext)</span>;
- }
- }
- private void processTokenArray(JsonToken token, List<TokenBuffer> result) throws IOException {
- if (!isTopLevelArrayToken(token)) {
- this.tokenBuffer.copyCurrentEvent(this.parser);
- }
- if (this.objectDepth == 0 && (this.arrayDepth == 0 || this.arrayDepth == 1) &&
- (token == JsonToken.END_OBJECT || token.isScalarValue())) {
- result.add(this.tokenBuffer);
- <span class="changed-code moved code-change-2">this.tokenBuffer = new TokenBuffer(this.parser, this.deserializationContext);</span>
- }
- }
- private boolean isTopLevelArrayToken(JsonToken token) {
- return this.objectDepth == 0 && ((token == JsonToken.START_ARRAY && this.arrayDepth == 1) ||
- (token == JsonToken.END_ARRAY && this.arrayDepth == 0));
- }
- private void assertInMemorySize(int currentBufferSize, List<TokenBuffer> result) {
- if (this.maxInMemorySize >= 0) {
- if (!result.isEmpty()) {
- this.byteCount = 0;
- }
- else if (currentBufferSize > Integer.MAX_VALUE - this.byteCount) {
- raiseLimitException();
- }
- else {
- this.byteCount += currentBufferSize;
- if (this.byteCount > this.maxInMemorySize) {
- raiseLimitException();
- }
- }
- }
- }
- private void raiseLimitException() {
- throw new DataBufferLimitException(
- "Exceeded limit on max bytes per JSON object: " + this.maxInMemorySize);
- }
- /**
- * Tokenize the given {@code Flux<DataBuffer>} into {@code Flux<TokenBuffer>}.
- * @param dataBuffers the source data buffers
- * @param jsonFactory the factory to use
- * @param objectMapper the current mapper instance
- * @param tokenizeArrays if {@code true} and the "top level" JSON object is
- * an array, each element is returned individually immediately after it is received
- * @return the resulting token buffers
- */
- public static Flux<TokenBuffer> tokenize(Flux<DataBuffer> dataBuffers, JsonFactory jsonFactory,
- ObjectMapper objectMapper, boolean tokenizeArrays, int maxInMemorySize) {
- try {
- JsonParser parser = jsonFactory.createNonBlockingByteArrayParser();
- DeserializationContext context = objectMapper.getDeserializationContext();
- if (context instanceof DefaultDeserializationContext) {
- context = ((DefaultDeserializationContext) context).createInstance(
- objectMapper.getDeserializationConfig(), parser, objectMapper.getInjectableValues());
- }
- <span class="changed-code moved code-change-5">Jackson2Tokenizer</span> tokenizer = <span class="changed-code updated code-change-20">new <span class="changed-code moved code-change-4">Jackson2Tokenizer</span>(parser, context, tokenizeArrays, maxInMemorySize)</span>;
- return dataBuffers.concatMapIterable(tokenizer::tokenize).concatWith(tokenizer.endOfInput());
- }
- catch (IOException ex) {
- return Flux.error(ex);
- }
- }
- }
- </code>
- </figure>
- <div class="diff">
- <div class="change change-addition" id="code-change-6">Insert ImportDeclaration to CompilationUnit at position 11</div><div class="change change-addition" id="code-change-7">Insert ImportDeclaration to CompilationUnit at position 21</div><div class="change change-move" id="code-change-0">Move FieldDeclaration to TypeDeclaration at position 11</div><div class="change change-move" id="code-change-1">Move FieldDeclaration to TypeDeclaration at position 6</div><div class="change change-addition" id="code-change-8">Insert FieldDeclaration to TypeDeclaration at position 6</div><div class="change change-addition" id="code-change-10">Insert MarkerAnnotation to FieldDeclaration at position 0</div><div class="change change-move" id="code-change-3">Move FieldAccess to MethodInvocation at position 0</div><div class="change change-update" id="code-change-19">Update Assignment with
- INS FieldAccess to Assignment: = at 0
- INS SimpleName: forceUseOfBigDecimal to Assignment: = at 1
- INS ThisExpression to FieldAccess at 0
- INS SimpleName: forceUseOfBigDecimal to FieldAccess at 1
- </div><div class="change change-delete" id="code-change-15">Remove ClassInstanceCreation</div><div class="change change-addition" id="code-change-11">Insert SingleVariableDeclaration to MethodDeclaration at position 5</div><div class="change change-addition" id="code-change-12">Insert ExpressionStatement to Block at position 6</div><div class="change change-addition" id="code-change-18">Insert Block to IfStatement at position 2</div><div class="change change-delete" id="code-change-17">Remove Assignment</div><div class="change change-addition" id="code-change-16">Insert MethodInvocation to ExpressionStatement at position 0</div><div class="change change-move" id="code-change-2">Move ExpressionStatement to Block at position 0</div><div class="change change-addition" id="code-change-13">Insert ExpressionStatement to Block at position 1</div><div class="change change-addition" id="code-change-9">Insert MethodDeclaration Partial to TypeDeclaration at position 20</div><div class="change change-move" id="code-change-5">Move SimpleType to ClassInstanceCreation at position 0</div><div class="change change-update" id="code-change-20">Update ClassInstanceCreation with
- INS SimpleName: forceUseOfBigDecimal to ClassInstanceCreation at 4
- </div><div class="change change-move" id="code-change-4">Move SimpleType to VariableDeclarationStatement at position 0</div><div class="change change-addition" id="code-change-14">Insert VariableDeclarationStatement to Block at position 3</div>
- </div>
- <figure class="code">
- <figcaption>After:</figcaption>
- <code>
- /*
- * Copyright 2002-2020 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.springframework.http.codec.json;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.function.Function;
- import com.fasterxml.jackson.core.JsonFactory;
- import com.fasterxml.jackson.core.JsonParser;
- import com.fasterxml.jackson.core.JsonProcessingException;
- import com.fasterxml.jackson.core.JsonToken;
- import com.fasterxml.jackson.core.async.ByteArrayFeeder;
- import com.fasterxml.jackson.databind.DeserializationContext;
- <span class="changed-code added code-change-6">import com.fasterxml.jackson.databind.DeserializationFeature;</span>
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.fasterxml.jackson.databind.deser.DefaultDeserializationContext;
- import com.fasterxml.jackson.databind.util.TokenBuffer;
- import reactor.core.Exceptions;
- import reactor.core.publisher.Flux;
- import org.springframework.core.codec.DecodingException;
- import org.springframework.core.io.buffer.DataBuffer;
- import org.springframework.core.io.buffer.DataBufferLimitException;
- import org.springframework.core.io.buffer.DataBufferUtils;
- <span class="changed-code added code-change-7">import org.springframework.lang.Nullable;</span>
- /**
- * {@link Function} to transform a JSON stream of arbitrary size, byte array
- * chunks into a {@code Flux<TokenBuffer>} where each token buffer is a
- * well-formed JSON object.
- *
- * @author Arjen Poutsma
- * @author Rossen Stoyanchev
- * @author Juergen Hoeller
- * @since 5.0
- */
- final class Jackson2Tokenizer {
- private final JsonParser parser;
- private final DeserializationContext deserializationContext;
- private final boolean tokenizeArrayElements;
- <span class="changed-code added code-change-8">private final boolean forceUseOfBigDecimal;</span>
- <span class="changed-code moved code-change-1">private final int maxInMemorySize;</span>
- private int objectDepth;
- private int arrayDepth;
- private int byteCount;
- <span class="changed-code moved code-change-0"><span class="changed-code added code-change-10">@Nullable</span> // yet initialized by calling createToken() in the constructor
- private TokenBuffer tokenBuffer;</span>
- // TODO: change to ByteBufferFeeder when supported by Jackson
- // See https://github.com/FasterXML/jackson-core/issues/478
- private final ByteArrayFeeder inputFeeder;
- private Jackson2Tokenizer(JsonParser parser, DeserializationContext deserializationContext,
- boolean tokenizeArrayElements, <span class="changed-code added code-change-11">boolean forceUseOfBigDecimal</span>, int maxInMemorySize) {
- this.parser = parser;
- this.deserializationContext = deserializationContext;
- this.tokenizeArrayElements = tokenizeArrayElements;
- <span class="changed-code updated code-change-19">this.forceUseOfBigDecimal = forceUseOfBigDecimal</span>;
- this.inputFeeder = (ByteArrayFeeder) this.parser.getNonBlockingInputFeeder();
- this.maxInMemorySize = maxInMemorySize;
- <span class="changed-code added code-change-12">createToken();</span>
- }
- private List<TokenBuffer> tokenize(DataBuffer dataBuffer) {
- int bufferSize = dataBuffer.readableByteCount();
- byte[] bytes = new byte[bufferSize];
- dataBuffer.read(bytes);
- DataBufferUtils.release(dataBuffer);
- try {
- this.inputFeeder.feedInput(bytes, 0, bytes.length);
- List<TokenBuffer> result = parseTokenBufferFlux();
- assertInMemorySize(bufferSize, result);
- return result;
- }
- catch (JsonProcessingException ex) {
- throw new DecodingException("JSON decoding error: " + ex.getOriginalMessage(), ex);
- }
- catch (IOException ex) {
- throw Exceptions.propagate(ex);
- }
- }
- private Flux<TokenBuffer> endOfInput() {
- return Flux.defer(() -> {
- this.inputFeeder.endOfInput();
- try {
- return Flux.fromIterable(parseTokenBufferFlux());
- }
- catch (JsonProcessingException ex) {
- throw new DecodingException("JSON decoding error: " + ex.getOriginalMessage(), ex);
- }
- catch (IOException ex) {
- throw Exceptions.propagate(ex);
- }
- });
- }
- private List<TokenBuffer> parseTokenBufferFlux() throws IOException {
- List<TokenBuffer> result = new ArrayList<>();
- // SPR-16151: Smile data format uses null to separate documents
- boolean previousNull = false;
- while (!this.parser.isClosed()) {
- JsonToken token = this.parser.nextToken();
- if (token == JsonToken.NOT_AVAILABLE ||
- token == null && previousNull) {
- break;
- }
- else if (token == null ) { // !previousNull
- previousNull = true;
- continue;
- }
- else <span class="changed-code added code-change-18">{
- previousNull = false;
- }</span>
- updateDepth(token);
- if (!this.tokenizeArrayElements) {
- processTokenNormal(token, result);
- }
- else {
- processTokenArray(token, result);
- }
- }
- return result;
- }
- private void updateDepth(JsonToken token) {
- switch (token) {
- case START_OBJECT:
- this.objectDepth++;
- break;
- case END_OBJECT:
- this.objectDepth--;
- break;
- case START_ARRAY:
- this.arrayDepth++;
- break;
- case END_ARRAY:
- this.arrayDepth--;
- break;
- }
- }
- private void processTokenNormal(JsonToken token, List<TokenBuffer> result) throws IOException {
- this.tokenBuffer.copyCurrentEvent(this.parser);
- if ((token.isStructEnd() || token.isScalarValue()) && this.objectDepth == 0 && this.arrayDepth == 0) {
- result.add(this.tokenBuffer);
- <span class="changed-code added code-change-16">createToken()</span>;
- }
- }
- private void processTokenArray(JsonToken token, List<TokenBuffer> result) throws IOException {
- if (!isTopLevelArrayToken(token)) {
- this.tokenBuffer.copyCurrentEvent(this.parser);
- }
- if (this.objectDepth == 0 && (this.arrayDepth == 0 || this.arrayDepth == 1) &&
- (token == JsonToken.END_OBJECT || token.isScalarValue())) {
- result.add(this.tokenBuffer);
- <span class="changed-code added code-change-13">createToken();</span>
- }
- }
- <span class="changed-code added code-change-9">private void createToken() {
- <span class="changed-code moved code-change-2">this.tokenBuffer = new TokenBuffer(this.parser, this.deserializationContext);</span>
- <span class="changed-code moved code-change-3">this.tokenBuffer</span>.forceUseOfBigDecimal(this.forceUseOfBigDecimal);
- }</span>
- private boolean isTopLevelArrayToken(JsonToken token) {
- return this.objectDepth == 0 && ((token == JsonToken.START_ARRAY && this.arrayDepth == 1) ||
- (token == JsonToken.END_ARRAY && this.arrayDepth == 0));
- }
- private void assertInMemorySize(int currentBufferSize, List<TokenBuffer> result) {
- if (this.maxInMemorySize >= 0) {
- if (!result.isEmpty()) {
- this.byteCount = 0;
- }
- else if (currentBufferSize > Integer.MAX_VALUE - this.byteCount) {
- raiseLimitException();
- }
- else {
- this.byteCount += currentBufferSize;
- if (this.byteCount > this.maxInMemorySize) {
- raiseLimitException();
- }
- }
- }
- }
- private void raiseLimitException() {
- throw new DataBufferLimitException(
- "Exceeded limit on max bytes per JSON object: " + this.maxInMemorySize);
- }
- /**
- * Tokenize the given {@code Flux<DataBuffer>} into {@code Flux<TokenBuffer>}.
- * @param dataBuffers the source data buffers
- * @param jsonFactory the factory to use
- * @param objectMapper the current mapper instance
- * @param tokenizeArrays if {@code true} and the "top level" JSON object is
- * an array, each element is returned individually immediately after it is received
- * @return the resulting token buffers
- */
- public static Flux<TokenBuffer> tokenize(Flux<DataBuffer> dataBuffers, JsonFactory jsonFactory,
- ObjectMapper objectMapper, boolean tokenizeArrays, int maxInMemorySize) {
- try {
- JsonParser parser = jsonFactory.createNonBlockingByteArrayParser();
- DeserializationContext context = objectMapper.getDeserializationContext();
- if (context instanceof DefaultDeserializationContext) {
- context = ((DefaultDeserializationContext) context).createInstance(
- objectMapper.getDeserializationConfig(), parser, objectMapper.getInjectableValues());
- }
- <span class="changed-code added code-change-14">boolean forceUseOfBigDecimal = objectMapper.isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);</span>
- <span class="changed-code moved code-change-4">Jackson2Tokenizer</span> tokenizer = <span class="changed-code updated code-change-20">new <span class="changed-code moved code-change-5">Jackson2Tokenizer</span>(parser, context, tokenizeArrays, forceUseOfBigDecimal,
- maxInMemorySize)</span>;
- return dataBuffers.concatMapIterable(tokenizer::tokenize).concatWith(tokenizer.endOfInput());
- }
- catch (IOException ex) {
- return Flux.error(ex);
- }
- }
- }
- </code>
- </figure>
- </div>
- <script type="text/javascript">
- function drawLine(start, end, line, color = 'rgb(0, 0, 0)') {
- let x1 = start.getBoundingClientRect().left;
- let y1 = start.offsetTop + start.getBoundingClientRect().height / 2;
- let x2 = end.getBoundingClientRect().left;
- let y2 = end.getBoundingClientRect().top + window.scrollY + end.clientHeight / 2;
- if (x1 < x2) { // code is to the left
- x1 += start.getBoundingClientRect().width;
- } else {
- x2 += end.clientWidth;
- }
- document.documentElement.style.setProperty('--line-color', setAlpha(color, 1));
- line.setAttribute('x1', x1);
- line.setAttribute('y1', y1);
- line.setAttribute('x2', x2);
- line.setAttribute('y2', y2);
- }
- function setChangedCodeListeners(changedCode, line) {
- for (let elem of changedCode) {
- elem.addEventListener('mouseenter', function () {
- let changeId = elem.className.split(' ').find((v) => v.startsWith('code-change-'));
- const start = elem;
- const end = document.getElementById(changeId);
- console.log(start);
- drawLine(start, end, line);
- });
- console.log(elem.offsetTop)
- }
- }
- function setAlpha(rgba, alpha) {
- console.log(rgba);
- if (rgba.startsWith('rgba')) {
- return rgba.replace(/ ([^ ]*)\)/, alpha);
- } else {
- return rgba.replace('rgb', 'rgba').replace(/(\))/, ', ' + alpha + ')');
- }
- }
- function setChangesListListeners(changesList, line, line2) {
- for (let elem of changesList) {
- let codeChanges = document.getElementsByClassName(elem.id);
- elem.addEventListener('mouseenter', function () {
- for (let change of codeChanges) {
- console.log("Enter", change.style.backgroundColor);
- change.style.backgroundColor = setAlpha(document.defaultView.getComputedStyle(change, null)['background-color'], 1);
- }
- if (elem.className.includes('change-addition')) {
- drawLine(codeChanges[0], elem, line, 'var(--add-color)');
- } else if (elem.className.includes('change-move')) {
- drawLine(codeChanges[0], elem, line, 'var(--move-color)');
- drawLine(codeChanges[1], elem, line2, 'var(--move-color)');
- } else if (elem.className.includes('change-delete')) {
- drawLine(codeChanges[0], elem, line, 'var(--delete-color)');
- } else if (elem.className.includes('change-update')) {
- drawLine(codeChanges[0], elem, line, 'var(--update-color)');
- drawLine(codeChanges[1], elem, line2, 'var(--update-color)');
- }
- });
- elem.addEventListener('mouseout', function () {
- for (let change of codeChanges) {
- line.setAttribute('x1', 0);
- line.setAttribute('y1', 0);
- line.setAttribute('x2', 0);
- line.setAttribute('y2', 0);
- line2.setAttribute('x1', 0);
- line2.setAttribute('y1', 0);
- line2.setAttribute('x2', 0);
- line2.setAttribute('y2', 0);
- console.log("Exit", change.style.backgroundColor);
- change.style.backgroundColor = setAlpha(document.defaultView.getComputedStyle(change, null)['background-color'], 0.3);
- }
- });
- }
- }
- function positionChanges(changes, changedCode) {
- const diffContainer = document.getElementsByClassName('diff')[0];
- const codeChange = document.getElementsByClassName(changes[0].id)[0];
- changes[0].style.top = (codeChange.offsetTop - diffContainer.offsetTop) + 'px';
- for (let i = 1; i < changes.length; i++) {
- const codeChange = document.getElementsByClassName(changes[i].id)[0];
- console.log(codeChange.offsetTop + " positioning");
- changes[i].style.top = Math.max(codeChange.offsetTop - diffContainer.offsetTop, changes[i - 1].offsetTop + changes[i - 1].offsetHeight + 10) + 'px';
- }
- }
- const changedCode = document.getElementsByClassName('changed-code');
- const changesList = document.getElementsByClassName('change');
- console.log(changedCode.length);
- const line = document.getElementById('line');
- const line2 = document.getElementById('line2');
- positionChanges(changesList, changedCode);
- setChangedCodeListeners(changedCode, line);
- setChangesListListeners(changesList, line, line2);
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement